Improve CLI commands

- Add configuration commands
- Improve error handling
- Update DBus interface
This commit is contained in:
lupoDharkael
2017-07-30 18:08:25 +02:00
parent 6bb7746d17
commit 37acf9383c
5 changed files with 212 additions and 70 deletions

View File

@@ -18,6 +18,8 @@
#include "src/core/controller.h"
#include "singleapplication.h"
#include "src/core/flameshotdbusadapter.h"
#include "src/utils/filenamehandler.h"
#include "src/utils/confighandler.h"
#include <QApplication>
#include <QTranslator>
#include <QObject>
@@ -49,89 +51,198 @@ int main(int argc, char *argv[]) {
return app.exec();
}
/*--------------|
* CLI parsing |
* ------------*/
QCoreApplication app(argc, argv);
app.installTranslator(&translator);
app.setApplicationName("flameshot");
app.setOrganizationName("Dharkael");
// CLI parsing
app.setApplicationVersion(qApp->applicationVersion());
QCommandLineParser parser;
QCommandLineOption versionOption(QStringList() << "v" << "version",
"Show version information");
parser.addOption(versionOption);
parser.addHelpOption();
// Add description
parser.setApplicationDescription(
"Powerfull yet simple to use screenshot software.");
// Command descriptions
QString fullDescription = "Capture the entire desktop.";
QString guiDescription = "Start a manual capture in GUI mode.";
parser.addPositionalArgument("mode", "full\t"+fullDescription+"\n"
"gui\t"+guiDescription,
QString configDescription = "Configure flameshot.";
// Positional alguments
parser.addPositionalArgument("mode", "full\t" + fullDescription + "\n"+
"gui\t" + guiDescription + "\n" +
"config\t" + configDescription,
"mode [mode_options]");
// Add options
parser.addHelpOption();
parser.addVersionOption();
// Initial parse ---------------------------------
parser.parse(app.arguments());
QTextStream out(stdout);
// show app version
if (parser.isSet("version")) {
qInfo().noquote() << "Flameshot" << qApp->applicationVersion()
<< "\nCompiled with Qt" << QT_VERSION_STR;
return 0;
}
const QStringList args = parser.positionalArguments();
const QString command = args.isEmpty() ? QString() : args.first();
// CLI options
QCommandLineOption pathOption(QStringList() << "p" << "path",
"Path where the capture will be saved", "");
"Path where the capture will be saved", "path");
QCommandLineOption clipboardOption({{"c", "clipboard"},
"Save the capture to the clipboard"});
QCommandLineOption delayOption(QStringList() << "d" << "delay",
"Delay time in milliseconds", "0");
// parse commands
if (command == "full") {
parser.clearPositionalArguments();
parser.addPositionalArgument(
"full", fullDescription, "full [full_options]");
parser.addOptions({ pathOption, clipboardOption, delayOption });
} else if (command == "gui") {
"Delay time in milliseconds", "milliseconds");
QCommandLineOption filenameOption("filename", "Set the filename pattern", "pattern");
QCommandLineOption trayOption("trayicon", "Enable or disable the trayicon", "bool");
QCommandLineOption showHelpOption("showhelp", "Show the help message in the capture mode", "bool");
// add here the names of the options without required values after the tag
QStringList optionsWithoutValue = QStringList()
<< clipboardOption.names();
// Second parse ----------------------------------
/* Detect undesired elements
* This is a very hacky solution to filter undesired arguments.
* I may consider changing to a better cli parsing library for
* this kind of command structure.
*/
auto args = app.arguments().mid(1); // ignore the first
QStringList commandList{"gui", "full", "config"};
auto i = args.cbegin();
QString val = (*i);
bool ok = commandList.contains(val);
// check first
for (++i; i != args.cend(); ++i) {
if (!ok) break;
val = (*i);
if(val.startsWith("-")) {
// skip next when
// - the parameter is not in the format -flag=100
// - there are more elements to check
// - it's a flag and it requires a value
bool skipNext = (!val.contains("=") && i+1 != args.cend()
&& !optionsWithoutValue.contains(val.remove("-")));
if (skipNext) ++i;
} else { // not a flag
ok = false;
}
}
// obtain the command
QString command;
if (ok && parser.positionalArguments().count() > 0) {
command = parser.positionalArguments().first();
}
// GUI
if (command == "gui") {
// Description
parser.clearPositionalArguments();
parser.addPositionalArgument(
"gui", guiDescription, "gui [gui_options]");
parser.addOptions({ pathOption, delayOption });
}
parser.process(app);
parser.process(app);
// obtain values
QDBusMessage m;
QString pathValue;
if (parser.isSet("path")) {
pathValue = QString::fromStdString(parser.value("path").toStdString());
if (!QDir(pathValue).exists()) {
qWarning().noquote() << QObject::tr("Invalid path.");
return 0;
// paramenters
QString pathValue;
if (parser.isSet(pathOption)) {
pathValue = QString::fromStdString(parser.value("path").toStdString());
if (!QDir(pathValue).exists()) {
qWarning().noquote() << "Invalid path.";
return 0;
}
}
}
int delay = 0;
if (parser.isSet("delay")) {
delay = parser.value("delay").toInt();
if (delay < 0) {
qWarning().noquote() << QObject::tr("Invalid negative delay.");
return 0;
int delay = 0;
if (parser.isSet(delayOption)) {
delay = parser.value("delay").toInt();
if (delay < 0) {
qWarning().noquote() << "Invalid negative delay.";
return 0;
}
}
}
// process commands
if (command == "gui") {
m = QDBusMessage::createMethodCall("org.dharkael.Flameshot",
// Send message
QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot",
"/", "", "graphicCapture");
m << pathValue << delay;
QDBusConnection::sessionBus().call(m);
} else if (command == "full") {
m = QDBusMessage::createMethodCall("org.dharkael.Flameshot",
}
// FULL
else if (command == "full") {
// Description
parser.clearPositionalArguments();
parser.addPositionalArgument(
"full", fullDescription, "full [full_options]");
parser.addOptions({ pathOption, clipboardOption, delayOption });
parser.process(app);
// paramenters
QString pathValue;
if (parser.isSet(pathOption)) {
pathValue = QString::fromStdString(parser.value("path").toStdString());
if (!QDir(pathValue).exists()) {
qWarning().noquote() << "Invalid path.";
return 0;
}
}
int delay = 0;
if (parser.isSet(delayOption)) {
delay = parser.value("delay").toInt();
if (delay < 0) {
qWarning().noquote() << "Invalid negative delay.";
return 0;
}
}
// Send message
QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot",
"/", "", "fullScreen");
m << pathValue << parser.isSet("clipboard") << delay;
QDBusConnection::sessionBus().call(m);
}
// CONFIG
else if (command == "config") {
// Description
parser.clearPositionalArguments();
parser.addPositionalArgument(
"config", configDescription, "config [config_options]");
parser.addOptions({ filenameOption, trayOption, showHelpOption });
parser.process(app);
bool filename = parser.isSet(filenameOption);
bool tray = parser.isSet(trayOption);
bool help = parser.isSet(showHelpOption);
bool someFlagSet = (filename || tray || help);
ConfigHandler config;
if (filename) {
QString newFilename(parser.value(filenameOption));
config.setFilenamePattern(newFilename);
FileNameHandler fh;
out << "The new pattern is " << newFilename
<< "\nParsed pattern example: "
<< fh.getParsedPattern() << "\n";
}
if (tray) {
QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot",
"/", "", "trayIconEnabled");
if (parser.value(trayOption) == "false") {
m << false;
} else if (parser.value(trayOption) == "true") {
m << true;
}
QDBusConnection::sessionBus().call(m);
}
if (help) {
if (parser.value(showHelpOption) == "false") {
config.setShowHelp(false);
} else if (parser.value(showHelpOption) == "true") {
config.setShowHelp(true);
}
}
// Open gui when no options
if (!someFlagSet) {
QDBusMessage m = QDBusMessage::createMethodCall("org.dharkael.Flameshot",
"/", "", "openConfig");
QDBusConnection::sessionBus().call(m);
}
} else {
qWarning().noquote() << "Invalid command, see 'flameshot --help'.";
parser.process(app.arguments());
}
return 0;
}