1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #include <QGuiApplication> |
5 | #include <QQmlApplicationEngine> |
6 | #include <QCommandLineParser> |
7 | #include <QFile> |
8 | #include <QQuickWindow> |
9 | #include <QQuickItem> |
10 | #include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h> |
11 | #include <QtQuickVectorImageGenerator/private/qquickqmlgenerator_p.h> |
12 | #include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h> |
13 | |
14 | #define ENABLE_GUI |
15 | |
16 | int main(int argc, char *argv[]) |
17 | { |
18 | #ifdef ENABLE_GUI |
19 | QGuiApplication app(argc, argv); |
20 | #else |
21 | QCoreApplication app(argc, argv); |
22 | #endif |
23 | |
24 | QCommandLineParser parser; |
25 | parser.setApplicationDescription("SVG to QML converter" ); |
26 | parser.addHelpOption(); |
27 | parser.addPositionalArgument(name: "input" , description: QCoreApplication::translate(context: "main" , key: "SVG file to read." )); |
28 | parser.addPositionalArgument(name: "output" , description: QCoreApplication::translate(context: "main" , key: "QML file to write." ), syntax: "[output]" ); |
29 | |
30 | QCommandLineOption curveRendererOption({ "c" , "curve-renderer" }, |
31 | QCoreApplication::translate(context: "main" , key: "Use the curve renderer in generated QML." )); |
32 | parser.addOption(commandLineOption: curveRendererOption); |
33 | |
34 | QCommandLineOption optimizeOption({ "p" , "optimize-paths" }, |
35 | QCoreApplication::translate(context: "main" , key: "Optimize paths for the curve renderer." )); |
36 | parser.addOption(commandLineOption: optimizeOption); |
37 | |
38 | QCommandLineOption typeNameOption({ "t" , "type-name" }, |
39 | QCoreApplication::translate(context: "main" , key: "Use <typename> for Shape." ), |
40 | QCoreApplication::translate(context: "main" , key: "typename" )); |
41 | parser.addOption(commandLineOption: typeNameOption); |
42 | |
43 | QCommandLineOption copyrightOption("copyright-statement" , |
44 | QCoreApplication::translate(context: "main" , key: "Add <string> as a comment at the start of the generated file." ), |
45 | QCoreApplication::translate(context: "main" , key: "string" )); |
46 | parser.addOption(commandLineOption: copyrightOption); |
47 | |
48 | QCommandLineOption outlineModeOption("outline-stroke-mode" , |
49 | QCoreApplication::translate(context: "main" , key: "Stroke the outline (contour) of the filled shape instead of " |
50 | "the original path. Also sets optimize-paths." )); |
51 | parser.addOption(commandLineOption: outlineModeOption); |
52 | |
53 | QCommandLineOption assetOutputDirectoryOption("asset-output-directory" , |
54 | QCoreApplication::translate(context: "main" , key: "If the SVG refers to external or embedded files, such as images, these " |
55 | "will be copied into the same directory as the output QML file by default. " |
56 | "Set the asset output directory to override the location." ), |
57 | QCoreApplication::translate(context: "main" , key: "directory" )); |
58 | parser.addOption(commandLineOption: assetOutputDirectoryOption); |
59 | |
60 | QCommandLineOption assetOutputPrefixOption("asset-output-prefix" , |
61 | QCoreApplication::translate(context: "main" , key: "If the SVG refers to external or embedded files, such as images, these " |
62 | "will be copied to files with unique identifiers. By default, the files will be prefixed " |
63 | "with \"svg_asset_\". Set the asset output prefix to override the prefix." ), |
64 | QCoreApplication::translate(context: "main" , key: "prefix" )); |
65 | parser.addOption(commandLineOption: assetOutputPrefixOption); |
66 | |
67 | QCommandLineOption keepPathsOption("keep-external-paths" , |
68 | QCoreApplication::translate(context: "main" , key: "Any paths to external files will be retained in the QML output. " |
69 | "The paths will be reformatted as relative to the output file. If " |
70 | "this is not enabled, copies of the file will be saved to the asset output " |
71 | "directory. Embedded data will still be saved to files, even if " |
72 | "this option is set." )); |
73 | parser.addOption(commandLineOption: keepPathsOption); |
74 | |
75 | #ifdef ENABLE_GUI |
76 | QCommandLineOption guiOption({ "v" , "view" }, |
77 | QCoreApplication::translate(context: "main" , key: "Display the generated QML in a window. This is the default behavior if no " |
78 | "output file is specified." )); |
79 | parser.addOption(commandLineOption: guiOption); |
80 | #endif |
81 | parser.process(app); |
82 | const QStringList args = parser.positionalArguments(); |
83 | if (args.size() < 1) { |
84 | parser.showHelp(exitCode: 1); |
85 | } |
86 | |
87 | const QString inFileName = args.at(i: 0); |
88 | |
89 | QString = QLatin1String("Generated from SVG file %1" ).arg(args: inFileName); |
90 | |
91 | const auto outFileName = args.size() > 1 ? args.at(i: 1) : QString{}; |
92 | const auto typeName = parser.value(option: typeNameOption); |
93 | const auto assetOutputDirectory = parser.value(option: assetOutputDirectoryOption); |
94 | const auto assetOutputPrefix = parser.value(option: assetOutputPrefixOption); |
95 | const bool keepPaths = parser.isSet(option: keepPathsOption); |
96 | auto copyrightString = parser.value(option: copyrightOption); |
97 | |
98 | if (!copyrightString.isEmpty()) { |
99 | copyrightString = copyrightString.replace(before: "\\n" , after: "\n" ); |
100 | commentString = copyrightString + u"\n" + commentString; |
101 | } |
102 | |
103 | QQuickVectorImageGenerator::GeneratorFlags flags; |
104 | if (parser.isSet(option: curveRendererOption)) |
105 | flags |= QQuickVectorImageGenerator::GeneratorFlag::CurveRenderer; |
106 | if (parser.isSet(option: optimizeOption)) |
107 | flags |= QQuickVectorImageGenerator::GeneratorFlag::OptimizePaths; |
108 | if (parser.isSet(option: outlineModeOption)) |
109 | flags |= (QQuickVectorImageGenerator::GeneratorFlag::OutlineStrokeMode |
110 | | QQuickVectorImageGenerator::GeneratorFlag::OptimizePaths); |
111 | |
112 | QQuickQmlGenerator generator(inFileName, flags, outFileName); |
113 | generator.setShapeTypeName(typeName); |
114 | generator.setCommentString(commentString); |
115 | generator.setAssetFileDirectory(assetOutputDirectory); |
116 | generator.setAssetFilePrefix(assetOutputPrefix); |
117 | generator.setRetainFilePaths(keepPaths); |
118 | bool ok = generator.generate(); |
119 | |
120 | #ifdef ENABLE_GUI |
121 | if (ok && (parser.isSet(option: guiOption) || outFileName.isEmpty())) { |
122 | app.setOrganizationName("QtProject" ); |
123 | const QUrl url(QStringLiteral("qrc:/main.qml" )); |
124 | QQmlApplicationEngine engine; |
125 | QObject::connect(sender: &engine, signal: &QQmlApplicationEngine::objectCreated, |
126 | context: &app, slot: [&](QObject *obj, const QUrl &objUrl){ |
127 | if (!obj && url == objUrl) |
128 | QCoreApplication::exit(retcode: -1); |
129 | if (obj) { |
130 | auto *containerItem = obj->findChild<QQuickItem*>(QStringLiteral("svg_item" )); |
131 | QQuickItemGenerator generator(inFileName, flags, containerItem); |
132 | generator.generate(); |
133 | } |
134 | }); |
135 | engine.load(url); |
136 | return app.exec(); |
137 | } |
138 | #endif |
139 | |
140 | return ok ? 0 : 1; |
141 | } |
142 | |