1 /*
2  * Copyright (c) 2015 Boudewijn Rempt <boud@valdyas.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 #include "KisApplicationArguments.h"
20 
21 #include <QCommandLineParser>
22 #include <QCommandLineOption>
23 #include <QApplication>
24 #include <QDir>
25 #include <QStringList>
26 #include <QString>
27 #include <QDebug>
28 #include <QDataStream>
29 #include <QBuffer>
30 
31 #include <klocalizedstring.h>
32 #include <KisPart.h>
33 #include <KisDocument.h>
34 
35 struct Q_DECL_HIDDEN KisApplicationArguments::Private
36 {
PrivateKisApplicationArguments::Private37     Private()
38     {
39     }
40 
41     QStringList filenames;
42     int dpiX {72};
43     int dpiY {72};
44     bool doTemplate {false};
45     bool exportAs {false};
46     bool exportSequence {false};
47     QString exportFileName;
48     QString workspace;
49     QString windowLayout;
50     QString session;
51     QString fileLayer;
52     bool canvasOnly {false};
53     bool noSplash {false};
54     bool fullScreen {false};
55 
56     bool newImage {false};
57     QString colorModel {"RGBA"};
58     QString colorDepth {"U8"};
59     int width {2000};
60     int height {5000};
61 };
62 
63 
KisApplicationArguments()64 KisApplicationArguments::KisApplicationArguments()
65     : d(new Private)
66 {
67 }
68 
69 
~KisApplicationArguments()70 KisApplicationArguments::~KisApplicationArguments()
71 {
72 }
73 
KisApplicationArguments(const QApplication & app)74 KisApplicationArguments::KisApplicationArguments(const QApplication &app)
75     : d(new Private)
76 {
77     QCommandLineParser parser;
78     parser.addVersionOption();
79     parser.addHelpOption();
80     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("template"), i18n("Open a new document with a template")));
81     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("new-image"), i18n("Create a new image.\n"
82                                                                                           "Possible colorspace values are:\n"
83                                                                                           "    * RGBA\n"
84                                                                                           "    * XYZA\n"
85                                                                                           "    * LABA\n"
86                                                                                           "    * CMYKA\n"
87                                                                                           "    * GRAY\n"
88                                                                                           "    * YCbCrA\n"
89                                                                                           "Possible channel depth arguments are\n"
90                                                                                           "    * U8 (8 bits integer)\n"
91                                                                                           "    * U16 (16 bits integer)\n"
92                                                                                           "    * F16 (16 bits floating point)\n"
93                                                                                           "    * F32 (32 bits floating point)\n"),
94                                         QLatin1String("colorspace,depth,width,height")));
95     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("workspace"), i18n("The name of the workspace to open Krita with"), QLatin1String("workspace")));
96     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("windowlayout"), i18n("The name of the window layout to open Krita with"), QLatin1String("windowlayout")));
97     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
98     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("canvasonly"), i18n("Start Krita in canvas-only mode")));
99     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("nosplash"), i18n("Do not show the splash screen")));
100     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("fullscreen"), i18n("Start Krita in full-screen mode")));
101     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("dpi"), i18n("Override display DPI"), QLatin1String("dpiX,dpiY")));
102     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export"), i18n("Export to the given filename and exit")));
103     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-sequence"), i18n("Export animation to the given filename and exit")));
104     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-filename"), i18n("Filename for export"), QLatin1String("filename")));
105     parser.addOption(QCommandLineOption(QStringList() << QLatin1String("file-layer"), i18n("File layer to be added to existing or new file"), QLatin1String("file-layer")));
106     parser.addPositionalArgument(QLatin1String("[file(s)]"), i18n("File(s) or URL(s) to open"));
107 
108 
109     if (parser.parse(app.arguments())) {
110         parser.process(app);
111     }
112 
113     QString dpiValues = parser.value("dpi");
114     if (!dpiValues.isEmpty()) {
115         int sep = dpiValues.indexOf(QRegExp("[x, ]"));
116         bool ok = true;
117         if (sep != -1) {
118             d->dpiY = dpiValues.mid(sep + 1).toInt(&ok);
119             dpiValues.truncate(sep);
120         }
121         if (ok) {
122             d->dpiX = dpiValues.toInt(&ok);
123             if (ok) {
124                 if (!d->dpiY)
125                     d->dpiY = d->dpiX;
126             }
127         }
128     }
129 
130     QString newImageValues = parser.value("new-image");
131     d->newImage = !newImageValues.isEmpty();
132     if (d->newImage) {
133         QStringList v = newImageValues.split(",");
134         if (v.size() != 4) {
135             d->newImage = false;
136             qWarning() << "Cannot create a new image: please specify colormodel, depth, width and height.";
137         }
138         d->colorModel = v[0].toUpper();
139         d->colorDepth = v[1].toUpper();
140         d->width = v[2].toInt();
141         d->height = v[3].toInt();
142     }
143 
144     d->fileLayer = parser.value("file-layer");
145     d->exportFileName = parser.value("export-filename");
146     d->workspace = parser.value("workspace");
147     d->windowLayout = parser.value("windowlayout");
148     d->session = parser.value("load-session");
149     d->doTemplate = parser.isSet("template");
150     d->exportAs = parser.isSet("export");
151     d->exportSequence = parser.isSet("export-sequence");
152     d->canvasOnly = parser.isSet("canvasonly");
153     d->noSplash = parser.isSet("nosplash");
154     d->fullScreen = parser.isSet("fullscreen");
155 
156     const QDir currentDir = QDir::current();
157     Q_FOREACH (const QString &filename, parser.positionalArguments()) {
158         d->filenames << currentDir.absoluteFilePath(filename);
159     }
160 }
161 
KisApplicationArguments(const KisApplicationArguments & rhs)162 KisApplicationArguments::KisApplicationArguments(const KisApplicationArguments &rhs)
163     : d(new Private)
164 {
165     d->filenames = rhs.filenames();
166     d->dpiX = rhs.dpiX();
167     d->dpiY = rhs.dpiY();
168     d->doTemplate = rhs.doTemplate();
169     d->exportAs = rhs.exportAs();
170     d->exportFileName = rhs.exportFileName();
171     d->canvasOnly = rhs.canvasOnly();
172     d->workspace = rhs.workspace();
173     d->windowLayout = rhs.windowLayout();
174     d->session = rhs.session();
175     d->noSplash = rhs.noSplash();
176     d->fullScreen = rhs.fullScreen();
177 }
178 
operator =(const KisApplicationArguments & rhs)179 void KisApplicationArguments::operator=(const KisApplicationArguments &rhs)
180 {
181     d->filenames = rhs.filenames();
182     d->dpiX = rhs.dpiX();
183     d->dpiY = rhs.dpiY();
184     d->doTemplate = rhs.doTemplate();
185     d->exportAs = rhs.exportAs();
186     d->exportFileName = rhs.exportFileName();
187     d->canvasOnly = rhs.canvasOnly();
188     d->workspace = rhs.workspace();
189     d->windowLayout = rhs.windowLayout();
190     d->session = rhs.session();
191     d->noSplash = rhs.noSplash();
192     d->fullScreen = rhs.fullScreen();
193 }
194 
serialize()195 QByteArray KisApplicationArguments::serialize()
196 {
197     QByteArray ba;
198     QBuffer buf(&ba);
199     buf.open(QIODevice::WriteOnly);
200     QDataStream ds(&buf);
201     ds.setVersion(QDataStream::Qt_5_0);
202     ds << d->filenames.count();
203     Q_FOREACH (const QString &filename, d->filenames) {
204         ds << filename;
205     }
206     ds << d->dpiX;
207     ds << d->dpiY;
208     ds << d->doTemplate;
209     ds << d->exportAs;
210     ds << d->exportFileName;
211     ds << d->workspace;
212     ds << d->windowLayout;
213     ds << d->session;
214     ds << d->canvasOnly;
215     ds << d->noSplash;
216     ds << d->fullScreen;
217     ds << d->newImage;
218     ds << d->height;
219     ds << d->width;
220     ds << d->height;
221     ds << d->colorModel;
222     ds << d->colorDepth;
223     ds << d->fileLayer;
224 
225     buf.close();
226 
227     return ba;
228 }
229 
deserialize(QByteArray & serialized)230 KisApplicationArguments KisApplicationArguments::deserialize(QByteArray &serialized)
231 {
232     KisApplicationArguments args;
233 
234     QBuffer buf(&serialized);
235     buf.open(QIODevice::ReadOnly);
236     QDataStream ds(&buf);
237     ds.setVersion(QDataStream::Qt_5_0);
238     int count;
239     ds >> count;
240     for(int i = 0; i < count; ++i) {
241         QString s;
242         ds >> s;
243         args.d->filenames << s;
244     }
245     ds >> args.d->dpiX;
246     ds >> args.d->dpiY;
247     ds >> args.d->doTemplate;
248     ds >> args.d->exportAs;
249     ds >> args.d->exportFileName;
250     ds >> args.d->workspace;
251     ds >> args.d->windowLayout;
252     ds >> args.d->session;
253     ds >> args.d->canvasOnly;
254     ds >> args.d->noSplash;
255     ds >> args.d->fullScreen;
256     ds >> args.d->newImage;
257     ds >> args.d->height;
258     ds >> args.d->width;
259     ds >> args.d->height;
260     ds >> args.d->colorModel;
261     ds >> args.d->colorDepth;
262     ds >> args.d->fileLayer;
263 
264     buf.close();
265 
266     return args;
267 }
268 
filenames() const269 QStringList KisApplicationArguments::filenames() const
270 {
271     return d->filenames;
272 }
273 
dpiX() const274 int KisApplicationArguments::dpiX() const
275 {
276     return d->dpiX;
277 }
278 
dpiY() const279 int KisApplicationArguments::dpiY() const
280 {
281     return d->dpiY;
282 }
283 
doTemplate() const284 bool KisApplicationArguments::doTemplate() const
285 {
286     return d->doTemplate;
287 }
288 
exportAs() const289 bool KisApplicationArguments::exportAs() const
290 {
291     return d->exportAs;
292 }
293 
exportSequence() const294 bool KisApplicationArguments::exportSequence() const
295 {
296     return d->exportSequence;
297 }
298 
exportFileName() const299 QString KisApplicationArguments::exportFileName() const
300 {
301     return d->exportFileName;
302 }
303 
workspace() const304 QString KisApplicationArguments::workspace() const
305 {
306     return d->workspace;
307 }
308 
windowLayout() const309 QString KisApplicationArguments::windowLayout() const
310 {
311     return d->windowLayout;
312 }
313 
session() const314 QString KisApplicationArguments::session() const
315 {
316     return d->session;
317 }
318 
fileLayer() const319 QString KisApplicationArguments::fileLayer() const
320 {
321     return d->fileLayer;
322 }
323 
canvasOnly() const324 bool KisApplicationArguments::canvasOnly() const
325 {
326     return d->canvasOnly;
327 }
328 
noSplash() const329 bool KisApplicationArguments::noSplash() const
330 {
331     return d->noSplash;
332 }
333 
fullScreen() const334 bool KisApplicationArguments::fullScreen() const
335 {
336     return d->fullScreen;
337 }
338 
doNewImage() const339 bool KisApplicationArguments::doNewImage() const
340 {
341     return d->newImage;
342 }
343 
createDocumentFromArguments() const344 KisDocument *KisApplicationArguments::createDocumentFromArguments() const
345 {
346     KisDocument *doc = KisPart::instance()->createDocument();
347     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(d->colorModel, d->colorDepth, "");
348     if (!cs) {
349         qWarning() << "Could not create the colorspace for the new image. Check the colorspace and depth arguments.";
350         return 0;
351     }
352 
353     doc->newImage(i18n("Unnamed"), d->width, d->height, cs, KoColor(QColor(Qt::white), cs), KisConfig::CANVAS_COLOR, 1, "", 100.0);
354     return doc;
355 }
356