mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-06 21:34:13 +02:00
8a72230916
Implements discussion #605. The diagram editor can already export a folio to SVG; the element editor, where a single .elmt symbol is drawn, had no export capability at all -- confirmed by grepping its header for "export" before starting: nothing. ## Renders the live scene, not ElementPictureFactory's cache The discussion proposed sourcing this from ElementPictureFactory's cached per-element QPicture (m_pictures_H), the one used for the elements-panel preview icons. Checked that cache's actual invalidation before building on it: nothing in the editor ever tells it to drop an entry on edit, and it is keyed by the element's on-disk uuid. So for any element already previewed once in the panel, exporting from the cache would silently produce stale content after any edit; for a brand-new, never-saved element, no entry would exist at all. Neither is acceptable for a File > Export action a user expects to reflect what's on screen right now. Renders ElementScene directly instead, the same way ExportDialog::generateSvg() already renders the live Diagram for the diagram editor's own SVG export: no new drawing logic, only a new playback target (QSvgGenerator instead of the screen), sized to the element's own content bounds via the existing elementSceneGeometricRect() helper. ## Hotspot cross excluded from the export ElementScene::drawForeground() draws the red origin/hotspot cross on every render() call, unconditionally -- it's an editing aid, not part of the element being drawn, and diagram editor's SVG export has no equivalent problem since Diagram doesn't draw one. Added a settable hotspotVisible flag, defaulting to true (the existing editing view is completely unaffected) and turned off only for the duration of the export render() call. ## Verified end-to-end via a real Xvfb session, not just a build Opened a real shipped element (en_60617_05_06_04.elmt, "Phototransistor"), exported it, and rendered the resulting SVG back to a bitmap with a small QSvgRenderer-based harness -- pixel-identical in shape to the element as shown in the editor. Confirmed the file is valid XML and contains no red/#ff0000 stroke (the hotspot cross did not leak in). Then the case the whole "render live, not cached" decision was about: opened the same element, drew a new line with the line tool, and exported again *without saving*. The new line is present in the exported SVG. git status on the source .elmt file after both exports shows it completely untouched -- the export is read-only and reflects live, unsaved editor state, exactly the property a cache-based implementation would have gotten wrong. Built clean, no new warnings.
170 lines
4.8 KiB
C++
170 lines
4.8 KiB
C++
/*
|
|
Copyright 2006-2026 The QElectroTech Team
|
|
This file is part of QElectroTech.
|
|
|
|
QElectroTech is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
QElectroTech is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#ifndef QETELEMENTEDITOR_H
|
|
#define QETELEMENTEDITOR_H
|
|
|
|
#include "../../ElementsCollection/elementslocation.h"
|
|
|
|
#include <QCloseEvent>
|
|
#include <QMainWindow>
|
|
|
|
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<QAction *> actions = QList<QAction *>());
|
|
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();
|
|
bool on_m_save_as_file_action_triggered();
|
|
bool on_m_export_svg_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();
|
|
void on_m_import_dxf_triggered();
|
|
void on_m_import_scaled_element_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<QAction *> m_context_menu_action_list;
|
|
|
|
QAction
|
|
*m_undo_action = nullptr,
|
|
*m_redo_action = nullptr;
|
|
|
|
|
|
/// Hash associating primitive names with their matching edition widget
|
|
QHash<QString, ElementItemEditor *> 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;
|
|
|
|
QLabel *m_position_label = nullptr;
|
|
|
|
};
|
|
|
|
#endif // QETELEMENTEDITOR_H
|