Krita Source Code Documentation
Loading...
Searching...
No Matches
KisApplicationArguments.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
7
8#include <QCommandLineParser>
9#include <QCommandLineOption>
10#include <QApplication>
11#include <QDir>
12#include <QStringList>
13#include <QString>
14#include <QDebug>
15#include <QDataStream>
16#include <QBuffer>
17
18#include <KoResourcePaths.h>
19#include <klocalizedstring.h>
20#include <KisPart.h>
21#include <KisDocument.h>
22
23struct Q_DECL_HIDDEN KisApplicationArguments::Private
24{
26 {
27 }
28
30 int dpiX {72};
31 int dpiY {72};
32 bool doTemplate {false};
33 bool exportAs {false};
34 bool exportSequence {false};
36 QString workspace;
37 QString windowLayout;
38 QString session;
39 QString fileLayer;
40 bool canvasOnly {false};
41 bool noSplash {false};
42 bool fullScreen {false};
43
44 bool newImage {false};
45 QString colorModel {"RGBA"};
46 QString colorDepth {"U8"};
47 int width {2000};
48 int height {5000};
49
50};
51
52
57
58
62
64 : d(new Private)
65{
66 QCommandLineParser parser;
67 parser.addVersionOption();
68 parser.addHelpOption();
69 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("template"), i18n("Open a new document with a template")));
70 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("new-image"), i18n("Create a new image.\n"
71 "Possible colorspace values are:\n"
72 " * RGBA\n"
73 " * XYZA\n"
74 " * LABA\n"
75 " * CMYKA\n"
76 " * GRAY\n"
77 " * YCbCrA\n"
78 "Possible channel depth arguments are\n"
79 " * U8 (8 bits integer)\n"
80 " * U16 (16 bits integer)\n"
81 " * F16 (16 bits floating point)\n"
82 " * F32 (32 bits floating point)\n"),
83 QLatin1String("colorspace,depth,width,height")));
84 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("workspace"), i18n("The name of the workspace to open Krita with"), QLatin1String("workspace")));
85 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("windowlayout"), i18n("The name of the window layout to open Krita with"), QLatin1String("windowlayout")));
86 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("load-session"), i18n("The name of the session to open Krita with"), QLatin1String("load-session"))); // NB: the argument "session" is already used by QGuiApplication
87 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("canvasonly"), i18n("Start Krita in canvas-only mode")));
88 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("nosplash"), i18n("Do not show the splash screen")));
89 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("fullscreen"), i18n("Start Krita in full-screen mode")));
90 {
91 QCommandLineOption opt(QStringList() << QLatin1String("dpi"), i18n("Override display DPI"), QLatin1String("dpiX,dpiY"));
92 opt.setFlags(QCommandLineOption::HiddenFromHelp);
93 parser.addOption(opt);
94 }
95 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export"), i18n("Export to the given filename and exit")));
96 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-sequence"), i18n("Export animation to the given filename and exit")));
97 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-filename"), i18n("Filename for export"), QLatin1String("filename")));
98 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("file-layer"), i18n("File layer to be added to existing or new file"), QLatin1String("file-layer")));
99 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("resource-location"), i18n("A location that overrides the configured location for Krita's resources"), QLatin1String("file-layer")));
100 parser.addPositionalArgument(QLatin1String("[file(s)]"), i18n("File(s) or URL(s) to open"));
101
102 QStringList filteredArgs;
103 {
104 auto checkIsIgnoreEpic = [](const QString &arg) {
105 // List according to https://dev.epicgames.com/docs/services/en-US/Interfaces/Auth/index.html#epicgameslauncher
106 static const QStringList epicIgnoreArgsStart = {
107 QStringLiteral("AUTH_PASSWORD="),
108 QStringLiteral("AUTH_LOGIN="),
109 QStringLiteral("AUTH_TYPE="),
110 QStringLiteral("epicapp="),
111 QStringLiteral("epicenv="),
112 QStringLiteral("epicusername="),
113 QStringLiteral("epicuserid="),
114 QStringLiteral("epiclocale="),
115 QStringLiteral("epicsandboxid="),
116 };
117 static const QStringList epicIgnoreArgsExact = {
118 QStringLiteral("EpicPortal"),
119 };
120#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
121 QStringRef argDashless(&arg);
122#else
123 QStringView argDashless(arg);
124#endif
125 // Strip leading dashes.
126 while (argDashless.startsWith('-')) {
127 argDashless = argDashless.mid(1);
128 }
129 Q_FOREACH(const auto &argToIgnore, epicIgnoreArgsStart) {
130 if (argDashless.startsWith(argToIgnore, Qt::CaseInsensitive)) {
131 return true;
132 }
133 }
134 Q_FOREACH(const auto &argToIgnore, epicIgnoreArgsExact) {
135 if (argDashless.compare(argToIgnore, Qt::CaseInsensitive) == 0) {
136 return true;
137 }
138 }
139 return false;
140 };
141
142 QStringListIterator iter(app.arguments());
143 if (iter.hasNext()) {
144 // First argument is application name.
145 filteredArgs.append(iter.next());
146
147 bool isAfterDoubleDash = false;
148 while (iter.hasNext()) {
149 QString arg = iter.next();
150 if (arg == QLatin1String("--")) {
151 isAfterDoubleDash = true;
152 }
153 if (isAfterDoubleDash || !checkIsIgnoreEpic(arg)) {
154 filteredArgs.append(arg);
155 }
156 }
157 }
158 }
159
160 parser.process(filteredArgs);
161
162 QString dpiValues = parser.value("dpi");
163 if (!dpiValues.isEmpty()) {
164 qWarning() << "The `dpi` argument does nothing!";
165 }
166
167 QString newImageValues = parser.value("new-image");
168 d->newImage = !newImageValues.isEmpty();
169 if (d->newImage) {
170 QStringList v = newImageValues.split(",");
171 if (v.size() != 4) {
172 d->newImage = false;
173 qWarning() << "Cannot create a new image: please specify colormodel, depth, width and height.";
174 }
175 d->colorModel = v[0].toUpper();
176 d->colorDepth = v[1].toUpper();
177 d->width = v[2].toInt();
178 d->height = v[3].toInt();
179 }
180
181 d->fileLayer = parser.value("file-layer");
182 d->exportFileName = parser.value("export-filename");
183 d->workspace = parser.value("workspace");
184 d->windowLayout = parser.value("windowlayout");
185 d->session = parser.value("load-session");
186 d->doTemplate = parser.isSet("template");
187 d->exportAs = parser.isSet("export");
188 d->exportSequence = parser.isSet("export-sequence");
189 d->canvasOnly = parser.isSet("canvasonly");
190 d->noSplash = parser.isSet("nosplash");
191 d->fullScreen = parser.isSet("fullscreen");
192
193 KoResourcePaths::s_overrideAppDataLocation = parser.value("resource-location");
194
195 const QDir currentDir = QDir::current();
196 Q_FOREACH (const QString &filename, parser.positionalArguments()) {
197 d->filenames << currentDir.absoluteFilePath(filename);
198 }
199}
200
202 : d(new Private)
203{
204 d->filenames = rhs.filenames();
205 d->dpiX = rhs.d->dpiX;
206 d->dpiY = rhs.d->dpiY;
207 d->doTemplate = rhs.doTemplate();
208 d->exportAs = rhs.exportAs();
209 d->exportFileName = rhs.exportFileName();
210 d->canvasOnly = rhs.canvasOnly();
211 d->workspace = rhs.workspace();
212 d->windowLayout = rhs.windowLayout();
213 d->session = rhs.session();
214 d->noSplash = rhs.noSplash();
215 d->fullScreen = rhs.fullScreen();
216
217}
218
220{
221 d->filenames = rhs.filenames();
222 d->dpiX = rhs.d->dpiX;
223 d->dpiY = rhs.d->dpiY;
224 d->doTemplate = rhs.doTemplate();
225 d->exportAs = rhs.exportAs();
226 d->exportFileName = rhs.exportFileName();
227 d->canvasOnly = rhs.canvasOnly();
228 d->workspace = rhs.workspace();
229 d->windowLayout = rhs.windowLayout();
230 d->session = rhs.session();
231 d->noSplash = rhs.noSplash();
232 d->fullScreen = rhs.fullScreen();
233}
234
236{
237 QBuffer buf;
238 buf.open(QIODevice::WriteOnly);
239 QDataStream ds(&buf);
240 ds.setVersion(QDataStream::Qt_5_0);
241 // explicitly declare the type of the size variable
242 const qsizetype fileNamesCount = d->filenames.count();
243 ds << fileNamesCount;
244 Q_FOREACH (const QString &filename, d->filenames) {
245 ds << filename;
246 }
247 ds << d->dpiX;
248 ds << d->dpiY;
249 ds << d->doTemplate;
250 ds << d->exportAs;
251 ds << d->exportFileName;
252 ds << d->workspace;
253 ds << d->windowLayout;
254 ds << d->session;
255 ds << d->canvasOnly;
256 ds << d->noSplash;
257 ds << d->fullScreen;
258 ds << d->newImage;
259 ds << d->height;
260 ds << d->width;
261 ds << d->height;
262 ds << d->colorModel;
263 ds << d->colorDepth;
264 ds << d->fileLayer;
265
266 buf.close();
267
268 return buf.data();
269}
270
272{
274
275 QBuffer buf(&serialized);
276 buf.open(QIODevice::ReadOnly);
277 QDataStream ds(&buf);
278 ds.setVersion(QDataStream::Qt_5_0);
279 qsizetype fileNamesCount;
280 ds >> fileNamesCount;
281 for(int i = 0; i < fileNamesCount; ++i) {
282 QString s;
283 ds >> s;
284 args.d->filenames << s;
285 }
286 ds >> args.d->dpiX;
287 ds >> args.d->dpiY;
288 ds >> args.d->doTemplate;
289 ds >> args.d->exportAs;
290 ds >> args.d->exportFileName;
291 ds >> args.d->workspace;
292 ds >> args.d->windowLayout;
293 ds >> args.d->session;
294 ds >> args.d->canvasOnly;
295 ds >> args.d->noSplash;
296 ds >> args.d->fullScreen;
297 ds >> args.d->newImage;
298 ds >> args.d->height;
299 ds >> args.d->width;
300 ds >> args.d->height;
301 ds >> args.d->colorModel;
302 ds >> args.d->colorDepth;
303 ds >> args.d->fileLayer;
304
305 buf.close();
306
307 return args;
308}
309
311{
312 return d->filenames;
313}
314
316{
317 return d->doTemplate;
318}
319
321{
322 return d->exportAs;
323}
324
326{
327 return d->exportSequence;
328}
329
331{
332 return d->exportFileName;
333}
334
336{
337 return d->workspace;
338}
339
341{
342 return d->windowLayout;
343}
344
346{
347 return d->session;
348}
349
351{
352 return d->fileLayer;
353}
354
356{
357 return d->canvasOnly;
358}
359
361{
362 return d->noSplash;
363}
364
366{
367 return d->fullScreen;
368}
369
371{
372 return d->newImage;
373}
374
376{
378 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(d->colorModel, d->colorDepth, "");
379 if (!cs) {
380 qWarning() << "Could not create the colorspace for the new image. Check the colorspace and depth arguments.";
381 return 0;
382 }
383
384 doc->newImage(i18n("Unnamed"), d->width, d->height, cs, KoColor(QColor(Qt::white), cs), KisConfig::CANVAS_COLOR, 1, "", 100.0);
385 return doc;
386}
qreal v
QList< QString > QStringList
bool newImage(const QString &name, qint32 width, qint32 height, const KoColorSpace *cs, const KoColor &bgColor, KisConfig::BackgroundStyle bgStyle, int numberOfLayers, const QString &imageDescription, const double imageResolution)
static KisPart * instance()
Definition KisPart.cpp:131
KisDocument * createDocument() const
Definition KisPart.cpp:230
static QString s_overrideAppDataLocation
getAppDataLocation Use this instead of QStandardPaths::AppDataLocation! The user can configure the lo...
void operator=(const KisApplicationArguments &rhs)
static KisApplicationArguments deserialize(QByteArray &serialized)
KisDocument * createDocumentFromArguments() const
const QScopedPointer< Private > d
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()