From e1b98ce5b5d729fe5972555fb249561cda63a8e6 Mon Sep 17 00:00:00 2001 From: joshua Date: Mon, 1 Feb 2021 19:52:15 +0100 Subject: [PATCH] Revert "QetElementEditor : rewrite gui with ui file" This reverts commit e3db2bc898c1479566dd1202c196fb3890d9e797. --- .../elementscollectionwidget.cpp | 5 +- sources/editor/elementitemeditor.cpp | 2 +- sources/editor/elementscene.cpp | 2 +- sources/editor/elementview.cpp | 2 +- sources/editor/esevent/eseventaddline.cpp | 2 +- sources/editor/esevent/eseventinterface.cpp | 19 +- .../editor/graphicspart/customelementpart.cpp | 3 +- sources/editor/graphicspart/partpolygon.cpp | 2 +- sources/editor/qetelementeditor.cpp | 1734 +++++++++++++++++ sources/editor/qetelementeditor.h | 189 ++ sources/editor/ui/dynamictextfieldeditor.cpp | 3 +- sources/editor/ui/qetelementeditor.cpp | 1480 -------------- sources/editor/ui/qetelementeditor.h | 163 -- sources/editor/ui/qetelementeditor.ui | 496 ----- sources/elementspanelwidget.cpp | 2 +- sources/newelementwizard.cpp | 6 +- sources/projectview.cpp | 2 +- sources/qetapp.cpp | 2 +- 18 files changed, 1944 insertions(+), 2170 deletions(-) create mode 100644 sources/editor/qetelementeditor.cpp create mode 100644 sources/editor/qetelementeditor.h delete mode 100644 sources/editor/ui/qetelementeditor.cpp delete mode 100644 sources/editor/ui/qetelementeditor.h delete mode 100644 sources/editor/ui/qetelementeditor.ui diff --git a/sources/ElementsCollection/elementscollectionwidget.cpp b/sources/ElementsCollection/elementscollectionwidget.cpp index 4777a5ffc..4dbbfb50b 100644 --- a/sources/ElementsCollection/elementscollectionwidget.cpp +++ b/sources/ElementsCollection/elementscollectionwidget.cpp @@ -17,7 +17,7 @@ */ #include "elementscollectionwidget.h" -#include "../editor/ui/qetelementeditor.h" +#include "../editor/qetelementeditor.h" #include "../elementscategoryeditor.h" #include "../newelementwizard.h" #include "../qetapp.h" @@ -38,9 +38,6 @@ #include #include #include -#include -#include -#include /** @brief ElementsCollectionWidget::ElementsCollectionWidget diff --git a/sources/editor/elementitemeditor.cpp b/sources/editor/elementitemeditor.cpp index bce2c70b3..c87f15a03 100644 --- a/sources/editor/elementitemeditor.cpp +++ b/sources/editor/elementitemeditor.cpp @@ -16,7 +16,7 @@ along with QElectroTech. If not, see . */ #include "elementitemeditor.h" -#include "ui/qetelementeditor.h" +#include "qetelementeditor.h" #include "editorcommands.h" /** diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index 570c5bec3..76be82edb 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -33,7 +33,7 @@ #include "graphicspart/partrectangle.h" #include "graphicspart/partterminal.h" #include "graphicspart/parttext.h" -#include "ui/qetelementeditor.h" +#include "qetelementeditor.h" #include "ui/elementpropertieseditorwidget.h" #include diff --git a/sources/editor/elementview.cpp b/sources/editor/elementview.cpp index 1dd8b2ecb..293b97784 100644 --- a/sources/editor/elementview.cpp +++ b/sources/editor/elementview.cpp @@ -19,7 +19,7 @@ #include "../qetapp.h" #include "UndoCommand/pastepartscommand.h" -#include "ui/qetelementeditor.h" +#include "qetelementeditor.h" /** Constructeur @param scene ElementScene visualisee par cette ElementView diff --git a/sources/editor/esevent/eseventaddline.cpp b/sources/editor/esevent/eseventaddline.cpp index d8b3fb580..2c9737c23 100644 --- a/sources/editor/esevent/eseventaddline.cpp +++ b/sources/editor/esevent/eseventaddline.cpp @@ -20,7 +20,7 @@ #include "../editorcommands.h" #include "../elementscene.h" #include "../graphicspart/partline.h" -#include "../ui/qetelementeditor.h" +#include "../qetelementeditor.h" #include #include diff --git a/sources/editor/esevent/eseventinterface.cpp b/sources/editor/esevent/eseventinterface.cpp index 2e80f9802..3ab356ef9 100644 --- a/sources/editor/esevent/eseventinterface.cpp +++ b/sources/editor/esevent/eseventinterface.cpp @@ -18,8 +18,7 @@ #include "eseventinterface.h" #include "../elementscene.h" -#include "../ui/qetelementeditor.h" -#include "../elementview.h" +#include "../qetelementeditor.h" #include @@ -41,7 +40,7 @@ ESEventInterface::ESEventInterface(ElementScene *scene) : void ESEventInterface::init() { m_scene->setBehavior(ElementScene::Behavior::AddPart); - m_editor->elementView()->setDragMode(QGraphicsView::NoDrag); + m_editor->slot_setNoDragToView(); } /** @@ -54,31 +53,31 @@ ESEventInterface::~ESEventInterface() delete m_help_verti; m_scene->setBehavior(ElementScene::Behavior::Normal); - m_editor->elementView()->setDragMode(QGraphicsView::RubberBandDrag); + m_editor->slot_setRubberBandToView(); } bool ESEventInterface::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { - Q_UNUSED (event) + Q_UNUSED (event); return false; } bool ESEventInterface::mousePressEvent(QGraphicsSceneMouseEvent *event) { - Q_UNUSED (event) + Q_UNUSED (event); return false; } bool ESEventInterface::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - Q_UNUSED (event) + Q_UNUSED (event); return false; } bool ESEventInterface::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { - Q_UNUSED (event) + Q_UNUSED (event); return false; } bool ESEventInterface::wheelEvent(QGraphicsSceneWheelEvent *event) { - Q_UNUSED (event) + Q_UNUSED (event); return false; } @@ -98,7 +97,7 @@ bool ESEventInterface::keyPressEvent(QKeyEvent *event) { } bool ESEventInterface::KeyReleaseEvent(QKeyEvent *event) { - Q_UNUSED (event) + Q_UNUSED (event); return false; } diff --git a/sources/editor/graphicspart/customelementpart.cpp b/sources/editor/graphicspart/customelementpart.cpp index 4ec4ebe95..27e3e6ca4 100644 --- a/sources/editor/graphicspart/customelementpart.cpp +++ b/sources/editor/graphicspart/customelementpart.cpp @@ -17,8 +17,7 @@ */ #include "customelementpart.h" -#include "../ui/qetelementeditor.h" -#include "../elementscene.h" +#include "../qetelementeditor.h" /// @return le QETElementEditor auquel cet editeur appartient QETElementEditor *CustomElementPart::elementEditor() const diff --git a/sources/editor/graphicspart/partpolygon.cpp b/sources/editor/graphicspart/partpolygon.cpp index 57541f10e..05c7ccc7a 100644 --- a/sources/editor/graphicspart/partpolygon.cpp +++ b/sources/editor/graphicspart/partpolygon.cpp @@ -22,7 +22,7 @@ #include "../../QetGraphicsItemModeler/qetgraphicshandlerutility.h" #include "../../qeticons.h" #include "../elementscene.h" -#include "../ui/qetelementeditor.h" +#include "../qetelementeditor.h" /** @brief PartPolygon::PartPolygon diff --git a/sources/editor/qetelementeditor.cpp b/sources/editor/qetelementeditor.cpp new file mode 100644 index 000000000..5f08e1f4f --- /dev/null +++ b/sources/editor/qetelementeditor.cpp @@ -0,0 +1,1734 @@ +/* + 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 . +*/ +#include "qetelementeditor.h" + +#include "../editor/graphicspart/customelementpart.h" +#include "../elementdialog.h" +#include "../newelementwizard.h" +#include "../qet.h" +#include "../qetapp.h" +#include "../qeticons.h" +#include "../qetmessagebox.h" +#include "../recentfiles.h" +#include "arceditor.h" +#include "editorcommands.h" +#include "elementitemeditor.h" +#include "elementscene.h" +#include "elementview.h" +#include "esevent/eseventaddarc.h" +#include "esevent/eseventadddynamictextfield.h" +#include "esevent/eseventaddellipse.h" +#include "esevent/eseventaddline.h" +#include "esevent/eseventaddpolygon.h" +#include "esevent/eseventaddrect.h" +#include "esevent/eseventaddterminal.h" +#include "esevent/eseventaddtext.h" +#include "graphicspart/partterminal.h" +#include "styleeditor.h" +#include "terminaleditor.h" +#include "ui/dynamictextfieldeditor.h" +#include "ui/ellipseeditor.h" +#include "ui/lineeditor.h" +#include "ui/polygoneditor.h" +#include "ui/rectangleeditor.h" +#include "ui/texteditor.h" + +#include +#include +#include +#include +#include +#include + +/* + Nombre maximum de primitives affichees par la "liste des parties" + Au-dela, un petit message est affiche, indiquant que ce nombre a ete depasse + et que la liste ne sera donc pas mise a jour. +*/ +#define QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST 200 + +/** + Constructeur + @param parent QWidget parent +*/ +QETElementEditor::QETElementEditor(QWidget *parent) : + QETMainWindow(parent), + read_only(false), + min_title(tr("QElectroTech - Éditeur d'élément", "window title")), + opened_from_file(false) { + setWindowTitle(min_title); + setWindowIcon(QET::Icons::QETLogo); + + setupInterface(); + setupActions(); + setupMenus(); + + // la fenetre est maximisee par defaut + setMinimumSize(QSize(500, 350)); + setWindowState(Qt::WindowMaximized); + + // lecture des parametres + readSettings(); + slot_updateMenus(); + + // affichage + show(); +} + +/// Destructeur +QETElementEditor::~QETElementEditor() +{ + /* + retire le widget d'edition de primitives affiche par le dock + cela evite qu'il ne soit supprime par son widget parent + */ + clearToolsDock(); + + // supprime les editeurs de primitives + qDeleteAll(m_editors.begin(), m_editors.end()); + m_editors.clear(); +} + +/** + @brief QETElementEditor::setLocation + The new location to edit + @param el +*/ +void QETElementEditor::setLocation(const ElementsLocation &el) { + location_ = el; + opened_from_file = false; + setReadOnly(!location_.isWritable()); + slot_updateTitle(); +} + +/** + @param fn Le nouveau nom de fichier de l'element edite +*/ +void QETElementEditor::setFileName(const QString &fn) { + filename_ = fn; + opened_from_file = true; + // modifie le mode lecture seule si besoin + bool must_be_read_only = !QFileInfo(filename_).isWritable(); + if (isReadOnly() != must_be_read_only) { + setReadOnly(must_be_read_only); + } + slot_updateTitle(); +} + +/** + @brief QETElementEditor::setupActions + Create action used in Element editor +*/ +void QETElementEditor::setupActions() +{ + new_element = new QAction(QET::Icons::DocumentNew, tr("&Nouveau"), this); + open = new QAction(QET::Icons::FolderOpen, tr("&Ouvrir"), this); + open_file = new QAction(QET::Icons::FolderOpen, tr("&Ouvrir depuis un fichier"), this); + open_dxf = new QAction(QET::Icons::RunDxf, tr("&Lancer le plugin convertisseur DXF"), this); + save = new QAction(QET::Icons::DocumentSave, tr("&Enregistrer"), this); + save_as = new QAction(QET::Icons::DocumentSaveAs, tr("Enregistrer sous"), this); + save_as_file = new QAction(QET::Icons::DocumentSaveAs, tr("Enregistrer dans un fichier"), this); + reload = new QAction(QET::Icons::ViewRefresh, tr("Recharger"), this); + quit = new QAction(QET::Icons::ApplicationExit, tr("&Quitter"), this); + selectall = new QAction(QET::Icons::EditSelectAll, tr("Tout sélectionner"), this); + deselectall = new QAction(QET::Icons::EditSelectNone, tr("Désélectionner tout"), this); + cut = new QAction(QET::Icons::EditCut, tr("Co&uper"), this); + copy = new QAction(QET::Icons::EditCopy, tr("Cop&ier"), this); + paste = new QAction(QET::Icons::EditPaste, tr("C&oller"), this); + paste_in_area = new QAction(QET::Icons::EditPaste, tr("C&oller dans la zone..."), this); + paste_from_file = new QAction(QET::Icons::XmlTextFile, tr("un fichier"), this); + paste_from_elmt = new QAction(QET::Icons::Element, tr("un élément"), this); + inv_select = new QAction(QET::Icons::EditSelectInvert, tr("Inverser la sélection"), this); + edit_delete = new QAction(QET::Icons::EditDelete, tr("&Supprimer"), this); + edit_names = new QAction(QET::Icons::Names, tr("Éditer le nom et les traductions de l'élément"), this); + edit_author = new QAction(QET::Icons::UserInformations, tr("Éditer les informations sur l'auteur"), this); + m_edit_properties = new QAction(QET::Icons::ElementEdit, tr("Éditer les propriétés de l'élément"), this); + +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) + open_dxf -> setStatusTip(tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" + "\n" + ">> Install on Windows\n" + "Put DXFtoQET.exe binary on C:\\Users\\user_name\\AppData\\Roaming\\qet\\ directory \n" + )); +#elif defined(Q_OS_MAC) + open_dxf -> setStatusTip(tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" + "\n" + ">> Install on macOSX\n" + "Put DXFtoQET.app binary on /Users/user_name/.qet/ directory \n" + )); +#else + open_dxf -> setStatusTip(tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" + "\n" + ">> Install on Linux\n" + "Put DXFtoQET binary on your /home/user_name/.qet/ directory\n" + "make it executable : chmod +x ./DXFtoQET\n" + )); +#endif + + open_dxf -> setWhatsThis (tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" + "\n" + ">> Install on Linux\n" + "Put DXFtoQET binary on your /home/user_name/.qet/ directory\n" + "make it executable : chmod +x ./DXFtoQET\n" + ">> Install on Windows\n" + "Put DXFtoQET.exe binary on C:\\Users\\user_name\\AppData\\Roaming\\qet\\ directory \n" + "\n" + ">> Install on macOSX\n" + "Put DXFtoQET.app binary on /Users/user_name/.qet/ directory \n" + )); + + undo = m_elmt_scene -> undoStack().createUndoAction(this, tr("Annuler")); + redo = m_elmt_scene -> undoStack().createRedoAction(this, tr("Refaire")); + undo -> setIcon(QET::Icons::EditUndo); + redo -> setIcon(QET::Icons::EditRedo); + undo -> setShortcuts(QKeySequence::Undo); + redo -> setShortcuts(QKeySequence::Redo); + + new_element -> setShortcut(QKeySequence::New); + open -> setShortcut(QKeySequence::Open); + open_file -> setShortcut(tr("Ctrl+Shift+O")); + save -> setShortcut(QKeySequence::Save); + save_as_file -> setShortcut(tr("Ctrl+Shift+S")); + quit -> setShortcut(QKeySequence(tr("Ctrl+Q"))); + selectall -> setShortcut(QKeySequence::SelectAll); + deselectall -> setShortcut(QKeySequence(tr("Ctrl+Shift+A"))); + inv_select -> setShortcut(QKeySequence(tr("Ctrl+I"))); + cut -> setShortcut(QKeySequence::Cut); + copy -> setShortcut(QKeySequence::Copy); + paste -> setShortcut(QKeySequence::Paste); + paste_in_area -> setShortcut(tr("Ctrl+Shift+V")); + +#ifndef Q_OS_MAC + edit_delete -> setShortcut(QKeySequence(Qt::Key_Delete)); +#else + edit_delete -> setShortcut(QKeySequence(tr("Backspace"))); +#endif + + edit_names -> setShortcut(QKeySequence(tr("Ctrl+E"))); + edit_author -> setShortcut(tr("Ctrl+Y")); + + connect(new_element, SIGNAL(triggered()), this, SLOT(slot_new())); + connect(open, SIGNAL(triggered()), this, SLOT(slot_open())); + connect(open_dxf, SIGNAL(triggered()), this, SLOT(slot_openDxf())); + connect(open_file, SIGNAL(triggered()), this, SLOT(slot_openFile())); + connect(save, SIGNAL(triggered()), this, SLOT(slot_save())); + connect(save_as, SIGNAL(triggered()), this, SLOT(slot_saveAs())); + connect(save_as_file, SIGNAL(triggered()), this, SLOT(slot_saveAsFile())); + connect(reload, SIGNAL(triggered()), this, SLOT(slot_reload())); + connect(quit, SIGNAL(triggered()), this, SLOT(close())); + connect(selectall, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_selectAll())); + connect(deselectall, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_deselectAll())); + connect(inv_select, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_invertSelection())); + connect(cut, SIGNAL(triggered()), m_view, SLOT(cut())); + connect(copy, SIGNAL(triggered()), m_view, SLOT(copy())); + connect(paste, SIGNAL(triggered()), m_view, SLOT(paste())); + connect(paste_in_area, SIGNAL(triggered()), m_view, SLOT(pasteInArea())); + connect(paste_from_file, SIGNAL(triggered()), this, SLOT(pasteFromFile())); + connect(paste_from_elmt, SIGNAL(triggered()), this, SLOT(pasteFromElement())); + connect(edit_delete, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_delete())); + connect(edit_names, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_editNames())); + connect(edit_author, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_editAuthorInformations())); + connect(m_edit_properties, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_editProperties())); + + //Action related to change depth of primitive + m_depth_action_group = QET::depthActionGroup(this); + + connect(m_depth_action_group, &QActionGroup::triggered, [this](QAction *action) { + this -> elementScene() -> undoStack().push( + new ChangeZValueCommand(this -> elementScene(), action -> data().value())); + emit(this -> elementScene() -> partsZValueChanged()); + }); + + depth_toolbar = addToolBar(tr("Profondeur", "toolbar title")); + depth_toolbar -> setObjectName("depth_toolbar"); + depth_toolbar -> addActions(m_depth_action_group -> actions()); + addToolBar(Qt::TopToolBarArea, depth_toolbar); + + /* + Action related to zoom + */ + m_zoom_ag = new QActionGroup(this); + + QAction *zoom_in = new QAction(QET::Icons::ZoomIn, tr("Zoom avant"), m_zoom_ag); + QAction *zoom_out = new QAction(QET::Icons::ZoomOut, tr("Zoom arrière"), m_zoom_ag); + QAction *zoom_fit = new QAction(QET::Icons::ZoomFitBest, tr("Zoom adapté"), m_zoom_ag); + QAction *zoom_reset = new QAction(QET::Icons::ZoomOriginal, tr("Pas de zoom"), m_zoom_ag); + + zoom_in -> setShortcut(QKeySequence::ZoomIn); + zoom_out -> setShortcut(QKeySequence::ZoomOut); + zoom_fit -> setShortcut(QKeySequence(tr("Ctrl+9"))); + zoom_reset -> setShortcut(QKeySequence(tr("Ctrl+0"))); + + connect(zoom_in, SIGNAL(triggered()), m_view, SLOT(zoomIn() )); + connect(zoom_out, SIGNAL(triggered()), m_view, SLOT(zoomOut() )); + connect(zoom_fit, SIGNAL(triggered()), m_view, SLOT(zoomFit() )); + connect(zoom_reset, SIGNAL(triggered()), m_view, SLOT(zoomReset() )); + + /* + Action related to primitive creation + */ + connect (m_elmt_scene, SIGNAL(partsAdded()), this, SLOT(UncheckAddPrimitive())); + parts = new QActionGroup(this); + + QAction *add_line = new QAction(QET::Icons::PartLine, tr("Ajouter une ligne"), parts); + QAction *add_rectangle = new QAction(QET::Icons::PartRectangle, tr("Ajouter un rectangle"), parts); + QAction *add_ellipse = new QAction(QET::Icons::PartEllipse, tr("Ajouter une ellipse"), parts); + QAction *add_polygon = new QAction(QET::Icons::PartPolygon, tr("Ajouter un polygone"), parts); + QAction *add_text = new QAction(QET::Icons::PartText, tr("Ajouter du texte"), parts); + QAction *add_arc = new QAction(QET::Icons::PartArc, tr("Ajouter un arc de cercle"), parts); + QAction *add_terminal = new QAction(QET::Icons::Terminal, tr("Ajouter une borne"), parts); + QAction *add_dynamic_text_field = new QAction(QET::Icons::PartTextField, tr("Ajouter un champ texte dynamique"), parts); + + foreach (QAction *action, parts -> actions()) action -> setCheckable(true); + + connect(add_line, SIGNAL(triggered()), this, SLOT(addLine() )); + connect(add_rectangle, SIGNAL(triggered()), this, SLOT(addRect() )); + connect(add_ellipse, SIGNAL(triggered()), this, SLOT(addEllipse() )); + connect(add_polygon, SIGNAL(triggered()), this, SLOT(addPolygon() )); + connect(add_text, SIGNAL(triggered()), this, SLOT(addText() )); + connect(add_arc, SIGNAL(triggered()), this, SLOT(addArc() )); + connect(add_terminal, SIGNAL(triggered()), this, SLOT(addTerminal() )); + connect(add_dynamic_text_field, &QAction::triggered, this, &QETElementEditor::addDynamicTextField); + + add_polygon -> setStatusTip(tr("Double-click pour terminer la forme, Click droit pour annuler le dernier point")); + add_text -> setStatusTip(tr("Ajouter un texte d'élément non éditable dans les schémas")); + add_dynamic_text_field -> setStatusTip(tr("Ajouter un texte d'élément pouvant être édité dans les schémas")); + + parts_toolbar = addToolBar(tr("Parties", "toolbar title")); + parts_toolbar -> setAllowedAreas(Qt::AllToolBarAreas); + parts_toolbar -> setObjectName("parts"); + parts_toolbar -> addActions(parts -> actions()); + addToolBar(Qt::LeftToolBarArea, parts_toolbar); + + main_toolbar = new QToolBar(tr("Outils", "toolbar title"), this); + main_toolbar -> setObjectName("main_toolbar"); + view_toolbar = new QToolBar(tr("Affichage", "toolbar title"), this); + view_toolbar -> setObjectName("display"); + element_toolbar = new QToolBar(tr("Élément", "toolbar title"), this); + element_toolbar -> setObjectName("element_toolbar"); + + main_toolbar -> addAction(new_element); + main_toolbar -> addAction(open); + main_toolbar -> addAction(save); + main_toolbar -> addAction(save_as); + main_toolbar -> addAction(reload); + main_toolbar -> addSeparator(); + main_toolbar -> addAction(undo); + main_toolbar -> addAction(redo); + main_toolbar -> addSeparator(); + main_toolbar -> addAction(edit_delete); + + view_toolbar -> addAction(zoom_fit); + view_toolbar -> addAction(zoom_reset); + + element_toolbar -> addAction(edit_names); + element_toolbar -> addAction(m_edit_properties); + + addToolBar(Qt::TopToolBarArea, main_toolbar); + addToolBar(Qt::TopToolBarArea, view_toolbar); + addToolBar(Qt::TopToolBarArea, element_toolbar); + + connect(m_elmt_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateInformations()), Qt::QueuedConnection); + connect(m_elmt_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updateMenus())); + connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slot_updateMenus())); + connect(&(m_elmt_scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(slot_updateMenus())); + connect(&(m_elmt_scene -> undoStack()), SIGNAL(cleanChanged(bool)), this, SLOT(slot_updateTitle())); + + // Annuler ou refaire une action met a jour la liste des primitives ; cela sert notamment pour les + // ajouts et suppressions de primitives ainsi que pour les actions entrainant un change + connect(&(m_elmt_scene -> undoStack()), SIGNAL(indexChanged(int)), this, SLOT(slot_updatePartsList())); + + // Annuler ou refaire une action met a jour les informations affichees sur les primitives selectionnees, + // celles-ci etant potentiellement impactees + connect(&(m_elmt_scene -> undoStack()), SIGNAL(indexChanged(int)), this, SLOT(slot_updateInformations())); +} + +/** + @brief QETElementEditor::setupMenus +*/ +void QETElementEditor::setupMenus() +{ + file_menu = new QMenu(tr("&Fichier"), this); + edit_menu = new QMenu(tr("&Édition"), this); + display_menu = new QMenu(tr("Afficha&ge"), this); + tools_menu = new QMenu(tr("O&utils"), this); + + file_menu -> setTearOffEnabled(true); + edit_menu -> setTearOffEnabled(true); + display_menu -> setTearOffEnabled(true); + tools_menu -> setTearOffEnabled(true); + + file_menu -> addAction(new_element); + file_menu -> addAction(open); + file_menu -> addAction(open_file); + file_menu -> addAction(open_dxf); + QMenu *recentfile = file_menu -> addMenu(QET::Icons::DocumentOpenRecent, tr("&Récemment ouverts")); + recentfile -> addActions(QETApp::elementsRecentFiles() -> menu() -> actions()); + connect(QETApp::elementsRecentFiles(), SIGNAL( + fileOpeningRequested(const QString &)), this, SLOT(openRecentFile(const QString &))); + file_menu -> addAction(save); + file_menu -> addAction(save_as); + file_menu -> addAction(save_as_file); + file_menu -> addSeparator(); + file_menu -> addAction(reload); + file_menu -> addSeparator(); + file_menu -> addAction(quit); + + paste_from_menu = new QMenu(tr("Coller depuis...")); + paste_from_menu -> setIcon(QET::Icons::EditPaste); + paste_from_menu -> addAction(paste_from_file); + paste_from_menu -> addAction(paste_from_elmt); + + edit_menu -> addAction(undo); + edit_menu -> addAction(redo); + edit_menu -> addSeparator(); + edit_menu -> addAction(selectall); + edit_menu -> addAction(deselectall); + edit_menu -> addAction(inv_select); + edit_menu -> addSeparator(); + edit_menu -> addAction(cut); + edit_menu -> addAction(copy); + edit_menu -> addAction(paste); + edit_menu -> addAction(paste_in_area); + edit_menu -> addMenu(paste_from_menu); + edit_menu -> addSeparator(); + edit_menu -> addAction(edit_delete); + edit_menu -> addSeparator(); + edit_menu -> addAction(edit_names); + edit_menu -> addAction(edit_author); + edit_menu -> addAction(m_edit_properties); + edit_menu -> addSeparator(); + edit_menu -> addActions(m_depth_action_group -> actions()); + + display_menu -> addActions(m_zoom_ag -> actions()); + + insertMenu(settings_menu_, file_menu); + insertMenu(settings_menu_, edit_menu); + insertMenu(settings_menu_, display_menu); +} + +/** + @brief QETElementEditor::contextMenu + Display a context menu, with all available action. + @param p : the pos of the menu, in screen coordinate + @param actions : + a list of actions who can be prepended to the context menu. +*/ +void QETElementEditor::contextMenu(QPoint p, QList actions) { + QMenu menu(this); + menu.addActions(std::move(actions)); + menu.addSeparator(); + menu.addAction(undo); + menu.addAction(redo); + menu.addAction(selectall); + menu.addAction(deselectall); + menu.addAction(inv_select); + menu.addSeparator(); + menu.addAction(edit_delete); + menu.addAction(cut); + menu.addAction(copy); + menu.addSeparator(); + menu.addAction(paste); + menu.addAction(paste_in_area); + menu.addMenu(paste_from_menu); + menu.addSeparator(); + menu.addActions(m_depth_action_group -> actions()); + + //Remove from the context menu the actions which are disabled. + const QListmenu_actions = menu.actions(); + for(QAction *action : menu_actions) { + if(!action -> isEnabled()) { + menu.removeAction(action); + } + } + menu.exec(p); +} + +/** + Met a jour les menus +*/ +void QETElementEditor::slot_updateMenus() +{ + bool selected_items = !read_only && !m_elmt_scene -> selectedItems().isEmpty(); + bool clipboard_elmt = !read_only && ElementScene::clipboardMayContainElement(); + + // actions dependant seulement de l'etat "lecture seule" de l'editeur + foreach (QAction *action, parts -> actions()) { + action -> setEnabled(!read_only); + } + selectall -> setEnabled(!read_only); + inv_select -> setEnabled(!read_only); + paste_from_file -> setEnabled(!read_only); + paste_from_elmt -> setEnabled(!read_only); + m_parts_list -> setEnabled(!read_only); + + // Action enabled if primitive selected + deselectall -> setEnabled(selected_items); + cut -> setEnabled(selected_items); + copy -> setEnabled(selected_items); + edit_delete -> setEnabled(selected_items); + foreach (QAction *action, m_depth_action_group -> actions()) { + action -> setEnabled(selected_items); + } + + // actions dependant du contenu du presse-papiers + paste -> setEnabled(clipboard_elmt); + paste_in_area -> setEnabled(clipboard_elmt); + + // actions dependant de l'etat de la pile d'annulation + save -> setEnabled(!read_only && !m_elmt_scene -> undoStack().isClean()); + undo -> setEnabled(!read_only && m_elmt_scene -> undoStack().canUndo()); + redo -> setEnabled(!read_only && m_elmt_scene -> undoStack().canRedo()); +} + +/** + Met a jour le titre de la fenetre +*/ +void QETElementEditor::slot_updateTitle() +{ + QString title = min_title; + title += " - " + m_elmt_scene -> names().name() + " "; + if (!filename_.isEmpty() || !location_.isNull()) { + if (!m_elmt_scene -> undoStack().isClean()) { + title += tr("[Modifié]", "window title tag"); + } + } + if (isReadOnly()) { + title += tr(" [lecture seule]", "window title tag"); + } + setWindowTitle(title); +} + +/** + @brief QETElementEditor::setupInterface +*/ +void QETElementEditor::setupInterface() +{ + // editeur + m_elmt_scene = new ElementScene(this, this); + m_view = new ElementView(m_elmt_scene, this); + slot_setRubberBandToView(); + setCentralWidget(m_view); + + // widget par defaut dans le QDockWidget + m_default_informations = new QLabel(); + + // ScrollArea pour accueillir un widget d'edition (change a la volee) +// m_tools_dock_scroll_area = new QScrollArea(); +// m_tools_dock_scroll_area -> setFrameStyle(QFrame::NoFrame); +// m_tools_dock_scroll_area -> setAlignment(Qt::AlignHCenter|Qt::AlignTop); + + // Pile de widgets pour accueillir les deux widgets precedents + m_tools_dock_stack = new QStackedWidget(); + m_tools_dock_stack -> insertWidget(0, m_default_informations); +// m_tools_dock_stack -> insertWidget(1, m_tools_dock_scroll_area); + + // widgets d'editions pour les parties + m_editors["arc"] = new ArcEditor(this); + m_editors["ellipse"] = new EllipseEditor(this); + m_editors["line"] = new LineEditor(this); + m_editors["polygon"] = new PolygonEditor(this); + m_editors["rect"] = new RectangleEditor(this); + m_editors["terminal"] = new TerminalEditor(this); + m_editors["text"] = new TextEditor(this); + m_editors["style"] = new StyleEditor(this); + m_editors["dynamic_text"] = new DynamicTextFieldEditor(this); + + // panel sur le cote pour editer les parties + m_tools_dock = new QDockWidget(tr("Informations", "dock title"), this); + m_tools_dock -> setObjectName("informations"); + m_tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_tools_dock -> setFeatures( + QDockWidget::DockWidgetClosable + |QDockWidget::DockWidgetMovable + |QDockWidget::DockWidgetFloatable); + //m_tools_dock -> setMinimumWidth(380); + addDockWidget(Qt::RightDockWidgetArea, m_tools_dock); + m_tools_dock -> setWidget(m_tools_dock_stack); + + // panel sur le cote pour les annulations + m_undo_dock = new QDockWidget(tr("Annulations", "dock title"), this); + m_undo_dock -> setObjectName("undo"); + m_undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_undo_dock -> setFeatures( + QDockWidget::DockWidgetClosable + |QDockWidget::DockWidgetMovable + |QDockWidget::DockWidgetFloatable); + m_undo_dock -> setMinimumWidth(290); + addDockWidget(Qt::RightDockWidgetArea, m_undo_dock); + QUndoView* undo_view = new QUndoView(&(m_elmt_scene -> undoStack()), this); + undo_view -> setEmptyLabel(tr("Aucune modification")); + m_undo_dock -> setWidget(undo_view); + + // panel sur le cote pour la liste des parties + m_parts_list = new QListWidget(this); + m_parts_list -> setSelectionMode(QAbstractItemView::ExtendedSelection); + connect(m_elmt_scene, SIGNAL(partsAdded()), this, SLOT(slot_createPartsList())); + connect(m_elmt_scene, SIGNAL(partsRemoved()), this, SLOT(slot_createPartsList())); + connect(m_elmt_scene, SIGNAL(partsZValueChanged()), this, SLOT(slot_createPartsList())); + connect(m_elmt_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updatePartsList())); + connect(m_parts_list, SIGNAL(itemSelectionChanged()), this, SLOT(slot_updateSelectionFromPartsList())); + m_parts_dock = new QDockWidget(tr("Parties", "dock title"), this); + m_parts_dock -> setObjectName("parts_list"); + m_parts_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_parts_dock -> setFeatures( + QDockWidget::DockWidgetClosable + |QDockWidget::DockWidgetMovable + |QDockWidget::DockWidgetFloatable); + m_parts_dock -> setMinimumWidth(290); + tabifyDockWidget(m_undo_dock, m_parts_dock); + m_parts_dock -> setWidget(m_parts_list); + + slot_updateInformations(); + slot_createPartsList(); + + // barre d'etat + statusBar() -> showMessage(tr("Éditeur d'éléments", "status bar message")); +} + +/** + Passe l'editeur d'element en mode selection : le pointeur deplace les + elements selectionnes et il est possible d'utiliser un rectangle de selection. +*/ +void QETElementEditor::slot_setRubberBandToView() +{ + m_view -> setDragMode(QGraphicsView::RubberBandDrag); +} + +/** + Passe l'editeur d'element en mode immobile (utilise pour la lecture seule) +*/ +void QETElementEditor::slot_setNoDragToView() +{ + m_view -> setDragMode(QGraphicsView::NoDrag); +} + +/** + Met a jour la zone d'information et d'edition des primitives. + Si plusieurs primitives sont selectionnees, seule leur quantite est + affichee. Sinon, un widget d'edition approprie est mis en place. +*/ +void QETElementEditor::slot_updateInformations() +{ + QList selected_qgis = m_elmt_scene -> selectedItems(); + if (selected_qgis.isEmpty()) { + clearToolsDock(); + m_default_informations -> setText(tr("%n partie(s) sélectionnée(s).", + "", + selected_qgis.size())); + m_default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); + m_tools_dock_stack -> setCurrentIndex(0); + return; + } + + QList cep_list; + + CustomElementPart* part = dynamic_cast(selected_qgis.first()); + QString selection_xml_name = part -> xmlName(); + bool same_xml_name = true; + bool style_editable = true; + for (QGraphicsItem *qgi: selected_qgis) { + if (CustomElementPart *cep = dynamic_cast(qgi)) { + cep_list << cep; + if (cep -> xmlName() != selection_xml_name) { + same_xml_name = false; + } + } + else { + style_editable = false; + same_xml_name = false; + } + } + if (style_editable) { + style_editable = StyleEditor::isStyleEditable(cep_list); + } + + if (same_xml_name) { + if (selection_xml_name == "terminal" || + selection_xml_name == "text" || + selection_xml_name == "dynamic_text" || + selection_xml_name == "line" || + selection_xml_name == "rect" || + selection_xml_name == "ellipse" || + selection_xml_name == "arc") { + clearToolsDock(); + //We add the editor widget + ElementItemEditor *editor = static_cast(m_editors[selection_xml_name]); + +#if TODO_LIST +#pragma message("@TODO Check if it takes longer than setting the parts again to the editor.") +#endif + // TODO: Check if it takes longer than setting the parts again to the editor. + bool equal = true; + QList parts = editor -> currentParts(); + if (parts.length() == cep_list.length()) { + for (auto cep: cep_list) { + bool part_found = false; + for (auto part: parts) { + if (part == cep) { + part_found = true; + break; + } + } + if (!part_found) { + equal = false; + break; + } + } + } + else { + equal = false; + } + + if (editor) { + bool success = true; + if (equal == false) { + success = editor -> setParts(cep_list); + } + if (success) { + m_tools_dock_stack -> insertWidget(1, editor); + m_tools_dock_stack -> setCurrentIndex(1); + } + else { + qDebug() << "Editor refused part."; + } + } + return; + } + else if (selection_xml_name == "polygon" && cep_list.length() == 1) { +#if TODO_LIST +#pragma message("@TODO maybe allowing multipart edit when number of points is the same?") +#endif + // multi edit for polygons makes no sense + // TODO: maybe allowing multipart edit when number of points is the same? + //We add the editor widget + clearToolsDock(); + ElementItemEditor *editor = static_cast(m_editors[selection_xml_name]); + CustomElementPart* part = editor -> currentPart(); + bool equal = part == cep_list.first(); + + if (editor) { + bool success = true; + if (equal == false) { + success = editor -> setPart(cep_list.first()); + } + if (success) { + m_tools_dock_stack -> insertWidget(1, editor); + m_tools_dock_stack -> setCurrentIndex(1); + } + else { + qDebug() << "Editor refused part."; + } + } + return; + + } + else { + qDebug() << "Multiedit not supported for: " << cep_list.first() -> xmlName(); + } + + } + + //There's several parts selecteds and all can be edited by style editor. + if (style_editable) { + clearToolsDock(); + ElementItemEditor *selection_editor = m_editors["style"]; + if (selection_editor) { + if (selection_editor -> setParts(cep_list)) { + m_tools_dock_stack -> insertWidget(1, selection_editor); + m_tools_dock_stack -> setCurrentIndex(1); + } + else { + qDebug() << "Editor refused part."; + } + } + } + //Else we only display the number of selected items + else { + clearToolsDock(); + m_default_informations -> setText(tr("%n partie(s) sélectionnée(s).", + "", + selected_qgis.size())); + m_default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); + m_tools_dock_stack -> setCurrentIndex(0); + } +} + +/** + @brief QETElementEditor::checkElement + Do several check about element. + If error is occurred return false +*/ +bool QETElementEditor::checkElement() +{ + //List of warning and error + typedef QPair QETWarning; + QList warnings; + QList errors; + + /// Warning #1: Element haven't got terminal + /// (except for report, because report must have one terminal and this checking is do below) + if (!m_elmt_scene -> containsTerminals() && !m_elmt_scene -> elementType().contains("report")) { + warnings << qMakePair( + tr("Absence de borne", "warning title"), + tr( + "
En l'absence de borne, l'élément ne pourra être" + " relié à d'autres éléments par l'intermédiaire de conducteurs.", + "warning description" + ) + ); + } + + /// Check folio report element + if (m_elmt_scene -> elementType().contains("report")) { + int terminal =0; + + foreach(QGraphicsItem *qgi, m_elmt_scene -> items()) { + if (qgraphicsitem_cast(qgi)) { + terminal ++; + } + } + + ///Error folio report must have only one terminal + if (terminal != 1) { + errors << qMakePair (tr("Absence de borne"), + tr("
Erreur :" + "
Les reports de folio doivent posséder une seul borne." + "
Solution :" + "
Verifier que l'élément ne possède qu'une seul borne")); + } + } + + if (!errors.count() && !warnings.count()) { + return(true); + } + + // Display warnings + QString dialog_message = tr("La vérification de cet élément a généré", "message box content"); + + if (errors.size()) { + dialog_message += QString(tr(" %n erreur(s)", "errors", errors.size())); + } + + if (warnings.size()) { + if (errors.size()) { + dialog_message += QString (tr(" et")); + } + dialog_message += QString (tr(" %n avertissement(s)", "warnings", warnings.size())); + } + dialog_message += " :"; + + dialog_message += "
    "; + QList total = warnings << errors; + foreach(QETWarning warning, total) { + dialog_message += "
  1. "; + dialog_message += QString( + tr("%1 : %2", "warning title: warning description") + ).arg(warning.first).arg(warning.second); + dialog_message += "
  2. "; + } + dialog_message += "
