forked from qt-creator/qt-creator
QmlDesigner: Allow inserting SVG snippets
Allows to paste SVG clipboard content into the Form Editor. It will create a Group item which acts as the SVGs view box and groups multiple items together. All SVG items will be transformed into SvgPathItem. * Supports all basic SVG shapes path, rect, polygon, circle, ellipse * Supports the following SVG presentation attributes as CSS-inline definition, XML-attribute, style element: fill, stroke, stroke-width, opacity, fill-opacity, stroke-opacity * Supports all transform operations Task-number: QDS-5259 Change-Id: I9b7027992de60e5c87f2031251348dbb31fe03fe Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Thomas Hartmann
parent
dbd5a4fe1b
commit
14c4f257fe
@@ -7,7 +7,7 @@ add_qtc_plugin(QmlDesigner
|
|||||||
CONDITION TARGET Qt5::QuickWidgets
|
CONDITION TARGET Qt5::QuickWidgets
|
||||||
DEPENDS
|
DEPENDS
|
||||||
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
|
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
|
||||||
Qt5::QuickWidgets Qt5::CorePrivate Sqlite
|
Qt5::QuickWidgets Qt5::CorePrivate Sqlite Qt5::Xml Qt5::Svg
|
||||||
DEFINES
|
DEFINES
|
||||||
DESIGNER_CORE_LIBRARY
|
DESIGNER_CORE_LIBRARY
|
||||||
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
||||||
@@ -139,6 +139,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
theme.cpp theme.h
|
theme.cpp theme.h
|
||||||
zoomaction.cpp zoomaction.h
|
zoomaction.cpp zoomaction.h
|
||||||
hdrimage.cpp hdrimage.h
|
hdrimage.cpp hdrimage.h
|
||||||
|
svgpasteaction.cpp svgpasteaction.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
|
@@ -20,6 +20,7 @@ SOURCES += crumblebar.cpp
|
|||||||
SOURCES += qmldesignericonprovider.cpp
|
SOURCES += qmldesignericonprovider.cpp
|
||||||
SOURCES += zoomaction.cpp
|
SOURCES += zoomaction.cpp
|
||||||
SOURCES += hdrimage.cpp
|
SOURCES += hdrimage.cpp
|
||||||
|
SOURCES += svgpasteaction.cpp
|
||||||
|
|
||||||
HEADERS += modelnodecontextmenu.h
|
HEADERS += modelnodecontextmenu.h
|
||||||
HEADERS += addimagesdialog.h
|
HEADERS += addimagesdialog.h
|
||||||
@@ -43,6 +44,7 @@ HEADERS += crumblebar.h
|
|||||||
HEADERS += qmldesignericonprovider.h
|
HEADERS += qmldesignericonprovider.h
|
||||||
HEADERS += zoomaction.h
|
HEADERS += zoomaction.h
|
||||||
HEADERS += hdrimage.h
|
HEADERS += hdrimage.h
|
||||||
|
HEADERS += svgpasteaction.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
$$PWD/addsignalhandlerdialog.ui
|
$$PWD/addsignalhandlerdialog.ui
|
||||||
|
1232
src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
Normal file
1232
src/plugins/qmldesigner/components/componentcore/svgpasteaction.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qmlitemnode.h>
|
||||||
|
|
||||||
|
#include <QDomDocument>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
struct CSSProperty
|
||||||
|
{
|
||||||
|
QString directive;
|
||||||
|
QString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CSSRule = std::vector<CSSProperty>;
|
||||||
|
using CSSRules = QHash<QString, CSSRule>;
|
||||||
|
using PropertyMap = QHash<QByteArray, QVariant>;
|
||||||
|
|
||||||
|
class SVGPasteAction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SVGPasteAction();
|
||||||
|
|
||||||
|
bool containsSVG(const QString &str);
|
||||||
|
|
||||||
|
QmlObjectNode createQmlObjectNode(QmlDesigner::ModelNode &targetNode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDomDocument m_domDocument;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -51,9 +51,12 @@
|
|||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <timelineactions.h>
|
#include <timelineactions.h>
|
||||||
|
#include <svgpasteaction.h>
|
||||||
|
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -62,6 +65,7 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
|
#include <QClipboard>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
@@ -171,6 +175,41 @@ Model* DesignDocument::createInFileComponentModel()
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DesignDocument::pasteSVG()
|
||||||
|
{
|
||||||
|
SVGPasteAction svgPasteAction;
|
||||||
|
|
||||||
|
if (!svgPasteAction.containsSVG(QApplication::clipboard()->text()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rewriterView()->executeInTransaction("DesignDocument::paste1", [&]() {
|
||||||
|
ModelNode targetNode;
|
||||||
|
|
||||||
|
// If nodes are currently selected make the first node in selection the target
|
||||||
|
if (!view()->selectedModelNodes().isEmpty())
|
||||||
|
targetNode = view()->firstSelectedModelNode();
|
||||||
|
|
||||||
|
// If target is still invalid make the root node the target
|
||||||
|
if (!targetNode.isValid())
|
||||||
|
targetNode = view()->rootModelNode();
|
||||||
|
|
||||||
|
// Check if document has studio components import, if not create it
|
||||||
|
QmlDesigner::Import import = QmlDesigner::Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
|
||||||
|
if (!currentModel()->hasImport(import, true, true)) {
|
||||||
|
QmlDesigner::Import studioComponentsImport = QmlDesigner::Import::createLibraryImport("QtQuick.Studio.Components", "1.0");
|
||||||
|
try {
|
||||||
|
currentModel()->changeImports({studioComponentsImport}, {});
|
||||||
|
} catch (const QmlDesigner::Exception &) {
|
||||||
|
QTC_ASSERT(false, return);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svgPasteAction.createQmlObjectNode(targetNode);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
QList<DocumentMessage> DesignDocument::qmlParseWarnings() const
|
QList<DocumentMessage> DesignDocument::qmlParseWarnings() const
|
||||||
{
|
{
|
||||||
return m_rewriterView->warnings();
|
return m_rewriterView->warnings();
|
||||||
@@ -495,6 +534,9 @@ static void scatterItem(const ModelNode &pastedNode, const ModelNode &targetNode
|
|||||||
|
|
||||||
void DesignDocument::paste()
|
void DesignDocument::paste()
|
||||||
{
|
{
|
||||||
|
if (pasteSVG())
|
||||||
|
return;
|
||||||
|
|
||||||
if (TimelineActions::clipboardContainsKeyframes()) // pasting keyframes is handled in TimelineView
|
if (TimelineActions::clipboardContainsKeyframes()) // pasting keyframes is handled in TimelineView
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -518,7 +560,7 @@ void DesignDocument::paste()
|
|||||||
ModelNode targetNode;
|
ModelNode targetNode;
|
||||||
|
|
||||||
if (!view.selectedModelNodes().isEmpty())
|
if (!view.selectedModelNodes().isEmpty())
|
||||||
targetNode = view.selectedModelNodes().constFirst();
|
targetNode = view.firstSelectedModelNode();
|
||||||
|
|
||||||
// in case we copy and paste a selection we paste in the parent item
|
// in case we copy and paste a selection we paste in the parent item
|
||||||
if ((view.selectedModelNodes().count() == selectedNodes.count()) && targetNode.isValid() && targetNode.hasParentProperty()) {
|
if ((view.selectedModelNodes().count() == selectedNodes.count()) && targetNode.isValid() && targetNode.hasParentProperty()) {
|
||||||
@@ -572,7 +614,7 @@ void DesignDocument::paste()
|
|||||||
ModelNode targetNode;
|
ModelNode targetNode;
|
||||||
|
|
||||||
if (!view.selectedModelNodes().isEmpty()) {
|
if (!view.selectedModelNodes().isEmpty()) {
|
||||||
targetNode = view.selectedModelNodes().constFirst();
|
targetNode = view.firstSelectedModelNode();
|
||||||
} else {
|
} else {
|
||||||
// if selection is empty and this is a 3D Node, paste it under the active scene
|
// if selection is empty and this is a 3D Node, paste it under the active scene
|
||||||
if (pastedNode.isSubclassOf("QtQuick3D.Node")) {
|
if (pastedNode.isSubclassOf("QtQuick3D.Node")) {
|
||||||
|
@@ -145,6 +145,8 @@ private: // functions
|
|||||||
|
|
||||||
Model *createInFileComponentModel();
|
Model *createInFileComponentModel();
|
||||||
|
|
||||||
|
bool pasteSVG();
|
||||||
|
|
||||||
private: // variables
|
private: // variables
|
||||||
QScopedPointer<Model> m_documentModel;
|
QScopedPointer<Model> m_documentModel;
|
||||||
QScopedPointer<Model> m_inFileComponentModel;
|
QScopedPointer<Model> m_inFileComponentModel;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
QT += quickwidgets core-private
|
QT += quickwidgets core-private xml svg
|
||||||
CONFIG += exceptions
|
CONFIG += exceptions
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD
|
INCLUDEPATH += $$PWD
|
||||||
|
@@ -10,7 +10,7 @@ Project {
|
|||||||
Depends {
|
Depends {
|
||||||
name: "Qt";
|
name: "Qt";
|
||||||
submodules: [
|
submodules: [
|
||||||
"core-private", "quickwidgets"
|
"core-private", "quickwidgets", "xml", "svg"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Depends { name: "AdvancedDockingSystem" }
|
Depends { name: "AdvancedDockingSystem" }
|
||||||
@@ -482,6 +482,8 @@ Project {
|
|||||||
"componentcore/zoomaction.h",
|
"componentcore/zoomaction.h",
|
||||||
"componentcore/hdrimage.cpp",
|
"componentcore/hdrimage.cpp",
|
||||||
"componentcore/hdrimage.h",
|
"componentcore/hdrimage.h",
|
||||||
|
"componentcore/svgpasteaction.cpp",
|
||||||
|
"componentcore/svgpasteaction.h",
|
||||||
"texteditor/texteditorstatusbar.cpp",
|
"texteditor/texteditorstatusbar.cpp",
|
||||||
"texteditor/texteditorstatusbar.h",
|
"texteditor/texteditorstatusbar.h",
|
||||||
"componentcore/changestyleaction.cpp",
|
"componentcore/changestyleaction.cpp",
|
||||||
|
Reference in New Issue
Block a user