mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-08-06 05:14:13 +02:00
Merge pull request #637 from ispyisail/feature-elmt-export-svg
Add "Export to SVG" to the element editor (discussion #605)
This commit is contained in:
@@ -317,6 +317,10 @@ void ElementScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
|||||||
*/
|
*/
|
||||||
void ElementScene::drawForeground(QPainter *p, const QRectF &)
|
void ElementScene::drawForeground(QPainter *p, const QRectF &)
|
||||||
{
|
{
|
||||||
|
if (!m_hotspot_visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
p -> save();
|
p -> save();
|
||||||
|
|
||||||
// desactive tout antialiasing, sauf pour le texte
|
// desactive tout antialiasing, sauf pour le texte
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ class ElementScene : public QGraphicsScene
|
|||||||
|
|
||||||
QPointer<CustomElementGraphicPart> m_single_selected_item;
|
QPointer<CustomElementGraphicPart> m_single_selected_item;
|
||||||
|
|
||||||
|
bool m_hotspot_visible = true;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
public:
|
public:
|
||||||
ElementData elementData();
|
ElementData elementData();
|
||||||
@@ -133,6 +135,14 @@ class ElementScene : public QGraphicsScene
|
|||||||
void addItems(QVector<QGraphicsItem *> items);
|
void addItems(QVector<QGraphicsItem *> items);
|
||||||
void removeItems(QVector<QGraphicsItem *> items);
|
void removeItems(QVector<QGraphicsItem *> items);
|
||||||
|
|
||||||
|
/// Whether drawForeground() draws the red hotspot cross. On by
|
||||||
|
/// default (the normal editing view); turned off around a
|
||||||
|
/// render() call meant to capture the element's actual content
|
||||||
|
/// only, e.g. exporting to SVG -- the cross is an editing aid,
|
||||||
|
/// not part of the drawn symbol.
|
||||||
|
void setHotspotVisible(bool visible) {m_hotspot_visible = visible;}
|
||||||
|
bool hotspotVisible() const {return m_hotspot_visible;}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent (QGraphicsSceneMouseEvent *) override;
|
void mouseMoveEvent (QGraphicsSceneMouseEvent *) override;
|
||||||
void mousePressEvent (QGraphicsSceneMouseEvent *) override;
|
void mousePressEvent (QGraphicsSceneMouseEvent *) override;
|
||||||
|
|||||||
@@ -53,6 +53,8 @@
|
|||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QSvgGenerator>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief QETElementEditor::QETElementEditor
|
* @brief QETElementEditor::QETElementEditor
|
||||||
@@ -1377,6 +1379,94 @@ bool QETElementEditor::on_m_save_as_file_action_triggered()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief QETElementEditor::on_m_export_svg_action_triggered
|
||||||
|
Export the element currently open in this editor to a standalone SVG
|
||||||
|
file.
|
||||||
|
|
||||||
|
Renders the live ElementScene directly, the same way
|
||||||
|
ExportDialog::generateSvg() renders the live Diagram for the diagram
|
||||||
|
editor's own SVG export -- not ElementPictureFactory's cached picture.
|
||||||
|
That cache is keyed by the element's saved-to-disk uuid and is never
|
||||||
|
invalidated on edit (nothing in this editor ever tells it to), so it
|
||||||
|
would silently export stale content for any element already previewed
|
||||||
|
once in the elements panel, and nothing at all for one that has never
|
||||||
|
been saved. Rendering the scene directly has neither problem and
|
||||||
|
always reflects exactly what is currently on screen, saved or not.
|
||||||
|
@return true if the file was written
|
||||||
|
*/
|
||||||
|
bool QETElementEditor::on_m_export_svg_action_triggered()
|
||||||
|
{
|
||||||
|
//Suggest the element's own filename (without its .elmt extension) as
|
||||||
|
//the default export name, per plc-user's review on #637 -- the
|
||||||
|
//directory-only default below is unchanged for an element that has
|
||||||
|
//never been saved, since there is no filename to derive one from.
|
||||||
|
QString suggested_path = QETApp::customElementsDir();
|
||||||
|
if (!m_file_name.isEmpty()) {
|
||||||
|
QFileInfo file_info(m_file_name);
|
||||||
|
suggested_path = QDir(file_info.absolutePath()).filePath(file_info.completeBaseName());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fn = QFileDialog::getSaveFileName(
|
||||||
|
this,
|
||||||
|
tr("Exporter en SVG", "dialog title"),
|
||||||
|
suggested_path,
|
||||||
|
tr("Image SVG (*.svg)", "filetypes allowed when exporting an element to SVG"));
|
||||||
|
|
||||||
|
if (fn.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!fn.endsWith(".svg", Qt::CaseInsensitive)) {
|
||||||
|
fn += ".svg";
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(fn);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
QMessageBox::critical(this, tr("Échec de l'export"),
|
||||||
|
tr("Impossible d'écrire dans le fichier « %1 ».").arg(fn));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Margin-less bounding rect of the element's own drawn content
|
||||||
|
//(lines, rects, terminals, text...), excluding the origin cross
|
||||||
|
//and other editor-only decoration -- see
|
||||||
|
//ElementScene::elementSceneGeometricRect()'s own doc comment.
|
||||||
|
//Falls back to itemsBoundingRect() for the rare element made up
|
||||||
|
//only of item types that helper deliberately excludes.
|
||||||
|
QRectF source_rect = m_elmt_scene->elementSceneGeometricRect();
|
||||||
|
if (source_rect.isEmpty()) {
|
||||||
|
source_rect = m_elmt_scene->itemsBoundingRect();
|
||||||
|
}
|
||||||
|
constexpr qreal margin = 5.0;
|
||||||
|
source_rect.adjust(-margin, -margin, margin, margin);
|
||||||
|
|
||||||
|
QSize target_size = source_rect.size().toSize();
|
||||||
|
if (target_size.isEmpty()) {
|
||||||
|
target_size = QSize(1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSvgGenerator svg_engine;
|
||||||
|
svg_engine.setSize(target_size);
|
||||||
|
svg_engine.setViewBox(QRect(QPoint(0, 0), target_size));
|
||||||
|
svg_engine.setOutputDevice(&file);
|
||||||
|
|
||||||
|
QPainter svg_painter(&svg_engine);
|
||||||
|
svg_painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
svg_painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
|
||||||
|
//The hotspot cross is ElementScene::drawForeground()'s editing aid,
|
||||||
|
//drawn unconditionally on every render() call including this one
|
||||||
|
//unless told not to -- it is not part of the element being
|
||||||
|
//exported.
|
||||||
|
m_elmt_scene->setHotspotVisible(false);
|
||||||
|
m_elmt_scene->render(&svg_painter, QRectF(QPointF(0, 0), target_size), source_rect);
|
||||||
|
m_elmt_scene->setHotspotVisible(true);
|
||||||
|
|
||||||
|
svg_painter.end();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void QETElementEditor::on_m_reload_action_triggered()
|
void QETElementEditor::on_m_reload_action_triggered()
|
||||||
{
|
{
|
||||||
//If user already edit the element, ask confirmation to reload
|
//If user already edit the element, ask confirmation to reload
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class QETElementEditor : public QMainWindow
|
|||||||
void on_m_open_action_triggered();
|
void on_m_open_action_triggered();
|
||||||
void on_m_open_from_file_action_triggered();
|
void on_m_open_from_file_action_triggered();
|
||||||
bool on_m_save_as_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_reload_action_triggered();
|
||||||
void on_m_quit_action_triggered();
|
void on_m_quit_action_triggered();
|
||||||
void on_m_deselect_all_action_triggered();
|
void on_m_deselect_all_action_triggered();
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
<addaction name="m_save_action"/>
|
<addaction name="m_save_action"/>
|
||||||
<addaction name="m_save_as_action"/>
|
<addaction name="m_save_as_action"/>
|
||||||
<addaction name="m_save_as_file_action"/>
|
<addaction name="m_save_as_file_action"/>
|
||||||
|
<addaction name="m_export_svg_action"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="m_reload_action"/>
|
<addaction name="m_reload_action"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@@ -262,6 +263,15 @@
|
|||||||
<string>Enregistrer dans un fichier</string>
|
<string>Enregistrer dans un fichier</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="m_export_svg_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/document-export.png</normaloff>:/ico/22x22/document-export.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Exporter en SVG</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="m_reload_action">
|
<action name="m_reload_action">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../../qelectrotech.qrc">
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
|||||||
Reference in New Issue
Block a user