| 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 | |