File indexing completed on 2024-05-12 16:01:44
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 #include "KisApplicationArguments.h" 0007 0008 #include <QCommandLineParser> 0009 #include <QCommandLineOption> 0010 #include <QApplication> 0011 #include <QDir> 0012 #include <QStringList> 0013 #include <QString> 0014 #include <QDebug> 0015 #include <QDataStream> 0016 #include <QBuffer> 0017 0018 #include <KoResourcePaths.h> 0019 #include <klocalizedstring.h> 0020 #include <KisPart.h> 0021 #include <KisDocument.h> 0022 0023 struct Q_DECL_HIDDEN KisApplicationArguments::Private 0024 { 0025 Private() 0026 { 0027 } 0028 0029 QStringList filenames; 0030 int dpiX {72}; 0031 int dpiY {72}; 0032 bool doTemplate {false}; 0033 bool exportAs {false}; 0034 bool exportSequence {false}; 0035 QString exportFileName; 0036 QString workspace; 0037 QString windowLayout; 0038 QString session; 0039 QString fileLayer; 0040 bool canvasOnly {false}; 0041 bool noSplash {false}; 0042 bool fullScreen {false}; 0043 0044 bool newImage {false}; 0045 QString colorModel {"RGBA"}; 0046 QString colorDepth {"U8"}; 0047 int width {2000}; 0048 int height {5000}; 0049 0050 }; 0051 0052 0053 KisApplicationArguments::KisApplicationArguments() 0054 : d(new Private) 0055 { 0056 } 0057 0058 0059 KisApplicationArguments::~KisApplicationArguments() 0060 { 0061 } 0062 0063 KisApplicationArguments::KisApplicationArguments(const QApplication &app) 0064 : d(new Private) 0065 { 0066 QCommandLineParser parser; 0067 parser.addVersionOption(); 0068 parser.addHelpOption(); 0069 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("template"), i18n("Open a new document with a template"))); 0070 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("new-image"), i18n("Create a new image.\n" 0071 "Possible colorspace values are:\n" 0072 " * RGBA\n" 0073 " * XYZA\n" 0074 " * LABA\n" 0075 " * CMYKA\n" 0076 " * GRAY\n" 0077 " * YCbCrA\n" 0078 "Possible channel depth arguments are\n" 0079 " * U8 (8 bits integer)\n" 0080 " * U16 (16 bits integer)\n" 0081 " * F16 (16 bits floating point)\n" 0082 " * F32 (32 bits floating point)\n"), 0083 QLatin1String("colorspace,depth,width,height"))); 0084 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("workspace"), i18n("The name of the workspace to open Krita with"), QLatin1String("workspace"))); 0085 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("windowlayout"), i18n("The name of the window layout to open Krita with"), QLatin1String("windowlayout"))); 0086 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 0087 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("canvasonly"), i18n("Start Krita in canvas-only mode"))); 0088 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("nosplash"), i18n("Do not show the splash screen"))); 0089 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("fullscreen"), i18n("Start Krita in full-screen mode"))); 0090 { 0091 QCommandLineOption opt(QStringList() << QLatin1String("dpi"), i18n("Override display DPI"), QLatin1String("dpiX,dpiY")); 0092 opt.setFlags(QCommandLineOption::HiddenFromHelp); 0093 parser.addOption(opt); 0094 } 0095 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export"), i18n("Export to the given filename and exit"))); 0096 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-sequence"), i18n("Export animation to the given filename and exit"))); 0097 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("export-filename"), i18n("Filename for export"), QLatin1String("filename"))); 0098 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("file-layer"), i18n("File layer to be added to existing or new file"), QLatin1String("file-layer"))); 0099 parser.addOption(QCommandLineOption(QStringList() << QLatin1String("resource-location"), i18n("A location that overrides the configured location for Krita's resources"), QLatin1String("file-layer"))); 0100 parser.addPositionalArgument(QLatin1String("[file(s)]"), i18n("File(s) or URL(s) to open")); 0101 0102 QStringList filteredArgs; 0103 { 0104 auto checkIsIgnoreEpic = [](const QString &arg) { 0105 // List according to https://dev.epicgames.com/docs/services/en-US/Interfaces/Auth/index.html#epicgameslauncher 0106 static const QStringList epicIgnoreArgsStart = { 0107 QStringLiteral("AUTH_PASSWORD="), 0108 QStringLiteral("AUTH_LOGIN="), 0109 QStringLiteral("AUTH_TYPE="), 0110 QStringLiteral("epicapp="), 0111 QStringLiteral("epicenv="), 0112 QStringLiteral("epicusername="), 0113 QStringLiteral("epicuserid="), 0114 QStringLiteral("epiclocale="), 0115 QStringLiteral("epicsandboxid="), 0116 }; 0117 static const QStringList epicIgnoreArgsExact = { 0118 QStringLiteral("EpicPortal"), 0119 }; 0120 QStringRef argDashless(&arg); 0121 // Strip leading dashes. 0122 while (argDashless.startsWith('-')) { 0123 argDashless = argDashless.mid(1); 0124 } 0125 Q_FOREACH(const auto &argToIgnore, epicIgnoreArgsStart) { 0126 if (argDashless.startsWith(argToIgnore, Qt::CaseInsensitive)) { 0127 return true; 0128 } 0129 } 0130 Q_FOREACH(const auto &argToIgnore, epicIgnoreArgsExact) { 0131 if (argDashless.compare(argToIgnore, Qt::CaseInsensitive) == 0) { 0132 return true; 0133 } 0134 } 0135 return false; 0136 }; 0137 0138 QStringListIterator iter(app.arguments()); 0139 if (iter.hasNext()) { 0140 // First argument is application name. 0141 filteredArgs.append(iter.next()); 0142 0143 bool isAfterDoubleDash = false; 0144 while (iter.hasNext()) { 0145 QString arg = iter.next(); 0146 if (arg == QLatin1String("--")) { 0147 isAfterDoubleDash = true; 0148 } 0149 if (isAfterDoubleDash || !checkIsIgnoreEpic(arg)) { 0150 filteredArgs.append(arg); 0151 } 0152 } 0153 } 0154 } 0155 0156 parser.process(filteredArgs); 0157 0158 QString dpiValues = parser.value("dpi"); 0159 if (!dpiValues.isEmpty()) { 0160 qWarning() << "The `dpi` argument does nothing!"; 0161 } 0162 0163 QString newImageValues = parser.value("new-image"); 0164 d->newImage = !newImageValues.isEmpty(); 0165 if (d->newImage) { 0166 QStringList v = newImageValues.split(","); 0167 if (v.size() != 4) { 0168 d->newImage = false; 0169 qWarning() << "Cannot create a new image: please specify colormodel, depth, width and height."; 0170 } 0171 d->colorModel = v[0].toUpper(); 0172 d->colorDepth = v[1].toUpper(); 0173 d->width = v[2].toInt(); 0174 d->height = v[3].toInt(); 0175 } 0176 0177 d->fileLayer = parser.value("file-layer"); 0178 d->exportFileName = parser.value("export-filename"); 0179 d->workspace = parser.value("workspace"); 0180 d->windowLayout = parser.value("windowlayout"); 0181 d->session = parser.value("load-session"); 0182 d->doTemplate = parser.isSet("template"); 0183 d->exportAs = parser.isSet("export"); 0184 d->exportSequence = parser.isSet("export-sequence"); 0185 d->canvasOnly = parser.isSet("canvasonly"); 0186 d->noSplash = parser.isSet("nosplash"); 0187 d->fullScreen = parser.isSet("fullscreen"); 0188 0189 KoResourcePaths::s_overrideAppDataLocation = parser.value("resource-location"); 0190 0191 const QDir currentDir = QDir::current(); 0192 Q_FOREACH (const QString &filename, parser.positionalArguments()) { 0193 d->filenames << currentDir.absoluteFilePath(filename); 0194 } 0195 } 0196 0197 KisApplicationArguments::KisApplicationArguments(const KisApplicationArguments &rhs) 0198 : d(new Private) 0199 { 0200 d->filenames = rhs.filenames(); 0201 d->dpiX = rhs.d->dpiX; 0202 d->dpiY = rhs.d->dpiY; 0203 d->doTemplate = rhs.doTemplate(); 0204 d->exportAs = rhs.exportAs(); 0205 d->exportFileName = rhs.exportFileName(); 0206 d->canvasOnly = rhs.canvasOnly(); 0207 d->workspace = rhs.workspace(); 0208 d->windowLayout = rhs.windowLayout(); 0209 d->session = rhs.session(); 0210 d->noSplash = rhs.noSplash(); 0211 d->fullScreen = rhs.fullScreen(); 0212 0213 } 0214 0215 void KisApplicationArguments::operator=(const KisApplicationArguments &rhs) 0216 { 0217 d->filenames = rhs.filenames(); 0218 d->dpiX = rhs.d->dpiX; 0219 d->dpiY = rhs.d->dpiY; 0220 d->doTemplate = rhs.doTemplate(); 0221 d->exportAs = rhs.exportAs(); 0222 d->exportFileName = rhs.exportFileName(); 0223 d->canvasOnly = rhs.canvasOnly(); 0224 d->workspace = rhs.workspace(); 0225 d->windowLayout = rhs.windowLayout(); 0226 d->session = rhs.session(); 0227 d->noSplash = rhs.noSplash(); 0228 d->fullScreen = rhs.fullScreen(); 0229 } 0230 0231 QByteArray KisApplicationArguments::serialize() 0232 { 0233 QBuffer buf; 0234 buf.open(QIODevice::WriteOnly); 0235 QDataStream ds(&buf); 0236 ds.setVersion(QDataStream::Qt_5_0); 0237 ds << d->filenames.count(); 0238 Q_FOREACH (const QString &filename, d->filenames) { 0239 ds << filename; 0240 } 0241 ds << d->dpiX; 0242 ds << d->dpiY; 0243 ds << d->doTemplate; 0244 ds << d->exportAs; 0245 ds << d->exportFileName; 0246 ds << d->workspace; 0247 ds << d->windowLayout; 0248 ds << d->session; 0249 ds << d->canvasOnly; 0250 ds << d->noSplash; 0251 ds << d->fullScreen; 0252 ds << d->newImage; 0253 ds << d->height; 0254 ds << d->width; 0255 ds << d->height; 0256 ds << d->colorModel; 0257 ds << d->colorDepth; 0258 ds << d->fileLayer; 0259 0260 buf.close(); 0261 0262 return buf.data(); 0263 } 0264 0265 KisApplicationArguments KisApplicationArguments::deserialize(QByteArray &serialized) 0266 { 0267 KisApplicationArguments args; 0268 0269 QBuffer buf(&serialized); 0270 buf.open(QIODevice::ReadOnly); 0271 QDataStream ds(&buf); 0272 ds.setVersion(QDataStream::Qt_5_0); 0273 int count; 0274 ds >> count; 0275 for(int i = 0; i < count; ++i) { 0276 QString s; 0277 ds >> s; 0278 args.d->filenames << s; 0279 } 0280 ds >> args.d->dpiX; 0281 ds >> args.d->dpiY; 0282 ds >> args.d->doTemplate; 0283 ds >> args.d->exportAs; 0284 ds >> args.d->exportFileName; 0285 ds >> args.d->workspace; 0286 ds >> args.d->windowLayout; 0287 ds >> args.d->session; 0288 ds >> args.d->canvasOnly; 0289 ds >> args.d->noSplash; 0290 ds >> args.d->fullScreen; 0291 ds >> args.d->newImage; 0292 ds >> args.d->height; 0293 ds >> args.d->width; 0294 ds >> args.d->height; 0295 ds >> args.d->colorModel; 0296 ds >> args.d->colorDepth; 0297 ds >> args.d->fileLayer; 0298 0299 buf.close(); 0300 0301 return args; 0302 } 0303 0304 QStringList KisApplicationArguments::filenames() const 0305 { 0306 return d->filenames; 0307 } 0308 0309 bool KisApplicationArguments::doTemplate() const 0310 { 0311 return d->doTemplate; 0312 } 0313 0314 bool KisApplicationArguments::exportAs() const 0315 { 0316 return d->exportAs; 0317 } 0318 0319 bool KisApplicationArguments::exportSequence() const 0320 { 0321 return d->exportSequence; 0322 } 0323 0324 QString KisApplicationArguments::exportFileName() const 0325 { 0326 return d->exportFileName; 0327 } 0328 0329 QString KisApplicationArguments::workspace() const 0330 { 0331 return d->workspace; 0332 } 0333 0334 QString KisApplicationArguments::windowLayout() const 0335 { 0336 return d->windowLayout; 0337 } 0338 0339 QString KisApplicationArguments::session() const 0340 { 0341 return d->session; 0342 } 0343 0344 QString KisApplicationArguments::fileLayer() const 0345 { 0346 return d->fileLayer; 0347 } 0348 0349 bool KisApplicationArguments::canvasOnly() const 0350 { 0351 return d->canvasOnly; 0352 } 0353 0354 bool KisApplicationArguments::noSplash() const 0355 { 0356 return d->noSplash; 0357 } 0358 0359 bool KisApplicationArguments::fullScreen() const 0360 { 0361 return d->fullScreen; 0362 } 0363 0364 bool KisApplicationArguments::doNewImage() const 0365 { 0366 return d->newImage; 0367 } 0368 0369 KisDocument *KisApplicationArguments::createDocumentFromArguments() const 0370 { 0371 KisDocument *doc = KisPart::instance()->createDocument(); 0372 const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(d->colorModel, d->colorDepth, ""); 0373 if (!cs) { 0374 qWarning() << "Could not create the colorspace for the new image. Check the colorspace and depth arguments."; 0375 return 0; 0376 } 0377 0378 doc->newImage(i18n("Unnamed"), d->width, d->height, cs, KoColor(QColor(Qt::white), cs), KisConfig::CANVAS_COLOR, 1, "", 100.0); 0379 return doc; 0380 }