"; + + if (errors.size()) { + QMessageBox::critical(this, tr("Erreurs"), dialog_message); + } + else { + QMessageBox::warning(this, tr("Avertissements"), dialog_message); + } + + //if error == 0 that means they are only warning, we return true. + if (errors.count() == 0) { + return(true); + } + return false; +} + +/** + Charge un fichier + @param filepath Chemin du fichier a charger +*/ +void QETElementEditor::fromFile(const QString &filepath) { + bool state = true; + QString error_message; + + // le fichier doit exister + QFileInfo infos_file(filepath); + if (!infos_file.exists() || !infos_file.isFile()) { + state = false; + error_message = QString(tr("Le fichier %1 n'existe pas.", "message box content")).arg(filepath); + } + + // le fichier doit etre lisible + QFile file(filepath); + if (state) { + if (!file.open(QIODevice::ReadOnly)) { + state = false; + error_message = QString(tr("Impossible d'ouvrir le fichier %1.", "message box content")).arg(filepath); + } + } + + // le fichier doit etre un document XML + QDomDocument document_xml; + if (state) { + if (!document_xml.setContent(&file)) { + state = false; + error_message = tr("Ce fichier n'est pas un document XML valide", "message box content"); + } + file.close(); + } + + if (!state) { + QET::QetMessageBox::critical(this, tr("Erreur", "toolbar title"), error_message); + return; + } + + // chargement de l'element + m_elmt_scene -> fromXml(document_xml); + slot_createPartsList(); + + // gestion de la lecture seule + if (!infos_file.isWritable()) { + QET::QetMessageBox::warning( + this, + tr("Édition en lecture seule", "message box title"), + tr("Vous n'avez pas les privilèges nécessaires pour modifier cet élement. Il sera donc ouvert en lecture seule.", "message box content") + ); + setReadOnly(true); + } + else { + setReadOnly(false); + } + + // memorise le fichier + setFileName(filepath); + QETApp::elementsRecentFiles() -> fileWasOpened(filepath); + slot_updateMenus(); +} + +/** + @brief QETElementEditor::toFile + Save to file the drawed element. + @param fn : path of the file + @return : true if succesfully save. +*/ +bool QETElementEditor::toFile(const QString &fn) { + m_elmt_scene -> clearEventInterface(); + m_elmt_scene -> clearSelection(); + UncheckAddPrimitive(); + + QDomDocument element_xml = m_elmt_scene -> toXml(); + bool writing = QET::writeXmlFile(element_xml, fn); + if (!writing) { + QET::QetMessageBox::warning( + this, + tr("Erreur", "message box title"), + tr("Impossible d'écrire dans ce fichier", "message box content") + ); + } + return(writing); +} + +/** + @brief QETElementEditor::toLocation + Save the element to Location + @param location : location where we must save the current element + @return true if succesfully saved +*/ +bool QETElementEditor::toLocation(const ElementsLocation &location) { + m_elmt_scene -> clearEventInterface(); + m_elmt_scene -> clearSelection(); + UncheckAddPrimitive(); + + if (!location.setXml(m_elmt_scene -> toXml())) { + QET::QetMessageBox::critical(this, + tr("Erreur", "message box title"), + tr("Impossible d'enregistrer l'élément", "message box content")); + return(false); + } + return(true); +} + +/** + @param provided_location Emplacement d'un element + @return true si cet editeur est en train d'editer l'element dont + l'emplacement est location, false sinon +*/ +bool QETElementEditor::isEditing(const ElementsLocation &provided_location) { + if (opened_from_file) { + return( + QET::compareCanonicalFilePaths( + filename_, + QETApp::realPath(provided_location.toString()) + ) + ); + } + else { + return(provided_location == location_); + } +} + +/** + @param provided_filepath Chemin d'un element sur un filesystem + @return true si cet editeur est en train d'editer l'element dont + le chemin est filepath, false sinon +*/ +bool QETElementEditor::isEditing(const QString &provided_filepath) { + // determine le chemin canonique de l'element actuelle edite, si applicable + QString current_filepath; + if (opened_from_file) { + current_filepath = filename_; + } + else { + current_filepath = QETApp::realPath(location_.toString()); + } + + return( + QET::compareCanonicalFilePaths( + current_filepath, + provided_filepath + ) + ); +} + +/** + specifie si l'editeur d'element doit etre en mode lecture seule + @param ro true pour activer le mode lecture seule, false pour le desactiver +*/ +void QETElementEditor::setReadOnly(bool ro) { + read_only = ro; + + // active / desactive les interactions avec la scene + m_view -> setInteractive(!ro); + + slot_updateMenus(); +} + +/** + @return true si l'editeur d'element est en mode lecture seule +*/ +bool QETElementEditor::isReadOnly() const +{ + return(read_only); +} + +/** + @brief QETElementEditor::addLine + Set line creation interface to scene +*/ +void QETElementEditor::addLine() +{ + m_elmt_scene -> setEventInterface(new ESEventAddLine(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addRect + Set rectangle creation interface to scene +*/ +void QETElementEditor::addRect() +{ + m_elmt_scene -> setEventInterface(new ESEventAddRect(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addEllipse + Set ellipse creation interface to scene +*/ +void QETElementEditor::addEllipse() +{ + m_elmt_scene -> setEventInterface(new ESEventAddEllipse(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addPolygon + Set polygon creation interface to scene +*/ +void QETElementEditor::addPolygon() +{ + m_elmt_scene -> setEventInterface(new ESEventAddPolygon(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addArc + Set arc creation interface to scene +*/ +void QETElementEditor::addArc() +{ + m_elmt_scene -> setEventInterface(new ESEventAddArc(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addText + Set text creation interface to scene +*/ +void QETElementEditor::addText() +{ + m_elmt_scene -> setEventInterface(new ESEventAddText(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addTerminal + Set terminal creation interface to scene +*/ +void QETElementEditor::addTerminal() +{ + m_elmt_scene -> setEventInterface(new ESEventAddTerminal(m_elmt_scene)); +} + +/** + @brief QETElementEditor::addDynamicTextField + Set dynamic text field creation interface to scene +*/ +void QETElementEditor::addDynamicTextField() +{ + m_elmt_scene -> setEventInterface(new ESEventAddDynamicTextField(m_elmt_scene)); +} + +/** + @brief QETElementEditor::UncheckAddPrimitive + Uncheck all action related to primitive +*/ +void QETElementEditor::UncheckAddPrimitive() +{ + foreach(QAction *action, parts -> actions()) { + action -> setChecked(false); + } +} + +/** + Lance l'assistant de creation d'un nouvel element. +*/ +void QETElementEditor::slot_new() +{ + NewElementWizard new_element_wizard(this); + new_element_wizard.exec(); +} + +/** + Ouvre un element +*/ +void QETElementEditor::slot_open() +{ + // demande le chemin virtuel de l'element a ouvrir a l'utilisateur + ElementsLocation location = ElementDialog::getOpenElementLocation(this); + if (location.isNull()) { + return; + } + QETApp::instance() -> openElementLocations(QList() << location); +} + +/** + Ouvre un fichier + Demande un fichier a l'utilisateur et ouvre ce fichier +*/ +void QETElementEditor::slot_openFile() +{ + // repertoire a afficher initialement dans le dialogue + QString open_dir = filename_.isEmpty() ? QETApp::customElementsDir() : QDir(filename_).absolutePath(); + + // demande un nom de fichier a ouvrir a l'utilisateur + QString user_filename = QETElementEditor::getOpenElementFileName(this, open_dir); + + // ouvre l'element + openElement(user_filename); +} + +/** + Slot utilise pour ouvrir un fichier recent. + Transfere filepath au slot openElement seulement si cet editeur est actif + @param filepath Fichier a ouvrir + @see openElement +*/ +void QETElementEditor::openRecentFile(const QString &filepath) { + // small hack to prevent all element editors from trying to topen the required + // recent file at the same time + if (qApp -> activeWindow() != this) { + return; + } + openElement(filepath); +} + +/** + @brief QETElementEditor::slot_openDxf +*/ +void QETElementEditor::slot_openDxf () +{ +#ifdef TODO_LIST +# pragma message("@TODO Merge 'DXF to GET-2020' code in to Qet") +# pragma message("https://github.com/qelectrotech/DXFtoQET-2020") +#endif +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) +QString program = (QDir::homePath() + "/Application Data/qet/DXFtoQET.exe"); +#elif defined(Q_OS_MAC) +QString program = (QDir::homePath() + "/.qet/DXFtoQET.app"); +#else +QString program = (QDir::homePath() + "/.qet/DXFtoQET"); +#endif +QStringList arguments; +QProcess *DXF = new QProcess(qApp); +DXF -> start(program,arguments); + +} + +/** + Ouvre un fichier element dans un nouvel editeur + Cette methode ne controle pas si le fichier est deja ouvert + @param filepath Fichier a ouvrir + @see fromFile + @see QETApp::openElementFiles +*/ +void QETElementEditor::openElement(const QString &filepath) { + if (filepath.isEmpty()) { + return; + } + // we have to test the file existence here because QETApp::openElementFiles() + // will discard non-existent files through QFileInfo::canonicalFilePath() + if (!QFile::exists(filepath)) { + QET::QetMessageBox::critical( + this, + tr("Impossible d'ouvrir le fichier", "message box title"), + QString( + tr("Il semblerait que le fichier %1 que vous essayez d'ouvrir" + " n'existe pas ou plus.") + ).arg(filepath) + ); + } + QETApp::instance() -> openElementFiles(QStringList() << filepath); +} + +/** + @brief QETElementEditor::slot_reload + Reload the element from the file or location +*/ +void QETElementEditor::slot_reload() +{ + //If user already edit the element, ask confirmation to reload + if (!m_elmt_scene -> undoStack().isClean()) { + QMessageBox::StandardButton answer = QET::QetMessageBox::question(this, + tr("Recharger l'élément", "dialog title"), + tr("Vous avez efffectué des modifications sur cet élément. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'élément ?", "dialog content"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Cancel); + if (answer != QMessageBox::Yes){ + return; + } + } + + //Reload the element + m_elmt_scene -> reset(); + if (opened_from_file) { + fromFile(filename_); + } + else { + fromLocation(location_); + } +} + +/** + @brief QETElementEditor::slot_save + Save the current editing element. + If the filepath or location is unknown, use save_as instead + @return true if save with success +*/ +bool QETElementEditor::slot_save() +{ + // Check element befor writing + if (checkElement()) { + //If we don't know the name of the current file, use save as instead + if (opened_from_file) { + if (filename_.isEmpty()) { + return(slot_saveAsFile()); + } + + //Else wa save to the file at filename_ path + bool result_save = toFile(filename_); + if (result_save) m_elmt_scene -> undoStack().setClean(); + return(result_save); + } + else { + if (location_.isNull()) { + return(slot_saveAs()); + } + + //Else save to the known location + bool result_save = toLocation(location_); + if (result_save) { + m_elmt_scene -> undoStack().setClean(); + emit saveToLocation(location_); + } + return(result_save); + } + } + + QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); + return false; +} + +/** + @brief QETElementEditor::slot_saveAs + Ask a location to user and save the current edited element + to this location + @return true if save with success +*/ +bool QETElementEditor::slot_saveAs() +{ + // Check element befor writing + if (checkElement()) { + //Ask a location to user + ElementsLocation location = ElementDialog::getSaveElementLocation(this); + if (location.isNull()) { + return(false); + } + + bool result_save = toLocation(location); + if (result_save) { + setLocation(location); + m_elmt_scene -> undoStack().setClean(); + emit saveToLocation(location); + } + + return(result_save); + } + QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); + return (false); +} + +/** + @brief QETElementEditor::slot_saveAsFile + Ask a file to user and save the current edited element to this file + @return true if save with success +*/ +bool QETElementEditor::slot_saveAsFile() +{ + // Check element befor writing + if (checkElement()) { + //Ask a filename to user, for save the element + QString fn = QFileDialog::getSaveFileName( + this, + tr("Enregistrer sous", "dialog title"), + filename_.isEmpty() ? QETApp::customElementsDir() : QDir(filename_).absolutePath(), + tr( + "Éléments QElectroTech (*.elmt)", + "filetypes allowed when saving an element file" + ) + ); + + if (fn.isEmpty()) { + return(false); + } + + //If the name doesn't end by .elmt, we add it + if (!fn.endsWith(".elmt", Qt::CaseInsensitive)) { + fn += ".elmt"; + } + + bool result_save = toFile(fn); + //If the save success, the filename is keep + if (result_save) { + setFileName(fn); + QETApp::elementsRecentFiles() -> fileWasOpened(fn); + m_elmt_scene -> undoStack().setClean(); + } + + return(result_save); + } + QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); + return false; +} + +/** + @return true si l'element peut etre ferme. + Un element peut etre ferme s'il ne comporte aucune modification. + Si l'element comporte des modifications, la question est posee a + l'utilisateur. +*/ +bool QETElementEditor::canClose() +{ + if (m_elmt_scene -> undoStack().isClean()) { + return(true); + } + // demande d'abord a l'utilisateur s'il veut enregistrer l'element en cours + QMessageBox::StandardButton answer = QET::QetMessageBox::question( + this, + tr("Enregistrer l'élément en cours ?", "dialog title"), + QString( + tr( + "Voulez-vous enregistrer l'élément %1 ?", + "dialog content - %1 is an element name" + ) + ).arg(m_elmt_scene -> names().name()), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Cancel + ); + bool result; + switch(answer) { + case QMessageBox::Cancel: { + result = false; + break; // l'utilisateur annule : echec de la fermeture + } + case QMessageBox::Yes: { + result = slot_save(); + break; // l'utilisateur dit oui : la reussite depend de l'enregistrement + } + default: { + result = true; // l'utilisateur dit non ou ferme le dialogue: c'est reussi + } + } + return(result); +} + +/** + Enleve et cache le widget affiche par le dock permettant d'editer les + parties. + @return le widget enleve, ou 0 s'il n'y avait pas de widget a enlever +*/ +QWidget *QETElementEditor::clearToolsDock() +{ + if (QWidget *previous_widget = m_tools_dock_stack -> widget(1)) { + m_tools_dock_stack -> removeWidget(previous_widget); + previous_widget -> setParent(nullptr); + previous_widget -> hide(); + return(previous_widget); + } + return(nullptr); +} + +/** + Exporte le document XML xml_document vers le presse-papier puis declenche + son collage dans l'editeur courant, avec selection de la zone de collage + @param xml_document Document XML a copier/coller + @see ElementView::pasteInArea +*/ +void QETElementEditor::copyAndPasteXml(const QDomDocument &xml_document) { + // accede au presse-papier + QClipboard *clipboard = QApplication::clipboard(); + + // genere la description XML de la selection + QString clipboard_content = xml_document.toString(4); + + // met la description XML dans le presse-papier + if (clipboard -> supportsSelection()) { + clipboard -> setText(clipboard_content, QClipboard::Selection); + } + clipboard -> setText(clipboard_content); + + m_view -> pasteInArea(); +} + +/** + Permet de quitter l'editeur lors de la fermeture de la fenetre principale + @param qce Le QCloseEvent correspondant a l'evenement de fermeture +*/ +void QETElementEditor::closeEvent(QCloseEvent *qce) { + if (canClose()) { + writeSettings(); + setAttribute(Qt::WA_DeleteOnClose); + m_elmt_scene -> reset(); + qce -> accept(); + } + else { + qce -> ignore(); + } +} + +/** + Executed the first time the window editor is displayed. +*/ +void QETElementEditor::firstActivation(QEvent *event) { + Q_UNUSED(event) + QTimer::singleShot(250, m_view, SLOT(zoomFit())); +} + +/** + Remplit la liste des parties +*/ +void QETElementEditor::slot_createPartsList() +{ + m_parts_list -> blockSignals(true); + m_parts_list -> clear(); + QList qgis = m_elmt_scene -> zItems(); + + // on ne construit plus la liste a partir de 200 primitives + // c'est ingerable : la maj de la liste prend trop de temps et le resultat + // est inexploitable + if (qgis.count() <= QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST) { + for (int j = qgis.count() - 1 ; j >= 0 ; -- j) { + QGraphicsItem *qgi = qgis[j]; + if (CustomElementPart *cep = dynamic_cast(qgi)) { + QString part_desc = cep -> name(); + QListWidgetItem *qlwi = new QListWidgetItem(part_desc); + QVariant v; +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove + v.setValue(qgi); +#else +#if TODO_LIST +#pragma message("@TODO remove code for QT 6 or later") +#endif + qDebug()<<"Help code for QT 6 or later"; +#endif + qlwi -> setData(42, v); + m_parts_list -> addItem(qlwi); + qlwi -> setSelected(qgi -> isSelected()); + } + } + } + else { + m_parts_list -> addItem(new QListWidgetItem(tr("Trop de primitives, liste non générée."))); + } + m_parts_list -> blockSignals(false); +} + +/** + Met a jour la selection dans la liste des parties +*/ +void QETElementEditor::slot_updatePartsList() +{ + int items_count = m_elmt_scene -> items().count(); + if (m_parts_list -> count() != items_count) { + slot_createPartsList(); + } + else if (items_count <= QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST) { + m_parts_list -> blockSignals(true); + int i = 0; + QList items = m_elmt_scene -> zItems(); + for (int j = items.count() - 1 ; j >= 0 ; -- j) { + QGraphicsItem *qgi = items[j]; + QListWidgetItem *qlwi = m_parts_list -> item(i); + if (qlwi) qlwi -> setSelected(qgi -> isSelected()); + ++ i; + } + m_parts_list -> blockSignals(false); + } +} + +/** + Met a jour la selection des parties de l'element a partir de la liste des + parties +*/ +void QETElementEditor::slot_updateSelectionFromPartsList() +{ + m_elmt_scene -> blockSignals(true); + m_parts_list -> blockSignals(true); + for (int i = 0 ; i < m_parts_list -> count() ; ++ i) { + QListWidgetItem *qlwi = m_parts_list -> item(i); + QGraphicsItem *qgi = qlwi -> data(42).value(); + if (qgi) { + qgi -> setSelected(qlwi -> isSelected()); + } + } + m_parts_list -> blockSignals(false); + m_elmt_scene -> blockSignals(false); + slot_updateInformations(); + slot_updateMenus(); +} + +/** + @brief QETElementEditor::readSettings + Read settings +*/ +void QETElementEditor::readSettings() +{ + QSettings settings; + + // dimensions et position de la fenetre + QVariant geometry = settings.value("elementeditor/geometry"); + if (geometry.isValid()) { + restoreGeometry(geometry.toByteArray()); + } + + // etat de la fenetre (barres d'outils, docks...) + QVariant state = settings.value("elementeditor/state"); + if (state.isValid()) { + restoreState(state.toByteArray()); + } + + // informations complementaires de l'element : valeur par defaut + m_elmt_scene -> setInformations(settings.value("elementeditor/default-informations", "").toString()); +} + +/** + @brief QETElementEditor::writeSettings + Write the settings +*/ +void QETElementEditor::writeSettings() +{ + QSettings settings; + settings.setValue("elementeditor/geometry", saveGeometry()); + settings.setValue("elementeditor/state", saveState()); +} + +/** + @return les decalages horizontaux et verticaux (sous la forme d'un point) a + utiliser lors d'un copier/coller avec decalage. +*/ +QPointF QETElementEditor::pasteOffset() +{ + QPointF paste_offset(5.0, 0.0); + return(paste_offset); +} + +/** + Demande a l'utilisateur d'ouvrir un fichier sense etre un element. + @param parent QWidget parent du dialogue d'ouverture de fichier + @param initial_dir Repertoire a afficher initialement - si une chaine vide + est fournie, QETApp::customElementsDir() sera utilise. + @return Le chemin du fichier choisi ou une chaine vide si l'utilisateur a + clique sur le bouton "Annuler". + @see QETApp::customElementsDir() +*/ +QString QETElementEditor::getOpenElementFileName(QWidget *parent, const QString &initial_dir) { + // demande un nom de fichier a ouvrir a l'utilisateur + QString user_filename = QFileDialog::getOpenFileName( + parent, + tr("Ouvrir un fichier", "dialog title"), + initial_dir.isEmpty() ? QETApp::customElementsDir() : initial_dir, + tr( + "Éléments QElectroTech (*.elmt);;" + "Fichiers XML (*.xml);;" + "Tous les fichiers (*)", + "filetypes allowed when opening an element file" + ) + ); + return(user_filename); +} + +/** + @brief QETElementEditor::fromLocation + Location of the element to edit + @param location +*/ +void QETElementEditor::fromLocation(const ElementsLocation &location) { + if (!location.isElement()) { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content")); + return; + } + if (!location.exist()) { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("L'élément n'existe pas.", "message box content")); + return; + } + + //The file must be an xml document + QDomDocument document_xml; + QDomNode node = document_xml.importNode(location.xml(), true); + document_xml.appendChild(node); + + //Load the element + m_elmt_scene -> fromXml(document_xml); + slot_createPartsList(); + + //location is read only + if (!location.isWritable()) { + QET::QetMessageBox::warning(this, + tr("Édition en lecture seule", "message box title"), + tr("Vous n'avez pas les privilèges nécessaires pour modifier cet élement. Il sera donc ouvert en lecture seule.", "message box content")); + setReadOnly(true); + } + else { + setReadOnly(false); + } + + setLocation(location); + slot_updateMenus(); +} + +/** + Demande un fichier a l'utilisateur, l'ouvre en tant que fichier element, + met son contenu dans le presse-papiers, et appelle ElementView::PasteInArea +*/ +void QETElementEditor::pasteFromFile() +{ + // demande le chemin du fichier a ouvrir a l'utilisateur + QString element_file_path = getOpenElementFileName(this); + if (element_file_path.isEmpty()) { + return; + } + + QString error_message; + QDomDocument xml_document; + QFile element_file(element_file_path); + // le fichier doit etre lisible + if (!element_file.open(QIODevice::ReadOnly)) { + error_message = QString(tr("Impossible d'ouvrir le fichier %1.", "message box content")).arg(element_file_path); + } + else { + // le fichier doit etre un document XML + if (!xml_document.setContent(&element_file)) { + error_message = tr("Ce fichier n'est pas un document XML valide", "message box content"); + } + element_file.close(); + } + + if (!error_message.isEmpty()) { + QET::QetMessageBox::critical(this, tr("Erreur", "toolbar title"), error_message); + } + copyAndPasteXml(xml_document); +} + +/** + @brief QETElementEditor::pasteFromElement + Ask an element to user, copy the xml definition of the element + to the clipboard and call ElementView::PasteInArea +*/ +void QETElementEditor::pasteFromElement() +{ + //Ask for a location + ElementsLocation location = ElementDialog::getOpenElementLocation(this); + if (location.isNull()) { + return; + } + + if (!location.isElement()) { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content")); + return; + } + if (!location.exist()) { + QET::QetMessageBox::critical(this, + tr("Élément inexistant.", "message box title"), + tr("L'élément n'existe pas.", "message box content")); + return; + } + + //Create an xml document from the location xml + QDomDocument document_xml; + QDomNode node = document_xml.importNode(location.xml(), true); + document_xml.appendChild(node); + + copyAndPasteXml(document_xml); +} + +/** + Met a jour l'editeur de primitive actuellement visible. + Si aucun editeur de primitive n'est visible, ce slot ne fait rien. +*/ +void QETElementEditor::updateCurrentPartEditor() +{ + // si aucun widget d'edition n'est affiche, on ne fait rien + if (!m_tools_dock_stack -> currentIndex()) { + return; + } + + // s'il y a un widget d'edition affiche, on le met a jour + if (ElementItemEditor *current_editor = dynamic_cast(m_tools_dock_stack -> widget(1))) { + current_editor -> updateForm(); + } +} diff --git a/sources/editor/qetelementeditor.h b/sources/editor/qetelementeditor.h new file mode 100644 index 000000000..ce8ec243c --- /dev/null +++ b/sources/editor/qetelementeditor.h @@ -0,0 +1,189 @@ +/* + 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 . +*/ +#ifndef CUSTOM_ELEMENT_EDITOR_H +#define CUSTOM_ELEMENT_EDITOR_H +#include "../ElementsCollection/elementslocation.h" +#include "../qet.h" +#include "../qetmainwindow.h" +#include "elementscene.h" + +class ElementItemEditor; +class ElementView; + +/** + This class represents an element editor, allowing users to draw, change and + configure a particular electrical element. +*/ +class QETElementEditor : public QETMainWindow { + Q_OBJECT + + // constructor, destructor + public: + QETElementEditor(QWidget * = nullptr); + ~QETElementEditor() override; + private: + QETElementEditor(const QETElementEditor &); + void setupActions(); + void setupMenus(); + void setupInterface(); + + // attributes + private: + /// whether the editor is "read-only" + bool read_only; + /// menus + QMenu *file_menu, *edit_menu, *paste_from_menu, *display_menu, *tools_menu; + /// view widget for the editing scene + ElementView *m_view; + /// editing scene + ElementScene *m_elmt_scene; + /// container for widgets dedicated to primitive edition + QDockWidget *m_tools_dock; + /// Stack of widgets for tools_dock + QStackedWidget *m_tools_dock_stack; + /// label displayed when several primitives are selected + QLabel *m_default_informations; + /// Hash associating primitive names with their matching edition widget + QHash m_editors; + /// container for the undo list + QDockWidget *m_undo_dock; + /// Container for the list of existing primitives + QDockWidget *m_parts_dock; + /// List of primitives + QListWidget *m_parts_list; + /// actions for the "file" menu + QAction *new_element, *open, *open_dxf, *open_file, *save, *save_as, *save_as_file, *reload, *quit; + /// actions for the "edit" menu + QAction *selectall, *deselectall, *inv_select; + QAction *cut, *copy, *paste, *paste_in_area, *paste_from_file, *paste_from_elmt; + QAction *undo, *redo; + QAction *edit_delete, *edit_size_hs, *edit_names, *edit_author, *m_edit_properties; + /// toolbars + QToolBar *parts_toolbar, *main_toolbar, *view_toolbar, *depth_toolbar, *element_toolbar; + /// Action group + QActionGroup *parts, *m_zoom_ag, *m_depth_action_group; + /// minimum window title + QString min_title; + /// filename of the currently edited element + QString filename_; + /// location of the currently edited element + ElementsLocation location_; + /// whether the currently edited element comes from a file or a location + bool opened_from_file; + + // methods + public: + void setNames(const NamesList &); + void setLocation(const ElementsLocation &); + ElementsLocation location() const; + void setFileName(const QString &); + QString fileName() const; + void setReadOnly(bool); + bool isReadOnly() const; + void fromFile(const QString &); + void fromLocation(const ElementsLocation &); + bool toFile(const QString &); + bool toLocation(const ElementsLocation &location); + bool isEditing(const ElementsLocation &); + bool isEditing(const QString &); + ElementScene *elementScene() const; + void readSettings(); + void writeSettings(); + static QPointF pasteOffset(); + static QString getOpenElementFileName(QWidget * = nullptr, const QString & = QString()); + void contextMenu(QPoint p, QList actions = QList()); + + signals: + void saveToLocation(ElementsLocation loc); + + protected: + void closeEvent(QCloseEvent *) override; + void firstActivation(QEvent *) override; + + private: + bool canClose(); + QWidget *clearToolsDock(); + void copyAndPasteXml(const QDomDocument &); + + public slots: + void addLine(); + void addRect(); + void addEllipse(); + void addPolygon(); + void addArc(); + void addText(); + void addTerminal(); + void addDynamicTextField(); + void UncheckAddPrimitive(); + + void slot_new(); + void slot_open(); + void slot_openDxf(); + void slot_openFile(); + void openRecentFile(const QString &); + void openElement(const QString &); + void slot_reload(); + bool slot_save(); + bool slot_saveAs(); + bool slot_saveAsFile(); + void slot_setRubberBandToView(); + void slot_setNoDragToView(); + void slot_updateInformations(); + void slot_updateMenus(); + void slot_updateTitle(); + void slot_createPartsList(); + void slot_updatePartsList(); + void slot_updateSelectionFromPartsList(); + bool checkElement(); + void pasteFromFile(); + void pasteFromElement(); + void updateCurrentPartEditor(); +}; + +/** + @param nameslist the new list of names for the currently edited element +*/ +inline void QETElementEditor::setNames(const NamesList &nameslist) { + m_elmt_scene -> setNames(nameslist); +} + +/** + @return the location of the currently edited element +*/ +inline ElementsLocation QETElementEditor::location() const +{ + return(location_); +} + +/** + @return the filename of the currently edited element +*/ +inline QString QETElementEditor::fileName() const +{ + return(filename_); +} + +/** + @return the editing scene +*/ +inline ElementScene *QETElementEditor::elementScene() const +{ + return(m_elmt_scene); +} + +#endif diff --git a/sources/editor/ui/dynamictextfieldeditor.cpp b/sources/editor/ui/dynamictextfieldeditor.cpp index 49cc20ade..8471de8b7 100644 --- a/sources/editor/ui/dynamictextfieldeditor.cpp +++ b/sources/editor/ui/dynamictextfieldeditor.cpp @@ -24,8 +24,7 @@ #include "../../qetinformation.h" #include "../../ui/alignmenttextdialog.h" #include "../../ui/compositetexteditdialog.h" -#include "../ui/qetelementeditor.h" -#include "../elementscene.h" +#include "../qetelementeditor.h" #include "ui_dynamictextfieldeditor.h" #include diff --git a/sources/editor/ui/qetelementeditor.cpp b/sources/editor/ui/qetelementeditor.cpp deleted file mode 100644 index ec79a0739..000000000 --- a/sources/editor/ui/qetelementeditor.cpp +++ /dev/null @@ -1,1480 +0,0 @@ -/* - Copyright 2006-2021 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 "qetelementeditor.h" -#include "ui_qetelementeditor.h" -#include "../elementscene.h" -#include "../../qeticons.h" -#include "../elementview.h" -#include "../../qetmessagebox.h" -#include "../../qetapp.h" -#include "../../recentfiles.h" -#include "../graphicspart/customelementpart.h" -#include "../elementitemeditor.h" -#include "../styleeditor.h" -#include "../esevent/eseventaddline.h" -#include "../esevent/eseventaddrect.h" -#include "../esevent/eseventaddellipse.h" -#include "../esevent/eseventaddpolygon.h" -#include "../esevent/eseventaddarc.h" -#include "../esevent/eseventaddtext.h" -#include "../esevent/eseventaddterminal.h" -#include "../esevent/eseventadddynamictextfield.h" -#include "../../elementdialog.h" -#include "../graphicspart/partterminal.h" -#include "../arceditor.h" -#include "ellipseeditor.h" -#include "lineeditor.h" -#include "polygoneditor.h" -#include "rectangleeditor.h" -#include "../terminaleditor.h" -#include "texteditor.h" -#include "dynamictextfieldeditor.h" -#include "../../newelementwizard.h" -#include "../editorcommands.h" - -#include -#include - -/** - Number max of primitive displayed by the parts list widget - */ -#define QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST 200 - -/** - * @brief QETElementEditor::QETElementEditor - * @param parent - */ -QETElementEditor::QETElementEditor(QWidget *parent) : - QMainWindow(parent), - ui(new Ui::QETElementEditor) -{ - ui->setupUi(this); - initGui(); - setupActions(); - setupConnection(); - - auto menu = createPopupMenu(); - menu->setTearOffEnabled(true); - menu->setTitle(tr("Afficher", "menu entry")); - menu->setIcon(QET::Icons::ConfigureToolbars); - ui->m_display_menu->addMenu(menu); - //ui->m_display_menu->insertMenu(ui->m_zoom_in_action, menu); - - setWindowState(Qt::WindowMaximized); - readSettings(); - show(); -} - -/** - * @brief QETElementEditor::~QETElementEditor - */ -QETElementEditor::~QETElementEditor() -{ - delete ui; - qDeleteAll(m_editors.begin(), m_editors.end()); -} - -/** - * @brief QETElementEditor::contextMenu - * Display a context menu, with all available action. - * @param p : the pos of the menu, in screen coordinate - * @param actions : a list of actions who can be prepended to the context menu. - */ -void QETElementEditor::contextMenu(QPoint p, QList actions) -{ - QMenu menu(this); - menu.addActions(std::move(actions)); - menu.addSeparator(); - menu.addAction(m_undo_action); - menu.addAction(m_redo_action); - menu.addAction(ui->m_select_all_act); - menu.addAction(ui->m_deselect_all_action); - menu.addAction(ui->m_revert_selection_action); - menu.addSeparator(); - menu.addAction(ui->m_delete_action); - menu.addAction(ui->m_cut_action); - menu.addAction(ui->m_copy_action); - menu.addSeparator(); - menu.addAction(ui->m_paste_action); - menu.addAction(ui->m_paste_in_area_action); - menu.addMenu(ui->m_paste_from_menu); - menu.addSeparator(); - menu.addActions(m_depth_action_group -> actions()); - - //Remove from the context menu the actions which are disabled. - const QListmenu_actions = menu.actions(); - for(QAction *action : menu_actions) { - if(!action -> isEnabled()) { - menu.removeAction(action); - } - } - menu.exec(p); -} - -/** - * @brief QETElementEditor::setNames - * Set the names list of the edited element - * @param name_list - */ -void QETElementEditor::setNames(const NamesList &name_list) -{ - m_elmt_scene->setNames(name_list); -} - -/** - * @brief QETElementEditor::setLocation - * Set the location to edit - * @param location - */ -void QETElementEditor::setLocation(const ElementsLocation &location) -{ - m_location = location; - m_opened_from_file = false; - setReadOnly(!location.isWritable()); - updateTitle(); - -} - -/** - * @brief QETElementEditor::location - * @return The location of the edited element - */ -ElementsLocation QETElementEditor::location() const { - return m_location; -} - -/** - * @brief QETElementEditor::setFileName - * Set the file name of the edited element - * @param file_name - */ -void QETElementEditor::setFileName(const QString &file_name) -{ - m_file_name = file_name; - m_opened_from_file = true; - bool must_be_read_only = !QFileInfo(file_name).isWritable(); - if (isReadOnly() != must_be_read_only) { - setReadOnly(must_be_read_only); - } - updateTitle(); -} - -/** - * @brief QETElementEditor::fileName - * @return the file name of this element - */ -QString QETElementEditor::fileName() const { - return m_file_name; -} - -void QETElementEditor::setReadOnly(bool ro) -{ - m_read_only = ro; - m_view->setInteractive(!ro); - updateAction(); -} - -bool QETElementEditor::isReadOnly() const { - return m_read_only; -} - -/** - * @brief QETElementEditor::fromFile - * Open an element from @filepath - * @param filepath - */ -void QETElementEditor::fromFile(const QString &filepath) -{ - bool state_ = true; - QString error_message; - - - QFileInfo infos_file(filepath); - if (!infos_file.exists() || !infos_file.isFile()) - { - state_ = false; - error_message = QString(tr("Le fichier %1 n'existe pas.", "message box content")).arg(filepath); - } - - QFile file(filepath); - if (state_ && !file.open(QIODevice::ReadOnly)) { - state_ = false; - error_message = QString(tr("Impossible d'ouvrir le fichier %1.", "message box content")).arg(filepath); - } - - QDomDocument document_xml; - if (state_) { - if (!document_xml.setContent(&file)) { - state_ = false; - error_message = tr("Ce fichier n'est pas un document XML valide", "message box content"); - } - file.close(); - } - - if (!state_) { - QET::QetMessageBox::critical(this, tr("Erreur", "toolbar title"), error_message); - return; - } - - m_elmt_scene -> fromXml(document_xml); - fillPartsList(); - - if (!infos_file.isWritable()) - { - QET::QetMessageBox::warning( - this, - tr("Édition en lecture seule", "message box title"), - tr("Vous n'avez pas les privilèges nécessaires pour modifier cet élement. Il sera donc ouvert en lecture seule.", "message box content") - ); - setReadOnly(true); - } - else { - setReadOnly(false); - } - - // memorise le fichier - setFileName(filepath); - QETApp::elementsRecentFiles() -> fileWasOpened(filepath); - updateAction(); -} - -/** - * @brief QETElementEditor::toFile - * Save to a file the current edited element - * @param filepath : path of the file - * @return true if success - */ -bool QETElementEditor::toFile(const QString &filepath) -{ - m_elmt_scene -> clearEventInterface(); - m_elmt_scene -> clearSelection(); - UncheckAddPrimitive(); - - QDomDocument element_xml = m_elmt_scene -> toXml(); - bool writing = QET::writeXmlFile(element_xml, filepath); - if (!writing) { - QET::QetMessageBox::warning( - this, - tr("Erreur", "message box title"), - tr("Impossible d'écrire dans ce fichier", "message box content") - ); - } - return(writing); -} - -/** - * @brief QETElementEditor::fromLocation - * Location of an element to edit. - */ -void QETElementEditor::fromLocation(const ElementsLocation &location) -{ - if (!location.isElement()) { - QET::QetMessageBox::critical(this, - tr("Élément inexistant.", "message box title"), - tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content")); - return; - } - if (!location.exist()) { - QET::QetMessageBox::critical(this, - tr("Élément inexistant.", "message box title"), - tr("L'élément n'existe pas.", "message box content")); - return; - } - - //The file must be an xml document - QDomDocument document_xml; - QDomNode node = document_xml.importNode(location.xml(), true); - document_xml.appendChild(node); - - //Load the element - m_elmt_scene -> fromXml(document_xml); - fillPartsList(); - - //location is read only - if (!location.isWritable()) { - QET::QetMessageBox::warning(this, - tr("Édition en lecture seule", "message box title"), - tr("Vous n'avez pas les privilèges nécessaires pour modifier cet élement. Il sera donc ouvert en lecture seule.", "message box content")); - setReadOnly(true); - } - else { - setReadOnly(false); - } - - setLocation(location); - updateAction(); -} - -/** - * @brief QETElementEditor::toLocation - * Save the edited element into @location - * @param location - * @return true if succesfully saved - */ -bool QETElementEditor::toLocation(const ElementsLocation &location) -{ - m_elmt_scene -> clearEventInterface(); - m_elmt_scene -> clearSelection(); - UncheckAddPrimitive(); - - if (!location.setXml(m_elmt_scene -> toXml())) { - QET::QetMessageBox::critical(this, - tr("Erreur", "message box title"), - tr("Impossible d'enregistrer l'élément", "message box content")); - return(false); - } - return(true); -} - -/** - * @brief QETElementEditor::isEditing - * @param location - * @return true if this editor is currently - * editing element of location - */ -bool QETElementEditor::isEditing(const ElementsLocation &location) -{ - if (m_opened_from_file) - { - auto r = QET::compareCanonicalFilePaths( - m_file_name, - QETApp::realPath(location.toString())); - return r; - } - else { - return(location == m_location); - } -} - -/** - * @brief QETElementEditor::isEditing - * @param filepath - * @return true if this editor is currently - * editing element at filepath. - */ -bool QETElementEditor::isEditing(const QString &filepath) -{ - QString current_filepath; - if (m_opened_from_file) { - current_filepath = m_file_name; - } else { - current_filepath = QETApp::realPath(m_location.toString()); - } - - auto r = QET::compareCanonicalFilePaths( - current_filepath, - filepath); - return r; -} - -/** - * @brief QETElementEditor::elementScene - * @return - */ -ElementScene *QETElementEditor::elementScene() const { - return m_elmt_scene; -} - -/** - * @brief QETElementEditor::elementView - * @return - */ -ElementView *QETElementEditor::elementView() const { - return m_view; -} - -/** - * @brief QETElementEditor::pasteOffset - * @return the vertical and horizontal paste offset - */ -QPointF QETElementEditor::pasteOffset() -{ - QPointF paste_offset(5.0, 0.0); - return(paste_offset); -} - -/** - * @brief QETElementEditor::getOpenElementFileName - * Ask user to open a file who must be an element. - * @param parent - * @param dir - * @return - */ -QString QETElementEditor::getOpenElementFileName(QWidget *parent, const QString &dir) -{ - QString user_filename = QFileDialog::getOpenFileName( - parent, - tr("Ouvrir un fichier", "dialog title"), - dir.isEmpty() ? QETApp::customElementsDir() : dir, - tr( - "Éléments QElectroTech (*.elmt);;" - "Fichiers XML (*.xml);;" - "Tous les fichiers (*)", - "filetypes allowed when opening an element file" - ) - ); - return(user_filename); -} - -/** - * @brief QETElementEditor::updateTitle - * Update the title of the windows - */ -void QETElementEditor::updateTitle() -{ - QString title = m_min_title; - title += " - " + m_elmt_scene -> names().name() + " "; - if (!m_file_name.isEmpty() || !m_location.isNull()) { - if (!m_elmt_scene -> undoStack().isClean()) { - title += tr("[Modifié]", "window title tag"); - } - } - if (isReadOnly()) { - title += tr(" [lecture seule]", "window title tag"); - } - setWindowTitle(title); -} - -/** - * @brief QETElementEditor::fillPartsList - */ -void QETElementEditor::fillPartsList() -{ - m_parts_list -> blockSignals(true); - m_parts_list -> clear(); - QList qgis = m_elmt_scene -> zItems(); - - if (qgis.count() <= QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST) - { - for (int j = qgis.count() - 1 ; j >= 0 ; -- j) - { - QGraphicsItem *qgi = qgis[j]; - if (CustomElementPart *cep = dynamic_cast(qgi)) - { - QString part_desc = cep -> name(); - QListWidgetItem *qlwi = new QListWidgetItem(part_desc); - QVariant v; -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove - v.setValue(qgi); -#else -#if TODO_LIST -#pragma message("@TODO remove code for QT 6 or later") -#endif - qDebug()<<"Help code for QT 6 or later"; -#endif - qlwi -> setData(42, v); - m_parts_list -> addItem(qlwi); - qlwi -> setSelected(qgi -> isSelected()); - } - } - } - else { - m_parts_list -> addItem(new QListWidgetItem(tr("Trop de primitives, liste non générée."))); - } - m_parts_list -> blockSignals(false); -} - -/** - * @brief QETElementEditor::UncheckAddPrimitive - */ -void QETElementEditor::UncheckAddPrimitive() { - for (auto action : m_add_part_action_grp->actions()) { - action->setChecked(false); - } -} - -/** - * @brief QETElementEditor::updateCurrentPartEditor - */ -void QETElementEditor::updateCurrentPartEditor() -{ - if (!m_tools_dock_stack -> currentIndex()) { - return; - } - - if (ElementItemEditor *current_editor = dynamic_cast(m_tools_dock_stack -> widget(1))) { - current_editor -> updateForm(); - } -} - -/** - * @brief QETElementEditor::updateInformations - * Update the information and editor dock. - */ -void QETElementEditor::updateInformations() -{ - QList selected_qgis = m_elmt_scene -> selectedItems(); - if (selected_qgis.isEmpty()) - { - clearToolsDock(); - m_default_informations -> setText(tr("%n partie(s) sélectionnée(s).", - "", - selected_qgis.size())); - m_default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); - m_tools_dock_stack -> setCurrentIndex(0); - return; - } - - QList cep_list; - - CustomElementPart* part = dynamic_cast(selected_qgis.first()); - QString selection_xml_name = part -> xmlName(); - bool same_xml_name = true; - bool style_editable = true; - for (QGraphicsItem *qgi: selected_qgis) - { - if (CustomElementPart *cep = dynamic_cast(qgi)) { - cep_list << cep; - if (cep -> xmlName() != selection_xml_name) { - same_xml_name = false; - } - } - else { - style_editable = false; - same_xml_name = false; - } - } - if (style_editable) { - style_editable = StyleEditor::isStyleEditable(cep_list); - } - - if (same_xml_name) { - if (selection_xml_name == "terminal" || - selection_xml_name == "text" || - selection_xml_name == "dynamic_text" || - selection_xml_name == "line" || - selection_xml_name == "rect" || - selection_xml_name == "ellipse" || - selection_xml_name == "arc") { - clearToolsDock(); - //We add the editor widget - ElementItemEditor *editor = static_cast(m_editors[selection_xml_name]); - -#if TODO_LIST -#pragma message("@TODO Check if it takes longer than setting the parts again to the editor.") -#endif - // TODO: Check if it takes longer than setting the parts again to the editor. - bool equal = true; - QList parts = editor -> currentParts(); - if (parts.length() == cep_list.length()) { - for (auto cep: cep_list) { - bool part_found = false; - for (auto part: parts) { - if (part == cep) { - part_found = true; - break; - } - } - if (!part_found) { - equal = false; - break; - } - } - } - else { - equal = false; - } - - if (editor) { - bool success = true; - if (equal == false) { - success = editor -> setParts(cep_list); - } - if (success) { - m_tools_dock_stack -> insertWidget(1, editor); - m_tools_dock_stack -> setCurrentIndex(1); - } - else { - qDebug() << "Editor refused part."; - } - } - return; - } - else if (selection_xml_name == "polygon" && cep_list.length() == 1) { -#if TODO_LIST -#pragma message("@TODO maybe allowing multipart edit when number of points is the same?") -#endif - // multi edit for polygons makes no sense - // TODO: maybe allowing multipart edit when number of points is the same? - //We add the editor widget - clearToolsDock(); - ElementItemEditor *editor = static_cast(m_editors[selection_xml_name]); - CustomElementPart* part = editor -> currentPart(); - bool equal = part == cep_list.first(); - - if (editor) { - bool success = true; - if (equal == false) { - success = editor -> setPart(cep_list.first()); - } - if (success) { - m_tools_dock_stack -> insertWidget(1, editor); - m_tools_dock_stack -> setCurrentIndex(1); - } - else { - qDebug() << "Editor refused part."; - } - } - return; - - } - else { - qDebug() << "Multiedit not supported for: " << cep_list.first() -> xmlName(); - } - - } - - //There's several parts selecteds and all can be edited by style editor. - if (style_editable) { - clearToolsDock(); - ElementItemEditor *selection_editor = m_editors["style"]; - if (selection_editor) { - if (selection_editor -> setParts(cep_list)) { - m_tools_dock_stack -> insertWidget(1, selection_editor); - m_tools_dock_stack -> setCurrentIndex(1); - } - else { - qDebug() << "Editor refused part."; - } - } - } - //Else we only display the number of selected items - else { - clearToolsDock(); - m_default_informations -> setText(tr("%n partie(s) sélectionnée(s).", - "", - selected_qgis.size())); - m_default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); - m_tools_dock_stack -> setCurrentIndex(0); - } -} - -/** - * @brief QETElementEditor::updatePartsList - */ -void QETElementEditor::updatePartsList() -{ - int items_count = m_elmt_scene -> items().count(); - if (m_parts_list -> count() != items_count) { - fillPartsList(); - } - else if (items_count <= QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST) { - m_parts_list -> blockSignals(true); - int i = 0; - QList items = m_elmt_scene -> zItems(); - for (int j = items.count() - 1 ; j >= 0 ; -- j) { - QGraphicsItem *qgi = items[j]; - QListWidgetItem *qlwi = m_parts_list -> item(i); - if (qlwi) qlwi -> setSelected(qgi -> isSelected()); - ++ i; - } - m_parts_list -> blockSignals(false); - } -} - -/** - * @brief QETElementEditor::updateSelectionFromPartsList - */ -void QETElementEditor::updateSelectionFromPartsList() -{ - m_elmt_scene -> blockSignals(true); - m_parts_list -> blockSignals(true); - for (int i = 0 ; i < m_parts_list -> count() ; ++ i) { - QListWidgetItem *qlwi = m_parts_list -> item(i); - QGraphicsItem *qgi = qlwi -> data(42).value(); - if (qgi) { - qgi -> setSelected(qlwi -> isSelected()); - } - } - m_parts_list -> blockSignals(false); - m_elmt_scene -> blockSignals(false); - updateInformations(); - updateAction(); -} - -/** - * @brief QETElementEditor::checkElement - * Do several check about element - * @return true if there is no error - */ -bool QETElementEditor::checkElement() -{ - //List of warning and error - typedef QPair QETWarning; - QList warnings; - QList errors; - - // Warning #1: Element haven't got terminal - // (except for report, because report must have one terminal and this checking is do below) - if (!m_elmt_scene -> containsTerminals() && !m_elmt_scene -> elementType().contains("report")) { - warnings << qMakePair( - tr("Absence de borne", "warning title"), - tr( - "
En l'absence de borne, l'élément ne pourra être" - " relié à d'autres éléments par l'intermédiaire de conducteurs.", - "warning description" - ) - ); - } - - // Check folio report element - if (m_elmt_scene -> elementType().contains("report")) - { - int terminal =0; - - for(auto qgi : m_elmt_scene -> items()) { - if (qgraphicsitem_cast(qgi)) { - terminal ++; - } - } - - //Error folio report must have only one terminal - if (terminal != 1) { - errors << qMakePair (tr("Absence de borne"), - tr("
Erreur :" - "
Les reports de folio doivent posséder une seul borne." - "
Solution :" - "
Verifier que l'élément ne possède qu'une seul borne")); - } - } - - if (!errors.count() && !warnings.count()) { - return(true); - } - - // Display warnings - QString dialog_message = tr("La vérification de cet élément a généré", "message box content"); - - if (errors.size()) { - dialog_message += QString(tr(" %n erreur(s)", "errors", errors.size())); - } - - if (warnings.size()) { - if (errors.size()) { - dialog_message += QString (tr(" et")); - } - dialog_message += QString (tr(" %n avertissement(s)", "warnings", warnings.size())); - } - dialog_message += " :"; - - dialog_message += "
    "; - QList total = warnings << errors; - for(QETWarning warning : total) - { - dialog_message += "
  1. "; - dialog_message += QString( - tr("%1 : %2", "warning title: warning description") - ).arg(warning.first).arg(warning.second); - dialog_message += "
  2. "; - } - dialog_message += "
