From 37acf9383cd13d8e53edb63fbf84aa2b9f598e2c Mon Sep 17 00:00:00 2001 From: lupoDharkael Date: Sun, 30 Jul 2017 18:08:25 +0200 Subject: [PATCH] Improve CLI commands - Add configuration commands - Improve error handling - Update DBus interface --- dbus/org.dharkael.Flameshot.xml | 20 +++ flameshot.pro | 4 +- src/core/flameshotdbusadapter.cpp | 36 +++-- src/core/flameshotdbusadapter.h | 5 +- src/main.cpp | 217 ++++++++++++++++++++++-------- 5 files changed, 212 insertions(+), 70 deletions(-) diff --git a/dbus/org.dharkael.Flameshot.xml b/dbus/org.dharkael.Flameshot.xml index 02c62c24..7ec71112 100644 --- a/dbus/org.dharkael.Flameshot.xml +++ b/dbus/org.dharkael.Flameshot.xml @@ -29,5 +29,25 @@ + + + + + + + + + + + diff --git a/flameshot.pro b/flameshot.pro index 6a11ac30..7db5f941 100644 --- a/flameshot.pro +++ b/flameshot.pro @@ -73,7 +73,7 @@ SOURCES += src/main.cpp\ src/capture/tools/toolfactory.cpp \ src/utils/confighandler.cpp \ src/core/controller.cpp \ - src/utils/systemnotification.cpp + src/utils/systemnotification.cpp \ HEADERS += \ src/capture/buttonhandler.h \ @@ -111,7 +111,7 @@ HEADERS += \ src/capture/tools/toolfactory.h \ src/utils/confighandler.h \ src/core/controller.h \ - src/utils/systemnotification.h + src/utils/systemnotification.h \ RESOURCES += \ graphics.qrc diff --git a/src/core/flameshotdbusadapter.cpp b/src/core/flameshotdbusadapter.cpp index 38492e3a..3ebaafce 100644 --- a/src/core/flameshotdbusadapter.cpp +++ b/src/core/flameshotdbusadapter.cpp @@ -17,9 +17,10 @@ #include "flameshotdbusadapter.h" #include "src/utils/confighandler.h" +#include "src/core/controller.h" #include -FlameshotDBusAdapter::FlameshotDBusAdapter(Controller *parent) +FlameshotDBusAdapter::FlameshotDBusAdapter(QObject *parent) : QDBusAbstractAdaptor(parent) { @@ -29,23 +30,32 @@ FlameshotDBusAdapter::~FlameshotDBusAdapter() { } -Controller *FlameshotDBusAdapter::parent() const { - return static_cast(QObject::parent()); -} - void FlameshotDBusAdapter::graphicCapture(QString path, int delay) { - auto p = parent(); - auto f = [p, path, this]() { - p->createVisualCapture(path); + auto controller = Controller::getInstance(); + auto f = [controller, path, this]() { + controller->createVisualCapture(path); }; - QTimer::singleShot(delay, p, f); + QTimer::singleShot(delay, controller, f); } void FlameshotDBusAdapter::fullScreen(QString path, bool toClipboard, int delay) { - auto p = parent(); - auto f = [p, path, toClipboard, this]() { - p->saveScreenshot(path, toClipboard); + auto controller = Controller::getInstance(); + auto f = [controller, path, toClipboard, this]() { + controller->saveScreenshot(path, toClipboard); }; - QTimer::singleShot(delay, p, f); + QTimer::singleShot(delay, controller, f); } + +void FlameshotDBusAdapter::openConfig() { + Controller::getInstance()->openConfigWindow(); +} + +void FlameshotDBusAdapter::trayIconEnabled(bool enabled) { + auto controller = Controller::getInstance(); + if (enabled) { + controller->enableTrayIcon(); + } else { + controller->disableTrayIcon(); + } +} diff --git a/src/core/flameshotdbusadapter.h b/src/core/flameshotdbusadapter.h index df349466..3a0ec17d 100644 --- a/src/core/flameshotdbusadapter.h +++ b/src/core/flameshotdbusadapter.h @@ -27,13 +27,14 @@ class FlameshotDBusAdapter : public QDBusAbstractAdaptor Q_CLASSINFO("D-Bus Interface", "org.dharkael.Flameshot") public: - FlameshotDBusAdapter(Controller *parent = nullptr); + FlameshotDBusAdapter(QObject *parent = nullptr); virtual ~FlameshotDBusAdapter(); - inline Controller *parent() const; public slots: Q_NOREPLY void graphicCapture(QString path, int delay); Q_NOREPLY void fullScreen(QString path, bool toClipboard, int delay); + Q_NOREPLY void openConfig(); + Q_NOREPLY void trayIconEnabled(bool enabled); }; diff --git a/src/main.cpp b/src/main.cpp index 787862ca..aa08c013 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 #include #include @@ -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; }