mirror of
https://github.com/fergalmoran/flameshot.git
synced 2026-04-05 06:49:03 +00:00
Improve CLI commands
- Add configuration commands - Improve error handling - Update DBus interface
This commit is contained in:
@@ -29,5 +29,25 @@
|
||||
<arg name="delay" type="i" direction="in"/>
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
openConfig:
|
||||
|
||||
Opens the configuration window.
|
||||
-->
|
||||
<method name="openConfig">
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
trayIconEnabled:
|
||||
@enabled: The new state fot the trayIcon.
|
||||
|
||||
Enable or disable the trayIcon.
|
||||
-->
|
||||
<method name="trayIconEnabled">
|
||||
<arg name="enabled" type="b" direction="in"/>
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
|
||||
#include "flameshotdbusadapter.h"
|
||||
#include "src/utils/confighandler.h"
|
||||
#include "src/core/controller.h"
|
||||
#include <QTimer>
|
||||
|
||||
FlameshotDBusAdapter::FlameshotDBusAdapter(Controller *parent)
|
||||
FlameshotDBusAdapter::FlameshotDBusAdapter(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
|
||||
@@ -29,23 +30,32 @@ FlameshotDBusAdapter::~FlameshotDBusAdapter() {
|
||||
|
||||
}
|
||||
|
||||
Controller *FlameshotDBusAdapter::parent() const {
|
||||
return static_cast<Controller *>(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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
217
src/main.cpp
217
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 <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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user