"; - - if (errors.size()) { - QMessageBox::critical(this, tr("Erreurs"), dialog_message); - } - else { - QMessageBox::warning(this, tr("Avertissements"), dialog_message); - } - - //if error == 0 that means they are only warning, we return true. - if (errors.count() == 0) { - return(true); - } - return false; -} - -/** - * @brief QETElementEditor::event - * @param event - * @return - */ -bool QETElementEditor::event(QEvent *event) -{ - if (m_first_activation && event->type() == QEvent::WindowActivate) { - m_first_activation = false; - QTimer::singleShot(250, m_view, SLOT(zoomFit())); - } - - return QMainWindow::event(event); -} - -/** - * @brief QETElementEditor::openElement - * OPen an element from @filepath - * @param filepath - */ -void QETElementEditor::openElement(const QString &filepath) -{ - if (filepath.isEmpty()) { - return; - } - // we have to test the file existence here because QETApp::openElementFiles() - // will discard non-existent files through QFileInfo::canonicalFilePath() - if (!QFile::exists(filepath)) { - QET::QetMessageBox::critical( - this, - tr("Impossible d'ouvrir le fichier", "message box title"), - QString( - tr("Il semblerait que le fichier %1 que vous essayez d'ouvrir" - " n'existe pas ou plus.") - ).arg(filepath) - ); - } - QETApp::instance() -> openElementFiles(QStringList() << filepath); -} - -/** - * @brief QETElementEditor::closeEvent - * @param qce - */ -void QETElementEditor::closeEvent(QCloseEvent *qce) -{ - if (canClose()) { - writeSettings(); - setAttribute(Qt::WA_DeleteOnClose); - m_elmt_scene -> reset(); - qce -> accept(); - } - else { - qce -> ignore(); - } -} - -/** - * @brief QETElementEditor::canClose - * @return - */ -bool QETElementEditor::canClose() -{ - if (m_elmt_scene -> undoStack().isClean()) { - return(true); - } - //First ask user to save - QMessageBox::StandardButton answer = QET::QetMessageBox::question( - this, - tr("Enregistrer l'élément en cours ?", "dialog title"), - QString( - tr( - "Voulez-vous enregistrer l'élément %1 ?", - "dialog content - %1 is an element name" - ) - ).arg(m_elmt_scene -> names().name()), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, - QMessageBox::Cancel - ); - - bool result; - switch(answer) { - case QMessageBox::Cancel: { - result = false; - break; - } - case QMessageBox::Yes: { - result = on_m_save_action_triggered(); - break; - } - default: { - result = true; - } - } - return(result); -} - -/** - * @brief QETElementEditor::readSettings - * Read some setting about this widget in the QSetting - * of qelectrotech - */ -void QETElementEditor::readSettings() -{ - QSettings settings; - - QVariant geometry = settings.value("elementeditor/geometry"); - if (geometry.isValid()) { - restoreGeometry(geometry.toByteArray()); - } - - QVariant state = settings.value("elementeditor/state"); - if (state.isValid()) { - restoreState(state.toByteArray()); - } - - m_elmt_scene->setInformations(settings.value("elementeditor/default-informations", "").toString()); -} - -/** - * @brief QETElementEditor::writeSettings - * Write some setting of this widget in the - * QSetting of qelectrotech - */ -void QETElementEditor::writeSettings() const -{ - QSettings settings; - settings.setValue("elementeditor/geometry", saveGeometry()); - settings.setValue("elementeditor/state", saveState()); -} - -/** - * @brief QETElementEditor::setupActions - */ -void QETElementEditor::setupActions() -{ -#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) - ui->m_open_dxf_action -> setStatusTip(tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" - "\n" - ">> Install on Windows\n" - "Put DXFtoQET.exe binary on C:\\Users\\user_name\\AppData\\Roaming\\qet\\ directory \n" - )); -#elif defined(Q_OS_MAC) - ui->m_open_dxf_action -> setStatusTip(tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" - "\n" - ">> Install on macOSX\n" - "Put DXFtoQET.app binary on /Users/user_name/.qet/ directory \n" - )); -#else - ui->m_open_dxf_action -> setStatusTip(tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" - "\n" - ">> Install on Linux\n" - "Put DXFtoQET binary on your /home/user_name/.qet/ directory\n" - "make it executable : chmod +x ./DXFtoQET\n" - )); -#endif - - ui->m_open_dxf_action -> setWhatsThis (tr("To install the plugin DXFtoQET\nVisit https://download.tuxfamily.org/qet/builds/dxf_to_elmt/\n" - "\n" - ">> Install on Linux\n" - "Put DXFtoQET binary on your /home/user_name/.qet/ directory\n" - "make it executable : chmod +x ./DXFtoQET\n" - ">> Install on Windows\n" - "Put DXFtoQET.exe binary on C:\\Users\\user_name\\AppData\\Roaming\\qet\\ directory \n" - "\n" - ">> Install on macOSX\n" - "Put DXFtoQET.app binary on /Users/user_name/.qet/ directory \n" - )); - - m_undo_action = m_elmt_scene -> undoStack().createUndoAction(this, tr("Annuler")); - m_redo_action = m_elmt_scene -> undoStack().createRedoAction(this, tr("Refaire")); - m_undo_action -> setIcon(QET::Icons::EditUndo); - m_redo_action -> setIcon(QET::Icons::EditRedo); - m_undo_action -> setShortcuts(QKeySequence::Undo); - m_redo_action -> setShortcuts(QKeySequence::Redo); - ui->m_undo_toolbar->addAction(m_undo_action); - ui->m_undo_toolbar->addAction(m_redo_action); - - ui->m_new_action -> setShortcut(QKeySequence::New); - ui->m_open_action -> setShortcut(QKeySequence::Open); - ui->m_open_from_file_action -> setShortcut(tr("Ctrl+Shift+O")); - ui->m_save_action -> setShortcut(QKeySequence::Save); - ui->m_save_as_file_action -> setShortcut(tr("Ctrl+Shift+S")); - ui->m_quit_action -> setShortcut(QKeySequence(tr("Ctrl+Q"))); - ui->m_select_all_act -> setShortcut(QKeySequence::SelectAll); - ui->m_deselect_all_action -> setShortcut(QKeySequence(tr("Ctrl+Shift+A"))); - ui->m_revert_selection_action -> setShortcut(QKeySequence(tr("Ctrl+I"))); - ui->m_cut_action -> setShortcut(QKeySequence::Cut); - ui->m_copy_action -> setShortcut(QKeySequence::Copy); - ui->m_paste_action -> setShortcut(QKeySequence::Paste); - ui->m_paste_in_area_action -> setShortcut(tr("Ctrl+Shift+V")); - ui->m_edit_names_action -> setShortcut(QKeySequence(tr("Ctrl+E"))); - ui->m_edit_author_action -> setShortcut(tr("Ctrl+Y")); - -#ifndef Q_OS_MAC - ui->m_delete_action -> setShortcut(QKeySequence(Qt::Key_Delete)); -#else - ui->m_delete_action -> setShortcut(QKeySequence(tr("Backspace"))); -#endif - - //Depth action - m_depth_action_group = QET::depthActionGroup(this); - connect(m_depth_action_group, &QActionGroup::triggered, [this](QAction *action) { - this -> elementScene() -> undoStack().push( - new ChangeZValueCommand(this -> elementScene(), action -> data().value())); - emit(this -> elementScene() -> partsZValueChanged()); - }); - auto depth_toolbar = addToolBar(tr("Profondeur", "toolbar title")); - depth_toolbar -> setObjectName("depth_toolbar"); - depth_toolbar -> addActions(m_depth_action_group -> actions()); - addToolBar(Qt::TopToolBarArea, depth_toolbar); - - //Zoom action - ui->m_zoom_in_action -> setShortcut(QKeySequence::ZoomIn); - ui->m_zoom_out_action -> setShortcut(QKeySequence::ZoomOut); - ui->m_zoom_fit_best_action -> setShortcut(QKeySequence(tr("Ctrl+9"))); - ui->m_zoom_original_action -> setShortcut(QKeySequence(tr("Ctrl+0"))); - - //Add primitive actions - m_add_part_action_grp = new QActionGroup(this); - - auto *add_line = new QAction(QET::Icons::PartLine, tr("Ajouter une ligne"), m_add_part_action_grp); - auto *add_rectangle = new QAction(QET::Icons::PartRectangle, tr("Ajouter un rectangle"), m_add_part_action_grp); - auto *add_ellipse = new QAction(QET::Icons::PartEllipse, tr("Ajouter une ellipse"), m_add_part_action_grp); - auto *add_polygon = new QAction(QET::Icons::PartPolygon, tr("Ajouter un polygone"), m_add_part_action_grp); - auto *add_text = new QAction(QET::Icons::PartText, tr("Ajouter du texte"), m_add_part_action_grp); - auto *add_arc = new QAction(QET::Icons::PartArc, tr("Ajouter un arc de cercle"), m_add_part_action_grp); - auto *add_terminal = new QAction(QET::Icons::Terminal, tr("Ajouter une borne"), m_add_part_action_grp); - auto *add_dynamic_text_field = new QAction(QET::Icons::PartTextField, tr("Ajouter un champ texte dynamique"), m_add_part_action_grp); - - for (auto action : m_add_part_action_grp->actions()) { - action -> setCheckable(true); - } - - connect(add_line, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddLine(m_elmt_scene));}); - connect(add_rectangle, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddRect(m_elmt_scene));}); - connect(add_ellipse, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddEllipse(m_elmt_scene));}); - connect(add_polygon, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddPolygon(m_elmt_scene));}); - connect(add_text, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddText(m_elmt_scene));}); - connect(add_arc, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddArc(m_elmt_scene));}); - connect(add_terminal, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddTerminal(m_elmt_scene));}); - connect(add_dynamic_text_field, &QAction::triggered, [this]() {m_elmt_scene->setEventInterface(new ESEventAddDynamicTextField(m_elmt_scene));}); - - add_polygon -> setStatusTip(tr("Double-click pour terminer la forme, Click droit pour annuler le dernier point")); - add_text -> setStatusTip(tr("Ajouter un texte d'élément non éditable dans les schémas")); - add_dynamic_text_field -> setStatusTip(tr("Ajouter un texte d'élément pouvant être édité dans les schémas")); - - auto parts_toolbar = addToolBar(tr("Parties", "toolbar title")); - parts_toolbar -> setAllowedAreas(Qt::AllToolBarAreas); - parts_toolbar -> setObjectName("parts"); - parts_toolbar -> addActions(m_add_part_action_grp -> actions()); - addToolBar(Qt::LeftToolBarArea, parts_toolbar); -} - -/** - * @brief QETElementEditor::updateAction - * Update actions - */ -void QETElementEditor::updateAction() -{ - //Action disabled if read only - auto ro_list = m_add_part_action_grp->actions(); - ro_list << ui->m_select_all_act - << ui->m_revert_selection_action - << ui->m_paste_from_file_action - << ui->m_paste_from_element_action; - for (auto action : qAsConst(ro_list)) { - action->setDisabled(m_read_only); - } - - //Action enabled if a primitive is selected - auto select_list = m_depth_action_group->actions(); - select_list << ui->m_deselect_all_action - << ui->m_cut_action - << ui->m_copy_action - << ui->m_delete_action; - auto items_selected = !m_read_only && m_elmt_scene->selectedItems().count(); - for (auto action : qAsConst(select_list)) { - action->setEnabled(items_selected); - } - - //Action about clipboard - auto clipboard_contain_elmt = !m_read_only && ElementScene::clipboardMayContainElement(); - ui->m_paste_action->setEnabled(clipboard_contain_elmt); - ui->m_paste_in_area_action->setEnabled(clipboard_contain_elmt); - - //Action about undo stack status - ui->m_save_action-> setEnabled(!m_read_only && !m_elmt_scene->undoStack().isClean()); - m_undo_action -> setEnabled(!m_read_only && m_elmt_scene -> undoStack().canUndo()); - m_redo_action -> setEnabled(!m_read_only && m_elmt_scene -> undoStack().canRedo()); - -} - -/** - * @brief QETElementEditor::setupConnection - */ -void QETElementEditor::setupConnection() -{ - connect(m_elmt_scene, &ElementScene::partsAdded, this, &QETElementEditor::UncheckAddPrimitive); - connect(m_elmt_scene, &ElementScene::partsAdded, this, &QETElementEditor::fillPartsList); - connect(m_elmt_scene, &ElementScene::partsRemoved, this, &QETElementEditor::fillPartsList); - connect(m_elmt_scene, &ElementScene::partsZValueChanged, this, &QETElementEditor::fillPartsList); - connect(m_parts_list, &QListWidget::itemSelectionChanged, this, &QETElementEditor::updateSelectionFromPartsList); - connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &QETElementEditor::updateAction); - - connect(m_elmt_scene, &ElementScene::selectionChanged, [this]() { - this->updateInformations(); - this->updateAction(); - this->updatePartsList(); - }); - - connect(&(m_elmt_scene -> undoStack()), &QUndoStack::cleanChanged, [this]() { - this->updateAction(); - this->updateTitle(); - }); - - connect(&(m_elmt_scene -> undoStack()), &QUndoStack::indexChanged, [this]() { - this->updatePartsList(); - this->updateInformations(); - }); -} - -/** - * @brief QETElementEditor::initGui - */ -void QETElementEditor::initGui() -{ - m_editors["arc"] = new ArcEditor(this); - m_editors["ellipse"] = new EllipseEditor(this); - m_editors["line"] = new LineEditor(this); - m_editors["polygon"] = new PolygonEditor(this); - m_editors["rect"] = new RectangleEditor(this); - m_editors["terminal"] = new TerminalEditor(this); - m_editors["text"] = new TextEditor(this); - m_editors["style"] = new StyleEditor(this); - m_editors["dynamic_text"] = new DynamicTextFieldEditor(this); - - m_elmt_scene = new ElementScene(this, this); - m_view = new ElementView(m_elmt_scene, this); - m_view->setDragMode(QGraphicsView::RubberBandDrag); - setCentralWidget(m_view); - - //Part dock editor - m_default_informations = new QLabel(this); - m_tools_dock_stack = new QStackedWidget(this); - m_tools_dock_stack->insertWidget(0, m_default_informations); - ui->m_tools_dock->setWidget(m_tools_dock_stack); - - //Undo dock - auto undo_view = new QUndoView(&(m_elmt_scene->undoStack()), this); - undo_view->setEmptyLabel(tr("Aucune modification")); - ui->m_undo_dock->setWidget(undo_view); - - //parts list dock - m_parts_list = new QListWidget(this); - m_parts_list->setSelectionMode(QAbstractItemView::ExtendedSelection); - tabifyDockWidget(ui->m_undo_dock, ui->m_parts_dock); - ui->m_parts_dock->setWidget(m_parts_list); - - updateInformations(); - fillPartsList(); - - statusBar()->showMessage(tr("Éditeur d'éléments", "status bar message")); -} - -/** - * @brief QETElementEditor::clearToolsDock - * Remove and hide the widget displayed by - * the dock used to edit primitives - * @return Return the removed widget or nullptr if there is no widget to remove. - */ -QWidget *QETElementEditor::clearToolsDock() -{ - if (QWidget *previous_widget = m_tools_dock_stack -> widget(1)) { - m_tools_dock_stack -> removeWidget(previous_widget); - previous_widget -> setParent(nullptr); - previous_widget -> hide(); - return(previous_widget); - } - return(nullptr); -} - -/** - * @brief QETElementEditor::copyAndPasteXml - * Copy the content of @xml_document to the clipboard - * and call pasteInArea method of elementView. - * @param xml_document - */ -void QETElementEditor::copyAndPasteXml(const QDomDocument &xml_document) -{ - QClipboard *clipboard = QApplication::clipboard(); - QString clipboard_content = xml_document.toString(4); - - if (clipboard -> supportsSelection()) { - clipboard -> setText(clipboard_content, QClipboard::Selection); - } - clipboard -> setText(clipboard_content); - - m_view -> pasteInArea(); -} - -/** - * @brief QETElementEditor::on_m_save_action_triggered - * @return - */ -bool QETElementEditor::on_m_save_action_triggered() -{ - if (checkElement()) - { - if (m_opened_from_file) - { - if (m_file_name.isEmpty()) { - return(on_m_save_as_action_triggered()); - } - - //Else wa save to the file at filename_ path - bool result_save = toFile(m_file_name); - if (result_save) m_elmt_scene -> undoStack().setClean(); - return(result_save); - } - else - { - if (m_location.isNull()) { - return(on_m_save_as_action_triggered()); - } - - //Else save to the known location - bool result_save = toLocation(m_location); - if (result_save) { - m_elmt_scene -> undoStack().setClean(); - emit saveToLocation(m_location); - } - return(result_save); - } - } - - QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); - return false; -} - -/** - * @brief QETElementEditor::on_m_save_as_action_triggered - * Ask a location to user and save the current edited element - * to this location - * @return true is success - */ -bool QETElementEditor::on_m_save_as_action_triggered() -{ - // Check element befor writing - if (checkElement()) { - //Ask a location to user - ElementsLocation location = ElementDialog::getSaveElementLocation(this); - if (location.isNull()) { - return(false); - } - - bool result_save = toLocation(location); - if (result_save) { - setLocation(location); - m_elmt_scene -> undoStack().setClean(); - emit saveToLocation(location); - } - - return(result_save); - } - QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); - return (false); -} - -void QETElementEditor::on_m_select_all_act_triggered() { - m_elmt_scene->slot_selectAll(); -} - -void QETElementEditor::on_m_edit_element_properties_action_triggered() { m_elmt_scene->slot_editProperties(); } - -void QETElementEditor::on_m_new_action_triggered() -{ - NewElementWizard new_element_wizard(this); - new_element_wizard.exec(); -} - -void QETElementEditor::on_m_open_action_triggered() -{ - ElementsLocation location = ElementDialog::getOpenElementLocation(this); - if (location.isNull()) { - return; - } - QETApp::instance() -> openElementLocations(QList() << location); -} - -void QETElementEditor::on_m_open_from_file_action_triggered() -{ - QString open_dir = m_file_name.isEmpty() ? QETApp::customElementsDir() : QDir(m_file_name).absolutePath(); - QString user_filename = QETElementEditor::getOpenElementFileName(this, open_dir); - openElement(user_filename); -} - -void QETElementEditor::on_m_open_dxf_action_triggered() -{ -#ifdef TODO_LIST -# pragma message("@TODO Merge 'DXF to GET-2020' code in to Qet") -# pragma message("https://github.com/qelectrotech/DXFtoQET-2020") -#endif -#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) - QString program = (QDir::homePath() + "/Application Data/qet/DXFtoQET.exe"); -#elif defined(Q_OS_MAC) - QString program = (QDir::homePath() + "/.qet/DXFtoQET.app"); -#else - QString program = (QDir::homePath() + "/.qet/DXFtoQET"); -#endif - QStringList arguments; - QProcess *DXF = new QProcess(qApp); - DXF -> start(program,arguments); -} - -bool QETElementEditor::on_m_save_as_file_action_triggered() -{ - // Check element befor writing - if (checkElement()) { - //Ask a filename to user, for save the element - QString fn = QFileDialog::getSaveFileName( - this, - tr("Enregistrer sous", "dialog title"), - m_file_name.isEmpty() ? QETApp::customElementsDir() : QDir(m_file_name).absolutePath(), - tr( - "Éléments QElectroTech (*.elmt)", - "filetypes allowed when saving an element file" - ) - ); - - if (fn.isEmpty()) { - return(false); - } - - //If the name doesn't end by .elmt, we add it - if (!fn.endsWith(".elmt", Qt::CaseInsensitive)) { - fn += ".elmt"; - } - - bool result_save = toFile(fn); - //If the save success, the filename is keep - if (result_save) { - setFileName(fn); - QETApp::elementsRecentFiles() -> fileWasOpened(fn); - m_elmt_scene -> undoStack().setClean(); - } - - return(result_save); - } - QMessageBox::critical(this, tr("Echec de l'enregistrement"), tr("L'enregistrement à échoué,\nles conditions requises ne sont pas valides")); - return false; -} - -void QETElementEditor::on_m_reload_action_triggered() -{ - //If user already edit the element, ask confirmation to reload - if (!m_elmt_scene -> undoStack().isClean()) { - QMessageBox::StandardButton answer = QET::QetMessageBox::question(this, - tr("Recharger l'élément", "dialog title"), - tr("Vous avez efffectué des modifications sur cet élément. Si vous le rechargez, ces modifications seront perdues. Voulez-vous vraiment recharger l'élément ?", "dialog content"), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, - QMessageBox::Cancel); - if (answer != QMessageBox::Yes){ - return; - } - } - - //Reload the element - m_elmt_scene -> reset(); - if (m_opened_from_file) { - fromFile(m_file_name); - } - else { - fromLocation(m_location); - } -} - -void QETElementEditor::on_m_quit_action_triggered() { close(); } - -void QETElementEditor::on_m_deselect_all_action_triggered() { m_elmt_scene->slot_deselectAll(); } - -void QETElementEditor::on_m_cut_action_triggered() { m_view->cut(); } - -void QETElementEditor::on_m_copy_action_triggered() { m_view->copy(); } - -void QETElementEditor::on_m_paste_action_triggered() { m_view->paste(); } - -void QETElementEditor::on_m_paste_in_area_action_triggered() { m_view->pasteInArea(); } - -void QETElementEditor::on_m_paste_from_file_action_triggered() -{ - QString element_file_path = getOpenElementFileName(this); - if (element_file_path.isEmpty()) { - return; - } - - QString error_message; - QDomDocument xml_document; - QFile element_file(element_file_path); - // le fichier doit etre lisible - if (!element_file.open(QIODevice::ReadOnly)) { - error_message = QString(tr("Impossible d'ouvrir le fichier %1.", "message box content")).arg(element_file_path); - } - else { - // le fichier doit etre un document XML - if (!xml_document.setContent(&element_file)) { - error_message = tr("Ce fichier n'est pas un document XML valide", "message box content"); - } - element_file.close(); - } - - if (!error_message.isEmpty()) { - QET::QetMessageBox::critical(this, tr("Erreur", "toolbar title"), error_message); - } - copyAndPasteXml(xml_document); -} - -void QETElementEditor::on_m_paste_from_element_action_triggered() -{ - //Ask for a location - ElementsLocation location = ElementDialog::getOpenElementLocation(this); - if (location.isNull()) { - return; - } - - if (!location.isElement()) { - QET::QetMessageBox::critical(this, - tr("Élément inexistant.", "message box title"), - tr("Le chemin virtuel choisi ne correspond pas à un élément.", "message box content")); - return; - } - if (!location.exist()) { - QET::QetMessageBox::critical(this, - tr("Élément inexistant.", "message box title"), - tr("L'élément n'existe pas.", "message box content")); - return; - } - - //Create an xml document from the location xml - QDomDocument document_xml; - QDomNode node = document_xml.importNode(location.xml(), true); - document_xml.appendChild(node); - - copyAndPasteXml(document_xml); -} - -void QETElementEditor::on_m_revert_selection_action_triggered() { m_elmt_scene->slot_invertSelection(); } - -void QETElementEditor::on_m_delete_action_triggered() { m_elmt_scene->slot_delete(); } - -void QETElementEditor::on_m_edit_names_action_triggered() { m_elmt_scene->slot_editNames(); } - -void QETElementEditor::on_m_edit_author_action_triggered() { m_elmt_scene->slot_editAuthorInformations(); } - -void QETElementEditor::on_m_zoom_in_action_triggered() { m_view->zoomIn(); } - -void QETElementEditor::on_m_zoom_out_action_triggered() { m_view->zoomOut(); } - -void QETElementEditor::on_m_zoom_fit_best_action_triggered() { m_view->zoomFit(); } - -void QETElementEditor::on_m_zoom_original_action_triggered() { m_view->zoomReset(); } - -void QETElementEditor::on_m_about_qet_action_triggered() { QETApp::instance()->aboutQET(); } - -void QETElementEditor::on_m_online_manual_triggered() { - QString link = "https://download.tuxfamily.org/qet/manual_0.7/build/index.html"; - QDesktopServices::openUrl(QUrl(link)); -} - -void QETElementEditor::on_m_youtube_action_triggered() { - QString link = "https://www.youtube.com/user/scorpio8101/videos"; - QDesktopServices::openUrl(QUrl(link)); -} - -void QETElementEditor::on_m_donate_action_triggered() { - QString link = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZZHC9D7C3MDPC"; - QDesktopServices::openUrl(QUrl(link)); -} - -void QETElementEditor::on_m_about_qt_action_triggered() { qApp->aboutQt(); } diff --git a/sources/editor/ui/qetelementeditor.h b/sources/editor/ui/qetelementeditor.h deleted file mode 100644 index ee0b5a221..000000000 --- a/sources/editor/ui/qetelementeditor.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - Copyright 2006-2021 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 QETELEMENTEDITOR_H -#define QETELEMENTEDITOR_H - -#include -#include "../../ElementsCollection/elementslocation.h" - -class ElementScene; -class QActionGroup; -class ElementItemEditor; -class ElementView; -class QListWidget; -class QStackedWidget; -class QLabel; - -namespace Ui { - class QETElementEditor; -} - -class QETElementEditor : public QMainWindow -{ - Q_OBJECT - signals: - void saveToLocation(ElementsLocation loc); - - public: - explicit QETElementEditor(QWidget *parent = nullptr); - ~QETElementEditor() override; - - void contextMenu(QPoint p, QList actions = QList()); - void setNames(const NamesList &name_list); - void setLocation(const ElementsLocation &location); - ElementsLocation location() const; - void setFileName(const QString &file_name); - QString fileName() const; - void setReadOnly(bool ro); - bool isReadOnly() const; - void fromFile(const QString &filepath); - bool toFile(const QString &filepath); - void fromLocation(const ElementsLocation &location); - bool toLocation(const ElementsLocation &location); - bool isEditing(const ElementsLocation &location); - bool isEditing(const QString &filepath); - ElementScene *elementScene() const; - ElementView *elementView() const; - static QPointF pasteOffset(); - static QString getOpenElementFileName(QWidget *parent = nullptr, const QString &dir = QString()); - void updateTitle(); - void fillPartsList(); - void UncheckAddPrimitive(); - void updateCurrentPartEditor(); - void updateInformations(); - void updatePartsList(); - void updateSelectionFromPartsList(); - void openElement(const QString &filepath); - bool checkElement(); - - protected: - bool event(QEvent *event) override; - void closeEvent(QCloseEvent *) override; - - - private slots: - bool on_m_save_action_triggered(); - bool on_m_save_as_action_triggered(); - void on_m_select_all_act_triggered(); - void on_m_edit_element_properties_action_triggered(); - void on_m_new_action_triggered(); - void on_m_open_action_triggered(); - void on_m_open_from_file_action_triggered(); - void on_m_open_dxf_action_triggered(); - bool on_m_save_as_file_action_triggered(); - void on_m_reload_action_triggered(); - void on_m_quit_action_triggered(); - void on_m_deselect_all_action_triggered(); - void on_m_cut_action_triggered(); - void on_m_copy_action_triggered(); - void on_m_paste_action_triggered(); - void on_m_paste_in_area_action_triggered(); - void on_m_paste_from_file_action_triggered(); - void on_m_paste_from_element_action_triggered(); - void on_m_revert_selection_action_triggered(); - void on_m_delete_action_triggered(); - void on_m_edit_names_action_triggered(); - void on_m_edit_author_action_triggered(); - void on_m_zoom_in_action_triggered(); - void on_m_zoom_out_action_triggered(); - void on_m_zoom_fit_best_action_triggered(); - void on_m_zoom_original_action_triggered(); - void on_m_about_qet_action_triggered(); - void on_m_online_manual_triggered(); - void on_m_youtube_action_triggered(); - void on_m_donate_action_triggered(); - void on_m_about_qt_action_triggered(); - - private: - bool canClose(); - void readSettings(); - void writeSettings() const; - void setupActions(); - void updateAction(); - void setupConnection(); - void initGui(); - QWidget *clearToolsDock(); - void copyAndPasteXml(const QDomDocument &xml_document); - - private: - Ui::QETElementEditor *ui; - - bool - m_read_only = false, - m_opened_from_file = false, - m_first_activation = true; - - ElementScene *m_elmt_scene = nullptr; - - QActionGroup - *m_add_part_action_grp = nullptr, - *m_depth_action_group = nullptr; - - QList m_context_menu_action_list; - - QAction - *m_undo_action = nullptr, - *m_redo_action = nullptr; - - - /// Hash associating primitive names with their matching edition widget - QHash m_editors; - - ElementsLocation m_location; - - QString - m_file_name, - m_min_title; - - ElementView *m_view = nullptr; - - QListWidget *m_parts_list = nullptr; - - QStackedWidget *m_tools_dock_stack = nullptr; - - QLabel *m_default_informations = nullptr; - -}; - -#endif // QETELEMENTEDITOR_H diff --git a/sources/editor/ui/qetelementeditor.ui b/sources/editor/ui/qetelementeditor.ui deleted file mode 100644 index d63959565..000000000 --- a/sources/editor/ui/qetelementeditor.ui +++ /dev/null @@ -1,496 +0,0 @@ - - - QETElementEditor - - - - 0 - 0 - 800 - 600 - - - - QElectroTech - Éditeur d'élément - - - - :/ico/16x16/qet.png:/ico/16x16/qet.png - - - - - - - 0 - 0 - 800 - 21 - - - - - &Fichier - - - - - - - - - - - - - - - - &Édition - - - - Coller depuis... - - - - :/ico/16x16/edit-paste.png:/ico/16x16/edit-paste.png - - - - - - - - - - - - - - - - - - - - - - - - Afficha&ge - - - - - - - - - - &Aide - - - - - - - - - - - - - - - - Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea - - - Annulations - - - 1 - - - - - - Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea - - - Parties - - - 2 - - - - - - Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea - - - Informations - - - 1 - - - - - - Outils - - - TopToolBarArea - - - false - - - - - - - - - - - Affichage - - - TopToolBarArea - - - false - - - - - - - - - Élément - - - TopToolBarArea - - - false - - - - - - - Annulation - - - TopToolBarArea - - - false - - - - - - :/ico/16x16/edit-select-all.png:/ico/16x16/edit-select-all.png - - - Tout sélectionner - - - - - - :/ico/22x22/document-new.png:/ico/22x22/document-new.png - - - &Nouveau - - - - - - :/ico/22x22/folder-open.png:/ico/22x22/folder-open.png - - - &Ouvrir - - - - - - :/ico/22x22/folder-open.png:/ico/22x22/folder-open.png - - - &Ouvrir depuis un fichier - - - - - - :/ico/16x16/run-dxf.png:/ico/16x16/run-dxf.png - - - &Lancer le plugin convertisseur DXF - - - - - - :/ico/22x22/document-save.png:/ico/22x22/document-save.png - - - &Enregistrer - - - - - - :/ico/22x22/document-save-as.png:/ico/22x22/document-save-as.png - - - Enregistrer sous - - - - - - :/ico/22x22/document-save.png:/ico/22x22/document-save.png - - - Enregistrer dans un fichier - - - - - - :/ico/22x22/view-refresh.png:/ico/22x22/view-refresh.png - - - Recharger - - - - - - :/ico/16x16/application-exit.png:/ico/16x16/application-exit.png - - - &Quitter - - - - - - :/ico/16x16/edit-select-none.png:/ico/16x16/edit-select-none.png - - - Désélectionner tout - - - - - - :/ico/16x16/edit-cut.png:/ico/16x16/edit-cut.png - - - Co&uper - - - - - - :/ico/16x16/edit-copy.png:/ico/16x16/edit-copy.png - - - Cop&ier - - - - - - :/ico/16x16/edit-paste.png:/ico/16x16/edit-paste.png - - - C&oller - - - - - - :/ico/16x16/edit-paste.png:/ico/16x16/edit-paste.png - - - C&oller dans la zone - - - - - - :/ico/16x16/text-xml.png:/ico/16x16/text-xml.png - - - Un fichier - - - - - - :/ico/16x16/element.png:/ico/16x16/element.png - - - Un élément - - - - - - :/ico/16x16/edit-select-invert.png:/ico/16x16/edit-select-invert.png - - - Inverser la sélection - - - - - - :/ico/22x22/edit-delete.png:/ico/22x22/edit-delete.png - - - &Supprimer - - - - - - :/ico/22x22/names.png:/ico/22x22/names.png - - - Éditer le nom et les traductions de l'élément - - - - - - :/ico/16x16/preferences-desktop-user.png:/ico/16x16/preferences-desktop-user.png - - - Éditer les informations sur l'auteur - - - - - - :/ico/22x22/element-edit.png:/ico/22x22/element-edit.png - - - Éditer les propriétés de l'élément - - - - - - :/ico/22x22/zoom-in.png:/ico/22x22/zoom-in.png - - - Zoom avant - - - - - - :/ico/22x22/zoom-out.png:/ico/22x22/zoom-out.png - - - Zoom arrière - - - - - - :/ico/22x22/zoom-fit-best.png:/ico/22x22/zoom-fit-best.png - - - Zoom adapté - - - - - - :/ico/22x22/zoom-original.png:/ico/22x22/zoom-original.png - - - Pas de zoom - - - - - - :/ico/16x16/qet.png:/ico/16x16/qet.png - - - À &propos de QElectroTech - - - Affiche des informations sur QElectroTech - - - - - - :/ico/16x16/help-contents.png:/ico/16x16/help-contents.png - - - Manuel en ligne - - - Lance le navigateur par défaut vers le manuel en ligne de QElectroTech - - - - - - :/ico/16x16/kdenlive-show-video.png:/ico/16x16/kdenlive-show-video.png - - - Chaine Youtube - - - Lance le navigateur par défaut vers la chaine Youtube de QElectroTech - - - - - - :/ico/16x16/help-donate.png:/ico/16x16/help-donate.png - - - Soutenir le projet par un don - - - Soutenir le projet QElectroTech par un don - - - - - - :/ico/16x16/qt.png:/ico/16x16/qt.png - - - À propos de &Qt - - - Affiche des informations sur la bibliothèque Qt - - - - - - - - diff --git a/sources/elementspanelwidget.cpp b/sources/elementspanelwidget.cpp index 02317a813..d5e373742 100644 --- a/sources/elementspanelwidget.cpp +++ b/sources/elementspanelwidget.cpp @@ -18,7 +18,7 @@ #include "elementspanelwidget.h" #include "diagram.h" -#include "editor/ui/qetelementeditor.h" +#include "editor/qetelementeditor.h" #include "elementscategoryeditor.h" #include "qetapp.h" #include "qeticons.h" diff --git a/sources/newelementwizard.cpp b/sources/newelementwizard.cpp index bca6c38d5..440f860ae 100644 --- a/sources/newelementwizard.cpp +++ b/sources/newelementwizard.cpp @@ -20,14 +20,10 @@ #include "ElementsCollection/elementcollectionitem.h" #include "ElementsCollection/elementscollectionmodel.h" #include "NameList/ui/namelistwidget.h" -#include "editor/ui/qetelementeditor.h" +#include "editor/qetelementeditor.h" #include "qetmessagebox.h" #include "qfilenameedit.h" -#include -#include -#include - /** Constructeur @param parent QWidget parent de ce dialogue diff --git a/sources/projectview.cpp b/sources/projectview.cpp index a6ce79efc..58259fdd6 100644 --- a/sources/projectview.cpp +++ b/sources/projectview.cpp @@ -21,7 +21,7 @@ #include "autoNum/assignvariables.h" #include "diagram.h" #include "diagramview.h" -#include "editor/ui/qetelementeditor.h" +#include "editor/qetelementeditor.h" #include "exportdialog.h" #include "qetapp.h" #include "qeticons.h" diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index a8e07663f..ec2f5c4db 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -19,7 +19,7 @@ #include "configdialog.h" #include "configpages.h" -#include "editor/ui/qetelementeditor.h" +#include "editor/qetelementeditor.h" #include "elementscollectioncache.h" #include "factory/elementfactory.h" #include "factory/elementpicturefactory.h"