From 9d062642afc0612c11ef837bd67ef8fc55a0b5dd Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Sat, 9 Apr 2016 14:50:54 +0200 Subject: [PATCH 01/33] Fix indentation Using 4 spaces as levels of indentation: * Use another level of indentation for the case-statements. * Use two levels of indentation for wrapped arguments. --- src/ckb/main.cpp | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index cf78909..c2276e3 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -178,34 +178,34 @@ int main(int argc, char *argv[]){ // Parse arguments switch (parseCommandLine(parser, &errorMessage)) { - case CommandLineOK: - // If launched with no argument - break; - case CommandLineError: - fputs(qPrintable(errorMessage), stderr); - fputs("\n\n", stderr); - fputs(qPrintable(parser.helpText()), stderr); - return 1; - case CommandLineVersionRequested: - // If launched with --version, print version info and then quit - printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), - qPrintable(QCoreApplication::applicationVersion())); - return 0; - case CommandLineHelpRequested: - // If launched with --help, print help and then quit - parser.showHelp(); - return 0; - case CommandLineClose: - // If launched with --close, kill existing app - if (isRunning("Close")) - printf("Asking existing instance to close.\n"); - else - printf("ckb is not running.\n"); - return 0; - case CommandLineBackground: - // If launched with --background, launch in background - background = 1; - break; + case CommandLineOK: + // If launched with no argument + break; + case CommandLineError: + fputs(qPrintable(errorMessage), stderr); + fputs("\n\n", stderr); + fputs(qPrintable(parser.helpText()), stderr); + return 1; + case CommandLineVersionRequested: + // If launched with --version, print version info and then quit + printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), + qPrintable(QCoreApplication::applicationVersion())); + return 0; + case CommandLineHelpRequested: + // If launched with --help, print help and then quit + parser.showHelp(); + return 0; + case CommandLineClose: + // If launched with --close, kill existing app + if (isRunning("Close")) + printf("Asking existing instance to close.\n"); + else + printf("ckb is not running.\n"); + return 0; + case CommandLineBackground: + // If launched with --background, launch in background + background = 1; + break; } #ifdef Q_OS_LINUX From 84970c17b95c2b4c3f0345dbc04ccebc99f681f0 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Sat, 9 Apr 2016 22:50:35 +0200 Subject: [PATCH 02/33] Add specifications for this branch The 'cli-specs.md' file gathers all information for implementing the CLI. It states the (currently) supported operations as well as a grammar to understand. This file should help keep track of necessities to implement and idiosyncrasies to consider. --- cli-specs.md | 277 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 cli-specs.md diff --git a/cli-specs.md b/cli-specs.md new file mode 100644 index 0000000..09d1a1f --- /dev/null +++ b/cli-specs.md @@ -0,0 +1,277 @@ +# CLI + +The command line interface is a fully scriptable interface to the user. + +## Idea + +Pass in a specific switch/flag - for example `--cmd` - to enter command mode and interpret subsequent strings as the command to execute. + +## Available operations + +Gather all available operations/commands here to have an overview and a guideline for parsing the given operation strings. + +Additionally there should be a help page to display the available operations and the commands for them. The tooltip text can be used for this endeavour. + +### Settings + +* list all available keyboard layouts +* set keyboard layout +* list available modifier keys (notify of keyboard profile/binding) + * OSX has different source keys! (i.e. Option, Command instead of Alt, Super) +* set modifier key to different key +* reset modifier keys +* display and set _frame rate_ +* display and set _directory of animation scripts_ +* display and set _brightness per-mode_ +* display and set _spatial dithering to simulate extra color resolution_ +* display and set _disable mouse acceleration_ (only on OSX) +* display and set _disable scroll acceleration_ (only on OSX) +* display and set _scroll acceleration speed_ (only on OSX) +* display and set _check for new firmware automatically_ +* display and set _show tray icon_ +* display and set _macro delay_ + +### Keyboard + +* List Profiles +* Create/Rename/Duplicate/Move Profile +* Save Profile to Hardware +* List Modes +* Create/Rename/Duplicate/Move Modes + +#### Lighting + +* display and set _key color_ +* display and set _key brightness_ +* display and set _key animation_ + +#### Binding + +* display, set and/or add _key bind_ + * bind to keyboard input (char, function, media, modifier, etc.) + * bind to mouse input (button, wheel, special button, change DPI, etc.) + * bind to animation (currently assigned animations) + * bind to special (switch mode, brightness, windows lock) + * bind to program (run script/program on press/release) +* copy bindings to mode +* bind macro action, text and comment to key + +#### Performance + +* display and set _indicator intensity_ +* display and set value of _indicator intensity_ +* display and set _indicate brightness_ +* display and set value of _indicate brightness_ (33%, 67%, 100%) +* display and set _indicate windows lock_ +* display and set value of _indicate windows lock_ (on, off) +* display and set _indicate mute_ +* display and set value of _indicate mute_ (on, off, unknown) +* list available modes for lock keys +* display and set _num lock_ +* display and set value of _num lock_ (on, off) +* display and set _caps lock_ +* display and set value of _caps lock_ (on, off) +* display and set _scroll lock_ (display warning because of scroll lock) +* display and set value of _scroll lock_ (on, off) + +#### Device + +* display information about device + * _USB device ID_ + * _Poll Rate_ + * _Firmware Version_ + * _Status_ +* update firmware + * automatically (via internet) + * manually (via file) + +### Mouse + +* List Profiles +* Create/Rename/Duplicate/Move Profile +* Save Profile to Hardware +* List Modes +* Create/Rename/Duplicate/Move Modes + +#### Lighting + +* display and set _key color_ +* display and set _key brightness_ +* display and add _key animation_ + +#### Binding + +* display, set and/or add _key bind_ + * bind to keyboard input (char, function, media, modifier, etc.) + * bind to mouse input (button, wheel, special button, change DPI, etc.) + * bind to animation (currently assigned animations) + * bind to special (switch mode, brightness, windows lock) + * bind to programm (run script/program on press/release) +* copy bindings to mode + +#### Performance + +* display and set _use DPI indicator_ +* display and set _DPI Indicator percentage_ +* display and set _independent X/Y states_ +* list DPI Stages with X/Y values +* display and set stages 1-5 + sniper & other +* display and set _angle snap_ +* list _lift height_ values +* display and set _lift height_ +* copy performance to mode + +#### Device + +* display information about device + * _USB device ID_ + * _Poll Rate_ + * _Firmware Version_ + * _Status_ +* update firmware + * automatically (via internet) + * manually (via file) + +## Grammar + +Generally the command line interface needs a different approach, than the GUI. For example does the GUI display all information concisely, while the _cli_ can only display a set of information at a time triggered by a command. Thus the grouping has to be different than the GUI does it. + +``` + ::= "global" + | "device" [] + | "profile" [] + ::= + ::= + + ::= "up" | "down" + ::= "#" + | "(" "," "," ")" +``` + +### Global Commands + +``` + ::= "info" + | "layout" + | "modifier" + | "framerate" + | "animation-dir" + | "brightness-per-mode" + | "spatial-dithering" + | "firmware-autocheck" + | "tray-icon" + | "mouse-acceleration" + | "scroll-acceleration" + | "scroll-acceleration-speed" + + ::= "show" | "set" + ::= "show" | "set" + ::= "show" | "set" + ::= "show" | "enable" | "disable" + + ::= "list" | "set" + ::= "EU" | "EU_DVORAK" + | "GB" | "GB_DVORAK" + | "US" | "US_DVORAK" + | "FR" | "DE" | "IT" | "PL" | "MX" | "ES" | "SE" + + ::= "list" | "set " | "reset" + ::= "lshift" | "lctrl" | "lwin" | "lalt" | "caps" | "menu" + | "rshift" | "rctrl" | "rwin" | "ralt" | "fn" | "altgr" + ::= "caps" | "shift" | "ctrl" | "option" | "cmd" | "alt" | "super" + + ::= | "scan" +``` + +### Device Commands + +``` + ::= "" | "info" + | "show profile" + | "set profile" + | "firmware" + + ::= "show" + | "update" [] +``` + +### Profile Commands + +``` + ::= "" | "list" + | "create" + | "duplicate" + | "rename" + | "move" + | "mode" + ::= + + ::= "list" + | "create" + | "duplicate" + | "rename" + | "move" + | "animation" + | "lighting" + | "bind" + | "performance" + + ::= "list" + | "show" + | "delete" + | "set" + + ::= "brightness" + | "color" + | "animation" + ::= "show" | "set" + ::= "show" | "set" + ::= "show" | "set" + + ::= "list" + | "show" + | "set" + | "copy" + | "reset" + | "macro" + + ::= + ::= "" + | "+" + | + ::= | "+" + ::= + | + ::= + + ::= + ::= "" | + ::= "" | + ::= "" | + + ::= "copy" + | "intensity" + | "indicator" + | "lock" + | "dpi" + + ::= + ::= "brightness" | "windows-lock" | "mute" + ::= "show" | "enable" | "disable" | set + ::= "0" | "1" | "2" + + ::= "list" + | "indicator" + | "independent-axes" + | "stage" "set" "x" ["y" ] + | "angle-snap" + | "lift-height" + ::= | "set" + ::= "0" | "1" | "2" | "3" | "4" | "5" | "other" + + ::= "show" | + ::= "num" | "caps" | "scroll" + ::= "set" | "set" + ::= "normal" | "always-on" | "always-off" | "RGB" | "normal-rgb" + ::= "0" | "1" +``` From f840449f227966fcc1226a8182883064da77a049 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 14 Apr 2016 00:36:34 +0200 Subject: [PATCH 03/33] Initial Commit of CLI functionality Add stubs to parse a `-x`, `--cmd` and `--execute` options. * Add CommandLineOptions to catch these cases. * Add CommandLine stub class in 'cli.h'/'cli.cpp' files. * Add these files to 'ckb.pro'. --- src/ckb/ckb.pro | 6 ++++-- src/ckb/cli.cpp | 17 +++++++++++++++++ src/ckb/cli.h | 14 ++++++++++++++ src/ckb/main.cpp | 16 +++++++++++++++- 4 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/ckb/cli.cpp create mode 100644 src/ckb/cli.h diff --git a/src/ckb/ckb.pro b/src/ckb/ckb.pro index 1a6ea11..4a9e783 100644 --- a/src/ckb/ckb.pro +++ b/src/ckb/ckb.pro @@ -101,7 +101,8 @@ SOURCES += main.cpp\ extrasettingswidget.cpp \ kbmanager.cpp \ colormap.cpp \ - macroreader.cpp + macroreader.cpp \ + cli.cpp HEADERS += mainwindow.h \ kbwidget.h \ @@ -159,7 +160,8 @@ HEADERS += mainwindow.h \ extrasettingswidget.h \ kbmanager.h \ colormap.h \ - macroreader.h + macroreader.h \ + cli.h FORMS += mainwindow.ui \ kbwidget.ui \ diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp new file mode 100644 index 0000000..af86b42 --- /dev/null +++ b/src/ckb/cli.cpp @@ -0,0 +1,17 @@ +#include "cli.h" + + +void CommandLine::execute(QStringList args) { + QStringList::const_iterator constIterator; + + // TODO: delegate accumulated commands to own handler, where command is executed + // * create instance of cli class/namespace + // * pass all remaining arguments to cli handler + // * catch return value and handle teardown code + int index = 0; + for (constIterator = args.constBegin(); constIterator != args.constEnd(); ++constIterator) { + fprintf(stdout, "%03d: %s\n", index++, qPrintable((*constIterator).toLocal8Bit().constData())); + } + + return; +} diff --git a/src/ckb/cli.h b/src/ckb/cli.h new file mode 100644 index 0000000..d0fa6c7 --- /dev/null +++ b/src/ckb/cli.h @@ -0,0 +1,14 @@ +#ifndef CKB_CLI_H +#define CKB_CLI_H + +/* Include Section */ +#include + +class CommandLine : public QObject +{ + Q_OBJECT +public: + static void execute(QStringList args); +}; + +#endif // CKB_CLI_H diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index c2276e3..21e79db 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include "cli.h" QSharedMemory appShare("ckb"); @@ -27,7 +28,8 @@ enum CommandLineParseResults { CommandLineVersionRequested, CommandLineHelpRequested, CommandLineClose, - CommandLineBackground + CommandLineBackground, + CommandLineCommand }; /** @@ -55,6 +57,10 @@ CommandLineParseResults parseCommandLine(QCommandLineParser &parser, QString *er const QCommandLineOption closeOption(QStringList() << "c" << "close", "Causes already running instance (if any) to exit."); parser.addOption(closeOption); + // add -x, --cmd, --execute + const QCommandLineOption commandOption(QStringList() << "x" << "cmd" << "execute", + "Execute the given command without a GUI."); + parser.addOption(commandOption); /* parse arguments */ if (!parser.parse(QCoreApplication::arguments())) { @@ -84,6 +90,11 @@ CommandLineParseResults parseCommandLine(QCommandLineParser &parser, QString *er return CommandLineClose; } + if (parser.isSet(commandOption)) { + // parse input and execute appropriate command + return CommandLineCommand; + } + /* no explicit argument was passed */ return CommandLineOK; }; @@ -206,6 +217,9 @@ int main(int argc, char *argv[]){ // If launched with --background, launch in background background = 1; break; + case CommandLineCommand: + // If launched with --cmd, try to execute given command + CommandLine::execute(QCoreApplication::arguments()); } #ifdef Q_OS_LINUX From ae3d31ec885cf574eb74d29fe54509277cba806d Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Sun, 5 Jun 2016 00:37:55 +0200 Subject: [PATCH 04/33] Run ckb in background on cli command Move cli-command handler in main program to pass through the background handler. This way the ckb program is automatically run in background on executing a cli command. This was discussed in issue #213. --- src/ckb/main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index 21e79db..9dbd4e6 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -213,13 +213,14 @@ int main(int argc, char *argv[]){ else printf("ckb is not running.\n"); return 0; + case CommandLineCommand: + // If launched with --cmd, try to execute given command + static int cli_error = CommandLine::execute(QCoreApplication::arguments()); + // Also run ckb in background on execute command case CommandLineBackground: // If launched with --background, launch in background background = 1; break; - case CommandLineCommand: - // If launched with --cmd, try to execute given command - CommandLine::execute(QCoreApplication::arguments()); } #ifdef Q_OS_LINUX From d68c7eadefa4ac7807153cdf54f9b9fdec4e27e7 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Sun, 5 Jun 2016 00:40:08 +0200 Subject: [PATCH 05/33] Add exit codes to cli handler To handle potential errors in cli operations by adding result codes, that can be returned to the main program. * Add enum to header definitons of the CommandLine class. * Return the `CommandLineOK` code by default. * Read return code of CommandLine in main routine. --- src/ckb/cli.cpp | 4 ++-- src/ckb/cli.h | 5 ++++- src/ckb/main.cpp | 4 ++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index af86b42..206600c 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,7 +1,7 @@ #include "cli.h" -void CommandLine::execute(QStringList args) { +int CommandLine::execute(QStringList args) { QStringList::const_iterator constIterator; // TODO: delegate accumulated commands to own handler, where command is executed @@ -13,5 +13,5 @@ void CommandLine::execute(QStringList args) { fprintf(stdout, "%03d: %s\n", index++, qPrintable((*constIterator).toLocal8Bit().constData())); } - return; + return CommandLineOK; } diff --git a/src/ckb/cli.h b/src/ckb/cli.h index d0fa6c7..f2ee23f 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -8,7 +8,10 @@ class CommandLine : public QObject { Q_OBJECT public: - static void execute(QStringList args); + enum CommandLineResult { + CommandLineOK + }; + static int execute(QStringList args); }; #endif // CKB_CLI_H diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index 9dbd4e6..2ee963d 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -217,6 +217,10 @@ int main(int argc, char *argv[]){ // If launched with --cmd, try to execute given command static int cli_error = CommandLine::execute(QCoreApplication::arguments()); // Also run ckb in background on execute command + if (cli_error) { + parser.showHelp(); + return cli_error; + } case CommandLineBackground: // If launched with --background, launch in background background = 1; From 754c08ef120838590a395d5d5f7ea801b0b8f0cb Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Sun, 5 Jun 2016 23:47:36 +0200 Subject: [PATCH 06/33] Add specifications for printing macro key binds As mentioned in issue #300 the cli should allow for printing all macro key definitions of the specified profile. --- cli-specs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cli-specs.md b/cli-specs.md index 09d1a1f..59ee7ab 100644 --- a/cli-specs.md +++ b/cli-specs.md @@ -233,7 +233,8 @@ Generally the command line interface needs a different approach, than the GUI. F | "set" | "copy" | "reset" - | "macro" + | "set-macro" + | "list-macros" ::= ::= "" From 09442cf3820a574cd48e0838fd029f063f1116a2 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Sun, 5 Jun 2016 23:53:26 +0200 Subject: [PATCH 07/33] Hide background warning on cli command Omit warning, that ckb is already running, if command line command was issued. --- src/ckb/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index 2ee963d..fbb0b6e 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -170,6 +170,7 @@ int main(int argc, char *argv[]){ QString errorMessage; parser.setApplicationDescription("Open Source Corsair Input Device Driver for Linux and OSX."); bool background = 0; + bool isCmd = 0; // Although the daemon runs as root, the GUI needn't and shouldn't be, as it has the potential to corrupt settings data. if(getuid() == 0){ @@ -216,11 +217,13 @@ int main(int argc, char *argv[]){ case CommandLineCommand: // If launched with --cmd, try to execute given command static int cli_error = CommandLine::execute(QCoreApplication::arguments()); - // Also run ckb in background on execute command if (cli_error) { + // display help text and errors, if command couldn't be executed parser.showHelp(); return cli_error; } + // Also run ckb in background on execute command + isCmd = 1; case CommandLineBackground: // If launched with --background, launch in background background = 1; @@ -235,7 +238,7 @@ int main(int argc, char *argv[]){ #endif if(isRunning(background ? 0 : "Open")){ - printf("ckb is already running. Exiting.\n"); + if (!isCmd) printf("ckb is already running. Exiting.\n"); return 0; } MainWindow w; From a1911593c091709f3931ffd0946898d059b748de Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Mon, 6 Jun 2016 12:30:35 +0200 Subject: [PATCH 08/33] Split parsing and running cmds in CommandLine cls In `execute()` split the arguments into base, flag and commands. Run the specified commands in the `run()` method. * Add `base`, `flag` and `commands` members. * Populate these members in the static `execute()` method. * Run the requested operations within the `commands` member in the new `run()` method. (Which is a stub at this point.) --- src/ckb/cli.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++------ src/ckb/cli.h | 6 ++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 206600c..34e591d 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,17 +1,56 @@ #include "cli.h" +#include +#include +/** + * run - Run specified Commands. + */ +int CommandLine::run() { + // TODO: parse commands and execute requested operation + printf("BaseCommand: %s\n", base.toLocal8Bit().data()); + printf("Flag : %s\n", flag.toLocal8Bit().data()); + printf("Arguments :\n"); + + for (int i = 0; i < commands.length(); i++) { + printf(" (%03d) %s\n", i, commands[i].toLocal8Bit().data()); + } + + // return with appropriate status + return CommandLineOK; +} + + +/** + * execute - Parse arguments and run specified commands. + * + * @param args QStringList of arguments to parse. + */ int CommandLine::execute(QStringList args) { QStringList::const_iterator constIterator; + CommandLine cli; - // TODO: delegate accumulated commands to own handler, where command is executed - // * create instance of cli class/namespace - // * pass all remaining arguments to cli handler - // * catch return value and handle teardown code + // setup command by splitting base, flag and actual command int index = 0; + QString item; for (constIterator = args.constBegin(); constIterator != args.constEnd(); ++constIterator) { - fprintf(stdout, "%03d: %s\n", index++, qPrintable((*constIterator).toLocal8Bit().constData())); + item = (*constIterator).toLocal8Bit().data(); + if (index == 0) { + // first arg is the base + cli.base = item; + } + else if (index == 1) { + // second arg is the flag + cli.flag = item; + } + else { + // the remaining args are the command to execute + cli.commands << item; + } + + index++; } - return CommandLineOK; + // run command + return cli.run(); } diff --git a/src/ckb/cli.h b/src/ckb/cli.h index f2ee23f..7e1cc69 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -7,7 +7,13 @@ class CommandLine : public QObject { Q_OBJECT +private: + int run(); public: + QString base; + QString flag; + QStringList commands; + enum CommandLineResult { CommandLineOK }; From 456eb8e31b3469d571932da034234cb6efd890da Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Mon, 13 Jun 2016 16:49:12 +0200 Subject: [PATCH 09/33] Fix indentation (again) This commit reverts some changes made in commit 9d06264. Remove one level of indentation for the case statements. This is done to ensure consistency with the project, instead of some coding convention. --- src/ckb/main.cpp | 74 ++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index fbb0b6e..57a767e 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -190,44 +190,44 @@ int main(int argc, char *argv[]){ // Parse arguments switch (parseCommandLine(parser, &errorMessage)) { - case CommandLineOK: - // If launched with no argument - break; - case CommandLineError: - fputs(qPrintable(errorMessage), stderr); - fputs("\n\n", stderr); - fputs(qPrintable(parser.helpText()), stderr); - return 1; - case CommandLineVersionRequested: - // If launched with --version, print version info and then quit - printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), - qPrintable(QCoreApplication::applicationVersion())); - return 0; - case CommandLineHelpRequested: - // If launched with --help, print help and then quit + case CommandLineOK: + // If launched with no argument + break; + case CommandLineError: + fputs(qPrintable(errorMessage), stderr); + fputs("\n\n", stderr); + fputs(qPrintable(parser.helpText()), stderr); + return 1; + case CommandLineVersionRequested: + // If launched with --version, print version info and then quit + printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), + qPrintable(QCoreApplication::applicationVersion())); + return 0; + case CommandLineHelpRequested: + // If launched with --help, print help and then quit + parser.showHelp(); + return 0; + case CommandLineClose: + // If launched with --close, kill existing app + if (isRunning("Close")) + printf("Asking existing instance to close.\n"); + else + printf("ckb is not running.\n"); + return 0; + case CommandLineCommand: + // If launched with --cmd, try to execute given command + static int cli_error = CommandLine::execute(QCoreApplication::arguments()); + if (cli_error) { + // display help text and errors, if command couldn't be executed parser.showHelp(); - return 0; - case CommandLineClose: - // If launched with --close, kill existing app - if (isRunning("Close")) - printf("Asking existing instance to close.\n"); - else - printf("ckb is not running.\n"); - return 0; - case CommandLineCommand: - // If launched with --cmd, try to execute given command - static int cli_error = CommandLine::execute(QCoreApplication::arguments()); - if (cli_error) { - // display help text and errors, if command couldn't be executed - parser.showHelp(); - return cli_error; - } - // Also run ckb in background on execute command - isCmd = 1; - case CommandLineBackground: - // If launched with --background, launch in background - background = 1; - break; + return cli_error; + } + // Also run ckb in background on execute command + isCmd = 1; + case CommandLineBackground: + // If launched with --background, launch in background + background = 1; + break; } #ifdef Q_OS_LINUX From e02e70ea1cb3989a6b115f6be49b568f89ed3800 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Mon, 13 Jun 2016 19:19:35 +0200 Subject: [PATCH 10/33] Add Command class Add class to track the selected command to execute. * Add identifiers to specify which command to execute. * Add method to differentiate and resolve command identifiers. --- src/ckb/cli.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ckb/cli.h | 34 ++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 34e591d..0f3842b 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -2,6 +2,61 @@ #include #include +/** + * resolveCommand - Resolve the given String to a Command identifier. + */ +int Command::resolveCommand(QString cmd) { + if (cmd.compare("global") == 0) { + return CommandGlobal; + } + else if (cmd.compare("device") == 0) { + return CommandDevice; + } + else if (cmd.compare("profile") == 0) { + return CommandProfile; + } + else if (cmd.compare("help") == 0) { + return CommandHelp; + } + else if (cmd.compare("info") == 0) { + return CommandInfo; + } + else if (cmd.compare("layout") == 0) { + return CommandLayout; + } + else if (cmd.compare("modifier") == 0) { + return CommandModifier; + } + else if (cmd.compare("framerate") == 0) { + return CommandFramerate; + } + else if (cmd.compare("animation-dir") == 0) { + return CommandAnimationDir; + } + else if (cmd.compare("brightness-per-mode") == 0) { + return CommandBrightnessPerMode; + } + else if (cmd.compare("spatial-dithering") == 0) { + return CommandSpatialDithering; + } + else if (cmd.compare("firmware-autocheck") == 0) { + return CommandFirmwareAutocheck; + } + else if (cmd.compare("tray-icon") == 0) { + return CommandTrayIcon; + } + else if (cmd.compare("mouse-acceleration") == 0) { + return CommandMouseAcceleration; + } + else if (cmd.compare("scroll-acceleration") == 0) { + return CommandScrollAcceleration; + } + else if (cmd.compare("scroll-acceleration-speed") == 0) { + return CommandScrollAccelerationSpeed; + } + + return CommandUnknown; +} /** * run - Run specified Commands. diff --git a/src/ckb/cli.h b/src/ckb/cli.h index 7e1cc69..7b9c5b8 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -4,6 +4,40 @@ /* Include Section */ #include + +class Command : public QObject +{ + Q_OBJECT +public: + enum CommandType { + // Top Level Commands + CommandGlobal, + CommandDevice, + CommandProfile, + + // Sub-commands + CommandHelp, + CommandInfo, + CommandLayout, + CommandModifier, + CommandFramerate, + CommandAnimationDir, + CommandBrightnessPerMode, + CommandSpatialDithering, + CommandFirmwareAutocheck, + CommandTrayIcon, + CommandMouseAcceleration, + CommandScrollAcceleration, + CommandScrollAccelerationSpeed, + + // Generic OK/Fail Flags + CommandOK, + CommandUnknown + }; + static int resolveCommand(QString cmd); +}; + + class CommandLine : public QObject { Q_OBJECT From 16e0d4d477d125a8b3ccafe4e9134005aeed89ad Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Mon, 13 Jun 2016 19:20:57 +0200 Subject: [PATCH 11/33] Start parsing of commands * Read in strings from commandList. * For debugging purposes print, what to do. --- src/ckb/cli.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++------ src/ckb/cli.h | 8 +++++++- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 0f3842b..1345fed 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -58,17 +58,55 @@ int Command::resolveCommand(QString cmd) { return CommandUnknown; } +int CommandLine::runGlobal() { + if (cmdOffset >= commands.length()) return Command::CommandUnknown; + switch (Command::resolveCommand(commands[cmdOffset++].toLocal8Bit().data())) { + case Command::CommandInfo: + std::cout << " Print Global Info" << std::endl; + break; + case Command::CommandLayout: + if (cmdOffset >= commands.length()) return Command::CommandUnknown; + + // further specify the layout command + QString task = commands[cmdOffset++].toLocal8Bit().data(); + if (task.compare("list") == 0) { + std::cout << " Print Global Layouts" << std::endl; + } + else if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return Command::CommandUnknown; + QString layout = commands[cmdOffset++].toLocal8Bit().data(); + std::cout << " Set Global Layout to " << layout.toLocal8Bit().data() << std::endl; + } + else { + return Command::CommandUnknown; + } + break; + } + + return Command::CommandOK; +} + /** * run - Run specified Commands. */ int CommandLine::run() { - // TODO: parse commands and execute requested operation - printf("BaseCommand: %s\n", base.toLocal8Bit().data()); - printf("Flag : %s\n", flag.toLocal8Bit().data()); - printf("Arguments :\n"); + cmdOffset = 0; - for (int i = 0; i < commands.length(); i++) { - printf(" (%03d) %s\n", i, commands[i].toLocal8Bit().data()); + // parse commands and execute requested operation + if (cmdOffset >= commands.length()) return CommandLineUnknown; + switch (Command::resolveCommand(commands[cmdOffset++].toLocal8Bit().data())) { + case Command::CommandGlobal: + std::cout << "Global: " << std::endl; + return runGlobal(); + break; + case Command::CommandDevice: + std::cout << "Device:" << std::endl; + break; + case Command::CommandProfile: + std::cout << "Profile:" << std::endl; + break; + default: + return CommandLineUnknown; } // return with appropriate status diff --git a/src/ckb/cli.h b/src/ckb/cli.h index 7b9c5b8..d5ec587 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -42,6 +42,9 @@ class CommandLine : public QObject { Q_OBJECT private: + int cmdOffset; + + int runGlobal(); int run(); public: QString base; @@ -49,9 +52,12 @@ class CommandLine : public QObject QStringList commands; enum CommandLineResult { - CommandLineOK + CommandLineOK, + CommandLineUnknown }; static int execute(QStringList args); + + friend class Command; }; #endif // CKB_CLI_H From 17c068ea33df8677a8b9e1818318278d296056e9 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Tue, 14 Jun 2016 14:04:31 +0200 Subject: [PATCH 12/33] Tidy cli * Inline `resolveCommand` querries to be more concise. * Let `CommandLine` methods return `CommandLine` status codes. * Remove excessive calls to `.toLocal8Bit().data()`. --- src/ckb/cli.cpp | 81 +++++++++++++++---------------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 1345fed..fa495e1 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -6,61 +6,29 @@ * resolveCommand - Resolve the given String to a Command identifier. */ int Command::resolveCommand(QString cmd) { - if (cmd.compare("global") == 0) { - return CommandGlobal; - } - else if (cmd.compare("device") == 0) { - return CommandDevice; - } - else if (cmd.compare("profile") == 0) { - return CommandProfile; - } - else if (cmd.compare("help") == 0) { - return CommandHelp; - } - else if (cmd.compare("info") == 0) { - return CommandInfo; - } - else if (cmd.compare("layout") == 0) { - return CommandLayout; - } - else if (cmd.compare("modifier") == 0) { - return CommandModifier; - } - else if (cmd.compare("framerate") == 0) { - return CommandFramerate; - } - else if (cmd.compare("animation-dir") == 0) { - return CommandAnimationDir; - } - else if (cmd.compare("brightness-per-mode") == 0) { - return CommandBrightnessPerMode; - } - else if (cmd.compare("spatial-dithering") == 0) { - return CommandSpatialDithering; - } - else if (cmd.compare("firmware-autocheck") == 0) { - return CommandFirmwareAutocheck; - } - else if (cmd.compare("tray-icon") == 0) { - return CommandTrayIcon; - } - else if (cmd.compare("mouse-acceleration") == 0) { - return CommandMouseAcceleration; - } - else if (cmd.compare("scroll-acceleration") == 0) { - return CommandScrollAcceleration; - } - else if (cmd.compare("scroll-acceleration-speed") == 0) { - return CommandScrollAccelerationSpeed; - } + if (cmd.compare("global") == 0) return Command::CommandGlobal; + else if (cmd.compare("device") == 0) return Command::CommandDevice; + else if (cmd.compare("profile") == 0) return Command::CommandProfile; + else if (cmd.compare("help") == 0) return Command::CommandHelp; + else if (cmd.compare("info") == 0) return Command::CommandInfo; + else if (cmd.compare("layout") == 0) return Command::CommandLayout; + else if (cmd.compare("modifier") == 0) return Command::CommandModifier; + else if (cmd.compare("framerate") == 0) return Command::CommandFramerate; + else if (cmd.compare("animation-dir") == 0) return Command::CommandAnimationDir; + else if (cmd.compare("brightness-per-mode") == 0) return Command::CommandBrightnessPerMode; + else if (cmd.compare("spatial-dithering") == 0) return Command::CommandSpatialDithering; + else if (cmd.compare("firmware-autocheck") == 0) return Command::CommandFirmwareAutocheck; + else if (cmd.compare("tray-icon") == 0) return Command::CommandTrayIcon; + else if (cmd.compare("mouse-acceleration") == 0) return Command::CommandMouseAcceleration; + else if (cmd.compare("scroll-acceleration") == 0) return Command::CommandScrollAcceleration; + else if (cmd.compare("scroll-acceleration-speed") == 0) return Command::CommandScrollAccelerationSpeed; - return CommandUnknown; + return Command::CommandUnknown; } int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; - switch (Command::resolveCommand(commands[cmdOffset++].toLocal8Bit().data())) { + switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandInfo: std::cout << " Print Global Info" << std::endl; break; @@ -68,22 +36,22 @@ int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; // further specify the layout command - QString task = commands[cmdOffset++].toLocal8Bit().data(); + QString task = commands[cmdOffset++]; if (task.compare("list") == 0) { std::cout << " Print Global Layouts" << std::endl; } else if (task.compare("set") == 0) { if (cmdOffset >= commands.length()) return Command::CommandUnknown; - QString layout = commands[cmdOffset++].toLocal8Bit().data(); + QString layout = commands[cmdOffset++]; std::cout << " Set Global Layout to " << layout.toLocal8Bit().data() << std::endl; } else { - return Command::CommandUnknown; + return CommandLineUnknown; } break; } - return Command::CommandOK; + return CommandLineOK; } /** @@ -94,11 +62,10 @@ int CommandLine::run() { // parse commands and execute requested operation if (cmdOffset >= commands.length()) return CommandLineUnknown; - switch (Command::resolveCommand(commands[cmdOffset++].toLocal8Bit().data())) { + switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandGlobal: std::cout << "Global: " << std::endl; return runGlobal(); - break; case Command::CommandDevice: std::cout << "Device:" << std::endl; break; @@ -127,7 +94,7 @@ int CommandLine::execute(QStringList args) { int index = 0; QString item; for (constIterator = args.constBegin(); constIterator != args.constEnd(); ++constIterator) { - item = (*constIterator).toLocal8Bit().data(); + item = (*constIterator); if (index == 0) { // first arg is the base cli.base = item; From 4cb36a029ba9809c01497593919c1060f9e168d1 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Tue, 14 Jun 2016 14:08:31 +0200 Subject: [PATCH 13/33] Add routine to resolve Keyboard Layout Resolve layout input to `KeyMap::Layout` specifier. --- src/ckb/cli.cpp | 22 ++++++++++++++++++++-- src/ckb/cli.h | 3 +++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index fa495e1..6b3a43d 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -26,6 +26,24 @@ int Command::resolveCommand(QString cmd) { return Command::CommandUnknown; } +KeyMap::Layout resolveLayout(QString layout) { + if (layout.compare("EU") == 0) return KeyMap::EU; + else if (layout.compare("EU_DVORAK") == 0) return KeyMap::EU_DVORAK; + else if (layout.compare("GB") == 0) return KeyMap::GB; + else if (layout.compare("GB_DVORAK") == 0) return KeyMap::GB_DVORAK; + else if (layout.compare("US") == 0) return KeyMap::US; + else if (layout.compare("US_DVORAK") == 0) return KeyMap::US_DVORAK; + else if (layout.compare("FR") == 0) return KeyMap::FR; + else if (layout.compare("DE") == 0) return KeyMap::DE; + else if (layout.compare("IT") == 0) return KeyMap::IT; + else if (layout.compare("PL") == 0) return KeyMap::PL; + else if (layout.compare("MX") == 0) return KeyMap::MX; + else if (layout.compare("ES") == 0) return KeyMap::ES; + else if (layout.compare("SE") == 0) return KeyMap::SE; + + return KeyMap::NO_LAYOUT; +} + int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { @@ -42,8 +60,8 @@ int CommandLine::runGlobal() { } else if (task.compare("set") == 0) { if (cmdOffset >= commands.length()) return Command::CommandUnknown; - QString layout = commands[cmdOffset++]; - std::cout << " Set Global Layout to " << layout.toLocal8Bit().data() << std::endl; + KeyMap::Layout kl = resolveLayout(commands[cmdOffset++]); + std::cout << " Set Global Layout: " << (int) kl << std::endl; } else { return CommandLineUnknown; diff --git a/src/ckb/cli.h b/src/ckb/cli.h index d5ec587..9156a47 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -3,6 +3,7 @@ /* Include Section */ #include +#include class Command : public QObject @@ -34,7 +35,9 @@ class Command : public QObject CommandOK, CommandUnknown }; + static int resolveCommand(QString cmd); + static KeyMap::Layout resolveLayout(QString layout); }; From 05f906119f9fc14d21abd0ffec002dd7d67e31be Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 16 Jun 2016 09:27:22 +0200 Subject: [PATCH 14/33] Replace pseudo-debugging with qDebug Replace all iostream-operations (`std::cout << ... << std::endl;`) with calls to `qDebug()`. --- src/ckb/cli.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 6b3a43d..b14f452 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,6 +1,6 @@ #include "cli.h" -#include #include +#include /** * resolveCommand - Resolve the given String to a Command identifier. @@ -48,7 +48,7 @@ int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandInfo: - std::cout << " Print Global Info" << std::endl; + qDebug() << " Print Global Info"; break; case Command::CommandLayout: if (cmdOffset >= commands.length()) return Command::CommandUnknown; @@ -56,12 +56,12 @@ int CommandLine::runGlobal() { // further specify the layout command QString task = commands[cmdOffset++]; if (task.compare("list") == 0) { - std::cout << " Print Global Layouts" << std::endl; + qDebug() << " Print Global Layouts"; } else if (task.compare("set") == 0) { if (cmdOffset >= commands.length()) return Command::CommandUnknown; KeyMap::Layout kl = resolveLayout(commands[cmdOffset++]); - std::cout << " Set Global Layout: " << (int) kl << std::endl; + qDebug() << " Set Global Layout: " << (int) kl; } else { return CommandLineUnknown; @@ -82,13 +82,13 @@ int CommandLine::run() { if (cmdOffset >= commands.length()) return CommandLineUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandGlobal: - std::cout << "Global: " << std::endl; + qDebug() << "Global: "; return runGlobal(); case Command::CommandDevice: - std::cout << "Device:" << std::endl; + qDebug() << "Device:"; break; case Command::CommandProfile: - std::cout << "Profile:" << std::endl; + qDebug() << "Profile:"; break; default: return CommandLineUnknown; From a7cb7ff381dc414dcab568ffc9870980baff5f11 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 16 Jun 2016 09:31:24 +0200 Subject: [PATCH 15/33] Resolve Command case-insensitive Coerce command to lower case before comparison to enable case-insensitive cli commands. --- src/ckb/cli.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index b14f452..0693b5e 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -6,22 +6,23 @@ * resolveCommand - Resolve the given String to a Command identifier. */ int Command::resolveCommand(QString cmd) { - if (cmd.compare("global") == 0) return Command::CommandGlobal; - else if (cmd.compare("device") == 0) return Command::CommandDevice; - else if (cmd.compare("profile") == 0) return Command::CommandProfile; - else if (cmd.compare("help") == 0) return Command::CommandHelp; - else if (cmd.compare("info") == 0) return Command::CommandInfo; - else if (cmd.compare("layout") == 0) return Command::CommandLayout; - else if (cmd.compare("modifier") == 0) return Command::CommandModifier; - else if (cmd.compare("framerate") == 0) return Command::CommandFramerate; - else if (cmd.compare("animation-dir") == 0) return Command::CommandAnimationDir; - else if (cmd.compare("brightness-per-mode") == 0) return Command::CommandBrightnessPerMode; - else if (cmd.compare("spatial-dithering") == 0) return Command::CommandSpatialDithering; - else if (cmd.compare("firmware-autocheck") == 0) return Command::CommandFirmwareAutocheck; - else if (cmd.compare("tray-icon") == 0) return Command::CommandTrayIcon; - else if (cmd.compare("mouse-acceleration") == 0) return Command::CommandMouseAcceleration; - else if (cmd.compare("scroll-acceleration") == 0) return Command::CommandScrollAcceleration; - else if (cmd.compare("scroll-acceleration-speed") == 0) return Command::CommandScrollAccelerationSpeed; + QString lowerCmd = cmd.toLower(); + if (lowerCmd.compare("global") == 0) return Command::CommandGlobal; + else if (lowerCmd.compare("device") == 0) return Command::CommandDevice; + else if (lowerCmd.compare("profile") == 0) return Command::CommandProfile; + else if (lowerCmd.compare("help") == 0) return Command::CommandHelp; + else if (lowerCmd.compare("info") == 0) return Command::CommandInfo; + else if (lowerCmd.compare("layout") == 0) return Command::CommandLayout; + else if (lowerCmd.compare("modifier") == 0) return Command::CommandModifier; + else if (lowerCmd.compare("framerate") == 0) return Command::CommandFramerate; + else if (lowerCmd.compare("animation-dir") == 0) return Command::CommandAnimationDir; + else if (lowerCmd.compare("brightness-per-mode") == 0) return Command::CommandBrightnessPerMode; + else if (lowerCmd.compare("spatial-dithering") == 0) return Command::CommandSpatialDithering; + else if (lowerCmd.compare("firmware-autocheck") == 0) return Command::CommandFirmwareAutocheck; + else if (lowerCmd.compare("tray-icon") == 0) return Command::CommandTrayIcon; + else if (lowerCmd.compare("mouse-acceleration") == 0) return Command::CommandMouseAcceleration; + else if (lowerCmd.compare("scroll-acceleration") == 0) return Command::CommandScrollAcceleration; + else if (lowerCmd.compare("scroll-acceleration-speed") == 0) return Command::CommandScrollAccelerationSpeed; return Command::CommandUnknown; } From 665a811943f6693744141e241bde6d53f3411df2 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 16 Jun 2016 09:32:37 +0200 Subject: [PATCH 16/33] Replace custom `resolveLayout` method with KeyMap method Use the already implemented `getLayout` method of the `KeyMap` class to resolve the correct layout. --- src/ckb/cli.cpp | 21 ++------------------- src/ckb/cli.h | 1 - 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 0693b5e..9fdfa66 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,4 +1,5 @@ #include "cli.h" +#include "keymap.h" #include #include @@ -27,24 +28,6 @@ int Command::resolveCommand(QString cmd) { return Command::CommandUnknown; } -KeyMap::Layout resolveLayout(QString layout) { - if (layout.compare("EU") == 0) return KeyMap::EU; - else if (layout.compare("EU_DVORAK") == 0) return KeyMap::EU_DVORAK; - else if (layout.compare("GB") == 0) return KeyMap::GB; - else if (layout.compare("GB_DVORAK") == 0) return KeyMap::GB_DVORAK; - else if (layout.compare("US") == 0) return KeyMap::US; - else if (layout.compare("US_DVORAK") == 0) return KeyMap::US_DVORAK; - else if (layout.compare("FR") == 0) return KeyMap::FR; - else if (layout.compare("DE") == 0) return KeyMap::DE; - else if (layout.compare("IT") == 0) return KeyMap::IT; - else if (layout.compare("PL") == 0) return KeyMap::PL; - else if (layout.compare("MX") == 0) return KeyMap::MX; - else if (layout.compare("ES") == 0) return KeyMap::ES; - else if (layout.compare("SE") == 0) return KeyMap::SE; - - return KeyMap::NO_LAYOUT; -} - int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { @@ -61,7 +44,7 @@ int CommandLine::runGlobal() { } else if (task.compare("set") == 0) { if (cmdOffset >= commands.length()) return Command::CommandUnknown; - KeyMap::Layout kl = resolveLayout(commands[cmdOffset++]); + KeyMap::Layout kl = KeyMap::getLayout(commands[cmdOffset++]); qDebug() << " Set Global Layout: " << (int) kl; } else { diff --git a/src/ckb/cli.h b/src/ckb/cli.h index 9156a47..0952b48 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -37,7 +37,6 @@ class Command : public QObject }; static int resolveCommand(QString cmd); - static KeyMap::Layout resolveLayout(QString layout); }; From 703bed5aa719af5f7cb89471525e7bc9778da6ff Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 16 Jun 2016 10:45:23 +0200 Subject: [PATCH 17/33] Add own QTextStream for printing to stdout Create a static `QTextStream` instance, that can be used similarily to `qDebug()`, etc. and helps printing text to the command line. NOTE: See http://stackoverflow.com/questions/3886105/\ how-to-print-to-console-when-using-qt for a discussion of the general idea. --- src/ckb/cli.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ckb/cli.h b/src/ckb/cli.h index 0952b48..ca1a42c 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -3,6 +3,7 @@ /* Include Section */ #include +#include #include @@ -58,6 +59,8 @@ class CommandLine : public QObject CommandLineUnknown }; static int execute(QStringList args); + /** static stdout stream to print text similar to qDebug() */ + inline QTextStream& qOut() { static QTextStream s{stdout}; return s; } friend class Command; }; From c7ae87d6149a55e6e26fecbb71ed15bb15b8a9f9 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 16 Jun 2016 10:48:21 +0200 Subject: [PATCH 18/33] Implement "global info" command * Add `CommandLine` class as friend to `KbManager` class access `scanDevices()` method. * Add calls to initialize KbManager instance and scan for devices. * Create the deviceLabel similar to the way it's done in the main window. * Build information string and print it to the console. --- src/ckb/cli.cpp | 48 ++++++++++++++++++++++++++++++--------------- src/ckb/kbmanager.h | 2 ++ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 9fdfa66..85d4aa1 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,5 +1,6 @@ #include "cli.h" #include "keymap.h" +#include "kbmanager.h" #include #include @@ -32,24 +33,38 @@ int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandInfo: - qDebug() << " Print Global Info"; - break; - case Command::CommandLayout: - if (cmdOffset >= commands.length()) return Command::CommandUnknown; - - // further specify the layout command - QString task = commands[cmdOffset++]; - if (task.compare("list") == 0) { - qDebug() << " Print Global Layouts"; - } - else if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return Command::CommandUnknown; - KeyMap::Layout kl = KeyMap::getLayout(commands[cmdOffset++]); - qDebug() << " Set Global Layout: " << (int) kl; + // TODO: the next section is almost verbosely taken from `MainWindow::updateVersion()` + // Outsource one of these routines and use it for both frontends. + QString daemonVersion = KbManager::ckbDaemonVersion(); + QString deviceLabel; + if(daemonVersion == DAEMON_UNAVAILABLE_STR){ + deviceLabel = "Driver inactive"; } else { - return CommandLineUnknown; + int count = KbManager::devices().count(); + // Warn if the daemon version doesn't match the GUI + QString daemonWarning; + if(daemonVersion != CKB_VERSION_STR) + daemonWarning = "\n\nWarning: Driver version mismatch (" + daemonVersion + "). Please upgrade ckb" + QString(KbManager::ckbDaemonVersionF() > KbManager::ckbGuiVersionF() ? "" : "-daemon") + ". If the problem persists, try rebooting."; + if(count == 0) + deviceLabel = "No devices connected" + daemonWarning; + else if(count == 1) + deviceLabel = "1 device connected" + daemonWarning; + else + deviceLabel = QString("%1 devices connected").arg(count) + daemonWarning; } + + qOut() + << "ckb " << CKB_VERSION_STR + << endl + << "Open Source Corsair Input Device Driver for Linux and OSX." + << endl << endl + << deviceLabel + << endl << endl + << "See https://github.com/ccMSC/ckb" + << endl + << QString::fromUtf8("©") << " 2014-2016. Licensed under GPLv2." + << endl; break; } @@ -66,7 +81,6 @@ int CommandLine::run() { if (cmdOffset >= commands.length()) return CommandLineUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandGlobal: - qDebug() << "Global: "; return runGlobal(); case Command::CommandDevice: qDebug() << "Device:"; @@ -89,6 +103,8 @@ int CommandLine::run() { * @param args QStringList of arguments to parse. */ int CommandLine::execute(QStringList args) { + KbManager::init(CKB_VERSION_STR); + KbManager::kbManager()->scanKeyboards(); QStringList::const_iterator constIterator; CommandLine cli; diff --git a/src/ckb/kbmanager.h b/src/ckb/kbmanager.h index 9935cf5..4330e86 100644 --- a/src/ckb/kbmanager.h +++ b/src/ckb/kbmanager.h @@ -42,6 +42,8 @@ class KbManager : public QObject // Timer for scanning the driver/device list. May also be useful for periodic GUI events. Created during init(), always runs at 10FPS. static inline QTimer* scanTimer() { return _kbManager ? _kbManager->_scanTimer : 0; } + friend class CommandLine; + signals: // A new device was connected. void kbConnected(Kb* device); From 3d07060431985ded5a928d40ba0a3b4466c07e15 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Thu, 16 Jun 2016 16:40:23 +0200 Subject: [PATCH 19/33] Implement "global layout" command * Encapsulate CommandInfo command in brackets to enable several cases. * List all available layout names + codes, highlighting the currently selected one with "global layout list". * Set new layout with the given layout code, if valid, persistently saving it via `CkbSettings` instance. --- src/ckb/cli.cpp | 121 +++++++++++++++++++++++++++++++++++------------- src/ckb/cli.h | 3 +- 2 files changed, 92 insertions(+), 32 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 85d4aa1..63c9e1b 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,4 +1,5 @@ #include "cli.h" +#include "ckbsettings.h" #include "keymap.h" #include "kbmanager.h" #include @@ -33,39 +34,96 @@ int CommandLine::runGlobal() { if (cmdOffset >= commands.length()) return Command::CommandUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandInfo: - // TODO: the next section is almost verbosely taken from `MainWindow::updateVersion()` - // Outsource one of these routines and use it for both frontends. - QString daemonVersion = KbManager::ckbDaemonVersion(); - QString deviceLabel; - if(daemonVersion == DAEMON_UNAVAILABLE_STR){ - deviceLabel = "Driver inactive"; - } - else { - int count = KbManager::devices().count(); - // Warn if the daemon version doesn't match the GUI - QString daemonWarning; - if(daemonVersion != CKB_VERSION_STR) - daemonWarning = "\n\nWarning: Driver version mismatch (" + daemonVersion + "). Please upgrade ckb" + QString(KbManager::ckbDaemonVersionF() > KbManager::ckbGuiVersionF() ? "" : "-daemon") + ". If the problem persists, try rebooting."; - if(count == 0) - deviceLabel = "No devices connected" + daemonWarning; - else if(count == 1) - deviceLabel = "1 device connected" + daemonWarning; - else - deviceLabel = QString("%1 devices connected").arg(count) + daemonWarning; + { + // TODO: the next section is almost verbosely taken from `MainWindow::updateVersion()` + // Outsource one of these routines and use it for both frontends. + QString daemonVersion = KbManager::ckbDaemonVersion(); + QString deviceLabel; + if(daemonVersion == DAEMON_UNAVAILABLE_STR){ + deviceLabel = "Driver inactive"; + } + else { + int count = KbManager::devices().count(); + // Warn if the daemon version doesn't match the GUI + QString daemonWarning; + if(daemonVersion != CKB_VERSION_STR) + daemonWarning = "\n\nWarning: Driver version mismatch (" + daemonVersion + "). Please upgrade ckb" + QString(KbManager::ckbDaemonVersionF() > KbManager::ckbGuiVersionF() ? "" : "-daemon") + ". If the problem persists, try rebooting."; + if(count == 0) + deviceLabel = "No devices connected" + daemonWarning; + else if(count == 1) + deviceLabel = "1 device connected" + daemonWarning; + else + deviceLabel = QString("%1 devices connected").arg(count) + daemonWarning; + } + + qOut() + << "ckb " << CKB_VERSION_STR + << endl + << "Open Source Corsair Input Device Driver for Linux and OSX." + << endl << endl + << deviceLabel + << endl << endl + << "See https://github.com/ccMSC/ckb" + << endl + << QString::fromUtf8("©") << " 2014-2016. Licensed under GPLv2." + << endl; + break; } + case Command::CommandLayout: + { + if (cmdOffset >= commands.length()) return Command::CommandUnknown; - qOut() - << "ckb " << CKB_VERSION_STR - << endl - << "Open Source Corsair Input Device Driver for Linux and OSX." - << endl << endl - << deviceLabel - << endl << endl - << "See https://github.com/ccMSC/ckb" - << endl - << QString::fromUtf8("©") << " 2014-2016. Licensed under GPLv2." - << endl; - break; + // further specify the layout command + QString task = commands[cmdOffset++]; + if (task.compare("list") == 0) { + // get currently set layout and available layouts + KeyMap::Layout layout = KeyMap::getLayout(settings.value("Program/KbdLayout").toString()); + QStringList layoutNames = KeyMap::layoutNames(); + + // iterate through available layouts + for (int layoutIndex = 0; layoutIndex < layoutNames.count(); layoutIndex++) { + // print out all available keyboard layouts + KeyMap::Layout currentLayout = KeyMap::Layout(layoutIndex); + qOut() + << qSetFieldWidth(0) << left << ((layout == currentLayout) ? "[x]" : "[ ]") << " " + << qSetFieldWidth(9) << left << KeyMap::getLayout(currentLayout).toUpper() << " | " + << qSetFieldWidth(0) << left << layoutNames[layoutIndex] + << endl; + } + } + else if (task.compare("set") == 0) { + // get next argument to set as the new layout + if (cmdOffset >= commands.length()) return Command::CommandUnknown; + KeyMap::Layout kl = KeyMap::getLayout(commands[cmdOffset++]); + + // if layout is invalid, abort + if (kl == KeyMap::NO_LAYOUT) { + qOut() + << "Could not set layout." + << endl; + + return CommandLineUnknown; + } + else { + // persistently save new layout + settings.set("Program/KbdLayout", KeyMap::getLayout(kl)); + Kb::layout(kl); + + // wait until, settings are written completely + settings.cleanUp(); + + qOut() + << "New layout is " << KeyMap::layoutNames()[(int)Kb::layout()] << "." + << endl; + } + } + else { + return CommandLineUnknown; + } + break; + } + default: + return CommandLineUnknown; } return CommandLineOK; @@ -103,6 +161,7 @@ int CommandLine::run() { * @param args QStringList of arguments to parse. */ int CommandLine::execute(QStringList args) { + CkbSettings settings("Program"); KbManager::init(CKB_VERSION_STR); KbManager::kbManager()->scanKeyboards(); QStringList::const_iterator constIterator; diff --git a/src/ckb/cli.h b/src/ckb/cli.h index ca1a42c..5781068 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -4,7 +4,7 @@ /* Include Section */ #include #include -#include +#include "ckbsettings.h" class Command : public QObject @@ -45,6 +45,7 @@ class CommandLine : public QObject { Q_OBJECT private: + CkbSettings settings; int cmdOffset; int runGlobal(); From 919acfc0b914b0c8f3898efba9b4672f79a9f27f Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 14:41:11 +0200 Subject: [PATCH 20/33] Small enhancements to cli.cpp * Make `Command::runGlobal()` return `CommandLineUnknown`, instead of `Command::CommandUnknown`. * Coerce layout's task command to lower case, to enable case insensitive invocation. * Fix comment's grammar. --- src/ckb/cli.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 63c9e1b..10e4d5a 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -31,7 +31,7 @@ int Command::resolveCommand(QString cmd) { } int CommandLine::runGlobal() { - if (cmdOffset >= commands.length()) return Command::CommandUnknown; + if (cmdOffset >= commands.length()) return CommandLineUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandInfo: { @@ -71,10 +71,10 @@ int CommandLine::runGlobal() { } case Command::CommandLayout: { - if (cmdOffset >= commands.length()) return Command::CommandUnknown; + if (cmdOffset >= commands.length()) return CommandLineUnknown; // further specify the layout command - QString task = commands[cmdOffset++]; + QString task = commands[cmdOffset++].toLower(); if (task.compare("list") == 0) { // get currently set layout and available layouts KeyMap::Layout layout = KeyMap::getLayout(settings.value("Program/KbdLayout").toString()); @@ -93,7 +93,7 @@ int CommandLine::runGlobal() { } else if (task.compare("set") == 0) { // get next argument to set as the new layout - if (cmdOffset >= commands.length()) return Command::CommandUnknown; + if (cmdOffset >= commands.length()) return CommandLineUnknown; KeyMap::Layout kl = KeyMap::getLayout(commands[cmdOffset++]); // if layout is invalid, abort @@ -109,7 +109,7 @@ int CommandLine::runGlobal() { settings.set("Program/KbdLayout", KeyMap::getLayout(kl)); Kb::layout(kl); - // wait until, settings are written completely + // wait until settings are written completely settings.cleanUp(); qOut() From 20b476fb2be7aceba57156ab09369ebdad9c63be Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 14:44:12 +0200 Subject: [PATCH 21/33] Implement "global modifier" command Use `KbBind` class to read and set the global key bindings. Allow setting of OS X specific keys, by handling appropriate edge cases. --- src/ckb/cli.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 10e4d5a..2d11c4f 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -2,6 +2,7 @@ #include "ckbsettings.h" #include "keymap.h" #include "kbmanager.h" +#include "kbbind.h" #include #include @@ -120,6 +121,138 @@ int CommandLine::runGlobal() { else { return CommandLineUnknown; } + break; + } + case Command::CommandModifier: + { + // load the global remaps from the ckbsettings + KbBind::loadGlobalRemap(); + + // set the modifier keys and names to display + QStringList modKeys, modNames; + modKeys << "caps" << "lshift" << "lctrl" << "lalt" << "lwin"; +#ifdef Q_OS_MACX + modNames << "Caps Lock" << "Shift" << "Control (⌃)" << "Option (⌥)" << "Command (⌘)"; +#else + modNames << "Caps Lock" << "Shift" << "Control" << "Alt" << "Super"; +#endif + + if (cmdOffset >= commands.length()) return CommandLineUnknown; + QString task = commands[cmdOffset++].toLower(); + if (task.compare("list") == 0) { + // print each modifier and it's rebind + qOut() + << "These will override the keyboard profile. See \"Binding\" tab for more settings." + << endl; + + foreach (QString mod, modKeys) { + qOut() + << qSetFieldWidth(11) << left << modNames[modKeys.indexOf(mod)] + << qSetFieldWidth(2) << left << ": " + << qSetFieldWidth(0) << left << modNames[modKeys.indexOf(KbBind::globalRemap(mod))] + << endl; + } + } + else if (task.compare("set") == 0) { + // abort if arguments don't contain key and remap + if (cmdOffset+1 >= commands.length()) return CommandLineUnknown; + + // get key and remap from arguments + QString key = commands[cmdOffset++].toLower(); + QString mod = commands[cmdOffset++].toLower(); + QString lmod, rmod; + + // strip leading 'r' or 'l' + mod = mod[0] == QChar('l') || mod[0] == QChar('r') ? mod.mid(1) : mod; + + // abort if remap not in list + if ((QStringList() << "caps" << "shift" << "ctrl" << "alt" << "option" << "win" << "cmd").indexOf(mod) == -1) + return CommandLineUnknown; + + // initialize newMods + QHash newMods; + newMods["caps"] = KbBind::globalRemap("caps"); + newMods["lshift"] = KbBind::globalRemap("lshift"); + newMods["rshift"] = KbBind::globalRemap("rshift"); + newMods["lctrl"] = KbBind::globalRemap("lctrl"); + newMods["rctrl"] = KbBind::globalRemap("rctrl"); + newMods["lalt"] = KbBind::globalRemap("lalt"); + newMods["ralt"] = KbBind::globalRemap("ralt"); + newMods["lwin"] = KbBind::globalRemap("lwin"); + newMods["rwin"] = KbBind::globalRemap("rwin"); + + // coerce remaps to understandable format + if (mod == "caps") { + lmod = rmod = mod; + } + else if (mod == "option") { + lmod = "lalt"; + rmod = "ralt"; + } + else if (mod == "cmd") { + lmod = "lwin"; + rmod = "rwin"; + } + else { + lmod = 'l' + mod; + rmod = 'r' + mod; + } + + // remap requested key to new mod + if (key.compare("caps") == 0) { + newMods["caps"] = lmod; + } + else if (key.compare("shift") == 0) { + newMods["lshift"] = lmod; + newMods["rshift"] = rmod; + } + else if (key.compare("ctrl") == 0) { + newMods["lctrl"] = lmod; + newMods["rctrl"] = rmod; + } + else if (key.compare("alt") == 0 || key.compare("option") == 0) { + newMods["lalt"] = lmod; + newMods["ralt"] = rmod; + } + else if (key.compare("win") == 0 || key.compare("cmd") == 0) { + newMods["lwin"] = lmod; + newMods["rwin"] = rmod; + } + else { + return CommandLineUnknown; + } + + // persistently store new remaps + KbBind::setGlobalRemap(newMods); + KbBind::saveGlobalRemap(); + + // wait until settings are written completely + settings.cleanUp(); + } + else if (task.compare("reset") == 0) { + // initialize newMods + QHash newMods; + newMods["caps"] = "caps"; + newMods["lshift"] = "lshift"; + newMods["rshift"] = "rshift"; + newMods["lctrl"] = "lctrl"; + newMods["rctrl"] = "rctrl"; + newMods["lalt"] = "lalt"; + newMods["ralt"] = "ralt"; + newMods["lwin"] = "lwin"; + newMods["rwin"] = "rwin"; + + // persistently store new remaps + KbBind::setGlobalRemap(newMods); + KbBind::saveGlobalRemap(); + + // wait until settings are written completely + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; } default: From 07c24d54b03627ef7c9953bf8624aa018726c5d1 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 18:41:20 +0200 Subject: [PATCH 22/33] Implement "global framerate" command Show frame rate from `CkbSettings` class, set it using `Kb` and store it via `CkbSettings` as well, showing all appropriate warnings. --- src/ckb/cli.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 2d11c4f..ea50153 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -253,6 +253,52 @@ int CommandLine::runGlobal() { return CommandLineUnknown; } + break; + } + case Command::CommandFramerate: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + if (task.compare("show") == 0) { + // display current framerate + qOut() + << "Current framerate: " + << settings.value("Program/framerate").toString() + << endl; + } + else if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + // get given framerate + bool ok; + QString frameRate = commands[cmdOffset++].toLower(); + int frameRateValue = frameRate.toInt(&ok); + + // check, whether it's a number between 0 and 60 + if (!ok || frameRateValue <= 0 || frameRateValue >= 60) { + qOut() + << "Framerate must be a number between 0 and 60." + << endl; + return CommandLineUnknown; + } + + // persistently store framerate and set it for current session + Kb::frameRate(frameRateValue); + settings.set("Program/framerate", frameRateValue); + + // print warning, if value above 30 + if (frameRateValue > 30) + qOut() + << "Warning: high frame rates may cause stability issues." + << endl; + + // wait until settings are written completely + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } break; } default: From 09ea76eaef79ba812f25f882dfb1ccfde1d88f08 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 19:08:31 +0200 Subject: [PATCH 23/33] Implement "global animation-dir" command Scan and display information about the animations directory/directories. --- src/ckb/cli.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index ea50153..4d6717d 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -1,4 +1,5 @@ #include "cli.h" +#include "animscript.h" #include "ckbsettings.h" #include "keymap.h" #include "kbmanager.h" @@ -301,6 +302,39 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandAnimationDir: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + // whether it's "show" or "scan", both do the same + QString task = commands[cmdOffset++].toLower(); + if (task.compare("show") == 0 || task.compare("scan") == 0) { + // scan and load the animations from the animation-dir + AnimScript::scan(); + + // display information about the results + qOut() + << "Location: " + << AnimScript::path() + << " "; + switch (AnimScript::count()) { + case 0: + qOut() << "No animations found."; + break; + case 1: + qOut() << "1 animation found."; + break; + default: + qOut() << QString("%1 animations found").arg(AnimScript::count()); + break; + } + qOut() << endl; + } + else { + return CommandLineUnknown; + } + break; + } default: return CommandLineUnknown; } From e7b9ed09b33470e3b795d7c69eb57f0e520efea2 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 20:17:31 +0200 Subject: [PATCH 24/33] Implement "global brightness-per-mode" command Use `KbLight` and `CkbSettings` class to display information about shared dimming and persistently set it's status. --- src/ckb/cli.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 4d6717d..ae4f5b5 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -4,6 +4,7 @@ #include "keymap.h" #include "kbmanager.h" #include "kbbind.h" +#include "kblight.h" #include #include @@ -335,6 +336,58 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandBrightnessPerMode: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // get current dimming from settings + int dimming = settings.value("Program/GlobalBrightness").toInt(); + if (dimming < -1 || dimming > KbLight::MAX_DIM) { + // normalize dimming, if value is malformed + dimming = 0; + } + + // display information about brightness per mode + qOut() + << "Brightness per mode: " + << (dimming == -1 ? "Enabled" : "Disabled") << "." + << endl + << "(By default, the same brightness level will be applied to all profiles and all devices. Enable this to store it with the lighting mode instead.)" + << endl; + } + else if (task.compare("enable") == 0) { + // enable brightness per mode -> disable shared dimming + settings.set("Program/GlobalBrightness", -1); + KbLight::shareDimming(-1); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // disable brightness per mode -> enable shared dimming + settings.set("Program/GlobalBrightness", 0); + KbLight::shareDimming(0); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } default: return CommandLineUnknown; } From 6794d191a359096f838fd46f2aa33b2e406860de Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 20:17:38 +0200 Subject: [PATCH 25/33] Implement "global spatial-dithering" command Use `Kb` and `CkbSettings` class to display information about spatial dithering and persistently set it's status. --- src/ckb/cli.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index ae4f5b5..870e968 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -388,6 +388,51 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandSpatialDithering: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + if (cmdOffset >= commands.length()) return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // display information about spatial dithering + qOut() + << "Use spatial dithering to simulate extra color resolution: " + << (settings.value("Program/Dither").toBool() ? "Enabled" : "Disabled") << "." + << endl + << "(May improve appearance on some keyboards)." + << endl; + } + else if (task.compare("enable") == 0) { + // enable spatial dithering + settings.set("Program/Dither", true); + Kb::dither(true); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // disable spatial dithering + settings.set("Program/Dither", false); + Kb::dither(false); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } default: return CommandLineUnknown; } From b2e7822dd40e30d4aa9b031804b47afe84b6eb83 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 20:26:06 +0200 Subject: [PATCH 26/33] Implement "globale firmware-autocheck" command Use `CkbSettings` class to display information about the status of the autocheck feature of the firmware and persistently set it's status. --- src/ckb/cli.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 870e968..90eb310 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -413,7 +413,7 @@ int CommandLine::runGlobal() { << "Use spatial dithering to simulate extra color resolution: " << (settings.value("Program/Dither").toBool() ? "Enabled" : "Disabled") << "." << endl - << "(May improve appearance on some keyboards)." + << "(May improve appearance on some keyboards.)" << endl; } else if (task.compare("enable") == 0) { @@ -433,6 +433,49 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandFirmwareAutocheck: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + if (cmdOffset >= commands.length()) return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // display information about firmware auto check + qOut() + << "Check for new firmware automatically: " + << (settings.value("Program/DisableAutoFWCheck").toBool() ? "Disabled" : "Enabled") << "." + << endl + << "(You will be notified when new firmware versions are available. You'll have the option to install them immediately or wait until later.)" + << endl; + } + else if (task.compare("enable") == 0) { + // enable firmware autocheck + settings.set("Program/DisableAutoFWCheck", false); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // disable firmware autocheck + settings.set("Program/DisableAutoFWCheck", true); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } default: return CommandLineUnknown; } From 806e3ed8ed06e431b8349a4a259da1fd8c92a949 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 20:41:51 +0200 Subject: [PATCH 27/33] Implement "global tray-icon" command Use `CkbSettings` class to display information about tray icon and persistently set it's status. --- src/ckb/cli.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 90eb310..4f0510a 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -476,6 +476,49 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandTrayIcon: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + if (cmdOffset >= commands.length()) return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // display information about the tray icon + qOut() + << "Show tray icon: " + << (settings.value("Program/SuppressTrayIcon").toBool() ? "Disabled" : "Enabled") << "." + << endl + << "(The tray icon will not be displayed, if disabled. The application will still run in the background; re-launch the app to see the GUI again.)" + << endl; + } + else if (task.compare("enable") == 0) { + // suppress tray icon + settings.set("Program/SuppressTrayIcon", false); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // allow tray icon + settings.set("Program/SuppressTrayIcon", true); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } default: return CommandLineUnknown; } From 460fefaaa827f6c665b88ba8a042108b46b66b73 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 20:56:02 +0200 Subject: [PATCH 28/33] Implement "global mouse-acceleration" command Use `Kb` and `CkbSettings` class to display information about mouse acceleration and persistently set it's status. --- src/ckb/cli.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 4f0510a..30cadac 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -519,6 +519,53 @@ int CommandLine::runGlobal() { } break; } +#ifdef Q_OS_MACX + case Command::CommandMouseAcceleration: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + if (cmdOffset >= commands.length()) return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // display information about mouse acceleration + qOut() + << "Mouse acceleration: " + << (settings.value("Program/DisableMouseAccel").toBool() ? "Disabled" : "Enabled") << "." + << endl + << "(Try this if you're having problems with mouse movement.)" + << endl; + } + else if (task.compare("enable") == 0) { + // suppress mouse acceleration + settings.set("Program/DisableMouseAccel", false); + Kb::mouseAccel(true); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // allow mouse acceleration + settings.set("Program/DisableMouseAccel", true); + Kb::mouseAccel(false); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } +#endif default: return CommandLineUnknown; } From 7d1ad56cd7f071d6968694b8ed7b526d6ef18009 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 21:21:49 +0200 Subject: [PATCH 29/33] Implement "global scroll-acceleration" command Use `Kb` and `CkbSettings` class to display information about scroll acceleration and persistently set it's status. --- src/ckb/cli.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 30cadac..dc3abe0 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -565,6 +565,51 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandScrollAcceleration: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + if (cmdOffset >= commands.length()) return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // display information about scroll acceleration + qOut() + << "Scroll acceleration: " + << (settings.value("Program/DisableScrollAccel").toBool() ? "Disabled" : "Enabled") << "." + << endl + << "(Try this if you're having problems with the scroll wheel.)" + << endl; + } + else if (task.compare("enable") == 0) { + // suppress scroll acceleration + settings.set("Program/DisableScrollAccel", false); + Kb::scrollSpeed(settings.value("Program/ScrollSpeed", 3).toInt()); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // allow scroll acceleration + settings.set("Program/DisableScrollAccel", true); + Kb::scrollSpeed(0); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } #endif default: return CommandLineUnknown; From dc6db13c7b1579c2b766a84d8fd952c5b66e8df9 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 21:22:46 +0200 Subject: [PATCH 30/33] Implement "global scroll-acceleration-speed" command Use `Kb` and `CkbSettings` class to display information about scroll acceleration speed and persistently set it's status. --- src/ckb/cli.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index dc3abe0..0d9bccd 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -610,6 +610,51 @@ int CommandLine::runGlobal() { } break; } + case Command::CommandScrollAccelerationSpeed: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + bool scrollDisabled = settings.value("Program/DisableScrollAccel"); + + if (task.compare("show") == 0) { + // display information about scroll acceleration speed + qOut() + << "Scroll acceleration value: " + << settings.value("Program/ScrollSpeed").toInt() << "." + << endl; + if (scrollDisabled) { + qOut() + << "Attention: Scroll Acceleration is disabled. It must be enabled for the Scroll Acceleration to be set to a specific value." + << endl; + break; + } + else if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + // get given scroll speed + bool ok; + QString scrollSpeed = commands[cmdOffset++].toLower(); + int scrollSpeedValue = scrollSpeed.toInt(&ok); + + // check, whether it's a number between 0 and 10 + if (!ok || scrollSpeedValue < 1 || scrollSpeedValue > 10) { + qOut() + << "Scroll speed must be a number between 1 and 10." + << endl; + return CommandLineUnknown; + } + + // set scroll acceleration speed (if enabled) + settings.set("Program/ScrollSpeed", scrollSpeedValue); + Kb::scrollSpeed(scrollDisabled ? 0 : scrollSpeedValue); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + break; + } #endif default: return CommandLineUnknown; From 08ac97924e44df44c241eab97565c707933c7782 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Fri, 17 Jun 2016 21:49:05 +0200 Subject: [PATCH 31/33] Implement "global long-macro-delay" command Add specification and parser for this command. Use `Kb` and `CkbSettings` class to display information about the long macro delay and persistently set it's status. --- cli-specs.md | 1 + src/ckb/cli.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/ckb/cli.h | 1 + 3 files changed, 49 insertions(+) diff --git a/cli-specs.md b/cli-specs.md index 59ee7ab..d4a6c13 100644 --- a/cli-specs.md +++ b/cli-specs.md @@ -163,6 +163,7 @@ Generally the command line interface needs a different approach, than the GUI. F | "mouse-acceleration" | "scroll-acceleration" | "scroll-acceleration-speed" + | "long-macro-delay" ::= "show" | "set" ::= "show" | "set" diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index 0d9bccd..cd830a8 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -29,6 +29,7 @@ int Command::resolveCommand(QString cmd) { else if (lowerCmd.compare("mouse-acceleration") == 0) return Command::CommandMouseAcceleration; else if (lowerCmd.compare("scroll-acceleration") == 0) return Command::CommandScrollAcceleration; else if (lowerCmd.compare("scroll-acceleration-speed") == 0) return Command::CommandScrollAccelerationSpeed; + else if (lowerCmd.compare("long-macro-delay") == 0) return Command::CommandLongMacroDelay; return Command::CommandUnknown; } @@ -656,6 +657,52 @@ int CommandLine::runGlobal() { break; } #endif + case Command::CommandLongMacroDelay: + { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + QString task = commands[cmdOffset++].toLower(); + + // coerce "set" to "disable"/"enable" if possible + if (task.compare("set") == 0) { + if (cmdOffset >= commands.length()) return CommandLineUnknown; + + task = commands[cmdOffset].toLower(); + if (task.compare("on") == 0 || task.compare("1") == 0) + task = "enable"; + else if (task.compare("off") == 0 || task.compare("0") == 0) + task = "disable"; + else + if (cmdOffset >= commands.length()) return CommandLineUnknown; + } + + if (task.compare("show") == 0) { + // display information about the long macro delay + qOut() + << "Use delay for very long macros: " + << (settings.value("Program/MacroDelay").toBool() ? "Enabled" : "Disabled") << "." + << endl + << "(When using macros with strings longer than 25 chars, some OS may lose characters (e.g. Mint 17.2). Select to prevent that bug.)" + << endl; + } + else if (task.compare("enable") == 0) { + // enable long macro delay + settings.set("Program/MacroDelay", true); + Kb::macroDelay(true); + settings.cleanUp(); + } + else if (task.compare("disable") == 0) { + // disable long macro delay + settings.set("Program/MacroDelay", false); + Kb::macroDelay(false); + settings.cleanUp(); + } + else { + return CommandLineUnknown; + } + + break; + } default: return CommandLineUnknown; } diff --git a/src/ckb/cli.h b/src/ckb/cli.h index 5781068..79082c3 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -31,6 +31,7 @@ class Command : public QObject CommandMouseAcceleration, CommandScrollAcceleration, CommandScrollAccelerationSpeed, + CommandLongMacroDelay, // Generic OK/Fail Flags CommandOK, From 7c9a09fd6bc16e7786bf4a746311466e57fd3881 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Tue, 28 Jun 2016 21:28:01 +0200 Subject: [PATCH 32/33] Update CLI syntax specification Remove the specification of empty device/profile commands, as they were not updated after the discussion in issue #213 foreshadowed a major update in the profile commands. * Remove `ckb --cmd device`. * Remove `ckb --cmd profile`. --- cli-specs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli-specs.md b/cli-specs.md index d4a6c13..709dcb4 100644 --- a/cli-specs.md +++ b/cli-specs.md @@ -187,7 +187,7 @@ Generally the command line interface needs a different approach, than the GUI. F ### Device Commands ``` - ::= "" | "info" + ::= "info" | "show profile" | "set profile" | "firmware" @@ -199,7 +199,7 @@ Generally the command line interface needs a different approach, than the GUI. F ### Profile Commands ``` - ::= "" | "list" + ::= "list" | "create" | "duplicate" | "rename" From 151bbda71b597fb68a795b6bd896698f995793fa Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Mon, 5 Sep 2016 10:09:15 +0200 Subject: [PATCH 33/33] Implement "global help" command Add value to identify invalid commands. Print the syntax for the `global` command on these cases. Only show the default help, if the command is unknown. --- src/ckb/cli.cpp | 123 ++++++++++++++++++++++++++++------------------- src/ckb/cli.h | 1 + src/ckb/main.cpp | 3 +- 3 files changed, 77 insertions(+), 50 deletions(-) diff --git a/src/ckb/cli.cpp b/src/ckb/cli.cpp index cd830a8..1d9629f 100644 --- a/src/ckb/cli.cpp +++ b/src/ckb/cli.cpp @@ -35,7 +35,7 @@ int Command::resolveCommand(QString cmd) { } int CommandLine::runGlobal() { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandInfo: { @@ -75,7 +75,7 @@ int CommandLine::runGlobal() { } case Command::CommandLayout: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; // further specify the layout command QString task = commands[cmdOffset++].toLower(); @@ -97,7 +97,7 @@ int CommandLine::runGlobal() { } else if (task.compare("set") == 0) { // get next argument to set as the new layout - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; KeyMap::Layout kl = KeyMap::getLayout(commands[cmdOffset++]); // if layout is invalid, abort @@ -106,7 +106,7 @@ int CommandLine::runGlobal() { << "Could not set layout." << endl; - return CommandLineUnknown; + return CommandLineInvalid; } else { // persistently save new layout @@ -122,7 +122,7 @@ int CommandLine::runGlobal() { } } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } @@ -140,7 +140,7 @@ int CommandLine::runGlobal() { modNames << "Caps Lock" << "Shift" << "Control" << "Alt" << "Super"; #endif - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); if (task.compare("list") == 0) { // print each modifier and it's rebind @@ -158,7 +158,7 @@ int CommandLine::runGlobal() { } else if (task.compare("set") == 0) { // abort if arguments don't contain key and remap - if (cmdOffset+1 >= commands.length()) return CommandLineUnknown; + if (cmdOffset+1 >= commands.length()) return CommandLineInvalid; // get key and remap from arguments QString key = commands[cmdOffset++].toLower(); @@ -170,7 +170,7 @@ int CommandLine::runGlobal() { // abort if remap not in list if ((QStringList() << "caps" << "shift" << "ctrl" << "alt" << "option" << "win" << "cmd").indexOf(mod) == -1) - return CommandLineUnknown; + return CommandLineInvalid; // initialize newMods QHash newMods; @@ -222,7 +222,7 @@ int CommandLine::runGlobal() { newMods["rwin"] = rmod; } else { - return CommandLineUnknown; + return CommandLineInvalid; } // persistently store new remaps @@ -253,14 +253,14 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandFramerate: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); if (task.compare("show") == 0) { @@ -271,7 +271,7 @@ int CommandLine::runGlobal() { << endl; } else if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; // get given framerate bool ok; @@ -283,7 +283,7 @@ int CommandLine::runGlobal() { qOut() << "Framerate must be a number between 0 and 60." << endl; - return CommandLineUnknown; + return CommandLineInvalid; } // persistently store framerate and set it for current session @@ -300,13 +300,13 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandAnimationDir: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; // whether it's "show" or "scan", both do the same QString task = commands[cmdOffset++].toLower(); @@ -333,19 +333,19 @@ int CommandLine::runGlobal() { qOut() << endl; } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandBrightnessPerMode: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -353,7 +353,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - return CommandLineUnknown; + return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -385,19 +385,19 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandSpatialDithering: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -405,7 +405,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -430,19 +430,19 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandFirmwareAutocheck: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -450,7 +450,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -473,19 +473,19 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandTrayIcon: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -493,7 +493,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -516,20 +516,20 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } #ifdef Q_OS_MACX case Command::CommandMouseAcceleration: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -537,7 +537,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -562,19 +562,19 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandScrollAcceleration: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -582,7 +582,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -607,13 +607,13 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } case Command::CommandScrollAccelerationSpeed: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); bool scrollDisabled = settings.value("Program/DisableScrollAccel"); @@ -631,7 +631,7 @@ int CommandLine::runGlobal() { break; } else if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; // get given scroll speed bool ok; @@ -643,7 +643,7 @@ int CommandLine::runGlobal() { qOut() << "Scroll speed must be a number between 1 and 10." << endl; - return CommandLineUnknown; + return CommandLineInvalid; } // set scroll acceleration speed (if enabled) @@ -652,20 +652,20 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } #endif case Command::CommandLongMacroDelay: { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; QString task = commands[cmdOffset++].toLower(); // coerce "set" to "disable"/"enable" if possible if (task.compare("set") == 0) { - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; task = commands[cmdOffset].toLower(); if (task.compare("on") == 0 || task.compare("1") == 0) @@ -673,7 +673,7 @@ int CommandLine::runGlobal() { else if (task.compare("off") == 0 || task.compare("0") == 0) task = "disable"; else - if (cmdOffset >= commands.length()) return CommandLineUnknown; + if (cmdOffset >= commands.length()) return CommandLineInvalid; } if (task.compare("show") == 0) { @@ -698,11 +698,13 @@ int CommandLine::runGlobal() { settings.cleanUp(); } else { - return CommandLineUnknown; + return CommandLineInvalid; } break; } + case Command::CommandHelp: + return CommandLineInvalid; default: return CommandLineUnknown; } @@ -720,7 +722,30 @@ int CommandLine::run() { if (cmdOffset >= commands.length()) return CommandLineUnknown; switch (Command::resolveCommand(commands[cmdOffset++])) { case Command::CommandGlobal: - return runGlobal(); + { + int global = runGlobal(); + if (global == CommandLineInvalid) { + qOut() + << "Syntax: global CMD" << endl + << "Where: CMD = info" << endl + << " | layout { list | set LAYOUT }" << endl + << " | modifier { list | set KEY MOD | reset }" << endl + << " | framerate { show | set VALUE }" << endl + << " | animation-dir { show | scan }" << endl + << " | brightness-per-mode { show | set VALUE }" << endl + << " | spatial-dithering { show | set VALUE }" << endl + << " | firmware-autocheck { show | set VALUE }" << endl + << " | tray-icon { show | set VALUE }" << endl + << " | mouse-acceleration { show | set VALUE }" << endl + << " | scroll-acceleration { show | set VALUE }" << endl + << " | scroll-acceleration-speed { show set VALUE }" << endl + << " | long-macro-delay { show | set VALUE }" << endl << endl; + + global = CommandLineOK; + } + + return global; + } case Command::CommandDevice: qDebug() << "Device:"; break; diff --git a/src/ckb/cli.h b/src/ckb/cli.h index 79082c3..1233305 100644 --- a/src/ckb/cli.h +++ b/src/ckb/cli.h @@ -58,6 +58,7 @@ class CommandLine : public QObject enum CommandLineResult { CommandLineOK, + CommandLineInvalid, CommandLineUnknown }; static int execute(QStringList args); diff --git a/src/ckb/main.cpp b/src/ckb/main.cpp index 57a767e..5ca860c 100644 --- a/src/ckb/main.cpp +++ b/src/ckb/main.cpp @@ -219,7 +219,8 @@ int main(int argc, char *argv[]){ static int cli_error = CommandLine::execute(QCoreApplication::arguments()); if (cli_error) { // display help text and errors, if command couldn't be executed - parser.showHelp(); + if (cli_error == CommandLine::CommandLineUnknown) + parser.showHelp(); return cli_error; } // Also run ckb in background on execute command