diff --git a/CMakeLists.txt b/CMakeLists.txt index dd8e095..543597b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,9 +22,15 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) + set(LINUX_UDEV_RULE_WRITER_NAME "udev-rule-writer.sh") +set(MACOSX_BUNDLE_COPYRIGHT "Debayan Sutradhar") +set(MACOSX_BUNDLE_GUI_IDENTIFIER io.github.rnayabed.rangoli) + add_compile_definitions( + DISABLE_QDEBUG=false + VERSION=${VERSION} GIT_REPOSITORY="https://github.com/rnayabed/rangoli" SUPPORTED_KEYBOARDS="https://github.com/rnayabed/rangoli/blob/master/supported-keyboards.md" @@ -36,10 +42,14 @@ add_compile_definitions( AUTHOR_UPI="9903299105@upi" AUTHOR_EMAIL="debayansutradhar3@gmail.com" GITHUB_RELEASES="https://api.github.com/repos/rnayabed/rangoli/releases" + LINUX_UDEV_RULE_WRITER_NAME="${LINUX_UDEV_RULE_WRITER_NAME}" LINUX_UDEV_RULES_PATH="/etc/udev/rules.d/71-rangoli.rules" LINUX_TERMINAL="xterm" + MACOSX_BUNDLE_COPYRIGHT="${MACOSX_BUNDLE_COPYRIGHT}" + MACOSX_BUNDLE_GUI_IDENTIFIER="${MACOSX_BUNDLE_GUI_IDENTIFIER}" + DEFAULT_ACCENT_RED=229 DEFAULT_ACCENT_GREEN=21 DEFAULT_ACCENT_BLUE=115 diff --git a/README.md b/README.md index bd737c2..a593e9f 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,11 @@ Therefore, instead of changing the keyboard firmware, this software pretends to - Per key LED Brightness, Animation and Sleep ## Planned features -- Macros - Music Mode - Custom RGB Patterns ## Features that will not be worked on +- Macros. This is something that can be done directly on OS level. There are tools like [AutoHotkey](https://www.autohotkey.com/) and [AutoKey](https://github.com/autokey/autokey) that does this far better than RK Software itself. - Keyboard Firmware update. I was not able to reverse engineer this aspect of the RK Software because the function itself is broken. ## Supported Keyboards diff --git a/keyboards/5ac/configs/24f.json b/keyboards/5ac/configs/24f.json deleted file mode 100644 index 166ea95..0000000 --- a/keyboards/5ac/configs/24f.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "name":"RK71 3 mode", - "rgb":true, - "top":[12, 43], - "bottom":[707, 247], - "keys":[ - { "bIndex":1, "keyCode":"Key_Escape", "top":[12, 44], "bottom":[39, 75] }, - { "bIndex":85, "keyCode":"Key_Insert", "top":[638, 45], "bottom":[665, 76] }, - { "bIndex":87, "keyCode":"Key_Pause", "top":[638, 130], "bottom":[665, 161] }, - { "bIndex":86, "keyCode":"Key_Delete", "top":[638, 87], "bottom":[665, 118] }, - { "bIndex":7, "keyCode":"Key_1", "top":[54, 44], "bottom":[81, 75] }, - { "bIndex":13, "keyCode":"Key_2", "top":[96, 44], "bottom":[123, 75] }, - { "bIndex":19, "keyCode":"Key_3", "top":[138, 44], "bottom":[165, 75] }, - { "bIndex":25, "keyCode":"Key_4", "top":[179, 44], "bottom":[206, 75] }, - { "bIndex":31, "keyCode":"Key_5", "top":[221, 44], "bottom":[248, 75] }, - { "bIndex":37, "keyCode":"Key_6", "top":[262, 44], "bottom":[289, 75] }, - { "bIndex":43, "keyCode":"Key_7", "top":[305, 44], "bottom":[332, 75] }, - { "bIndex":49, "keyCode":"Key_8", "top":[346, 44], "bottom":[373, 75] }, - { "bIndex":55, "keyCode":"Key_9", "top":[388, 44], "bottom":[415, 75] }, - { "bIndex":61, "keyCode":"Key_0", "top":[430, 44], "bottom":[457, 75] }, - { "bIndex":67, "keyCode":"Key_Hyphen", "top":[471, 44], "bottom":[498, 75] }, - { "bIndex":73, "keyCode":"Key_Equals", "top":[513, 44], "bottom":[540, 75] }, - { "bIndex":79, "keyCode":"Key_Backspace", "top":[556, 43], "bottom":[622, 74] }, - { "bIndex":92, "keyCode":"Key_End", "top":[679, 87], "bottom":[706, 118] }, - { "bIndex":91, "keyCode":"Key_Home", "top":[680, 44], "bottom":[707, 75] }, - { "bIndex":2, "keyCode":"Key_Tab", "top":[13, 87], "bottom":[60, 118] }, - { "bIndex":8, "keyCode":"Key_Q", "top":[75, 87], "bottom":[102, 118] }, - { "bIndex":14, "keyCode":"Key_W", "top":[117, 87], "bottom":[144, 118] }, - { "bIndex":20, "keyCode":"Key_E", "top":[158, 87], "bottom":[185, 118] }, - { "bIndex":26, "keyCode":"Key_R", "top":[200, 87], "bottom":[227, 118] }, - { "bIndex":32, "keyCode":"Key_T", "top":[242, 87], "bottom":[269, 118] }, - { "bIndex":38, "keyCode":"Key_Y", "top":[284, 87], "bottom":[311, 118] }, - { "bIndex":44, "keyCode":"Key_U", "top":[325, 87], "bottom":[352, 118] }, - { "bIndex":50, "keyCode":"Key_I", "top":[367, 87], "bottom":[394, 118] }, - { "bIndex":56, "keyCode":"Key_O", "top":[409, 87], "bottom":[436, 118] }, - { "bIndex":62, "keyCode":"Key_P", "top":[450, 87], "bottom":[477, 118] }, - { "bIndex":68, "keyCode":"Key_Left_Bracket", "top":[492, 87], "bottom":[519, 118] }, - { "bIndex":74, "keyCode":"Key_Right_Bracket", "top":[534, 87], "bottom":[561, 118] }, - { "bIndex":80, "keyCode":"Key_Back_Slash", "top":[576, 87], "bottom":[622, 118] }, - { "bIndex":94, "keyCode":"Key_Page_Down", "top":[680, 173], "bottom":[707, 204] }, - { "bIndex":93, "keyCode":"Key_Page_Up", "top":[680, 130], "bottom":[707, 161] }, - { "bIndex":3, "keyCode":"Key_Caps_Lock", "top":[13, 130], "bottom":[70, 161] }, - { "bIndex":9, "keyCode":"Key_A", "top":[86, 130], "bottom":[113, 161] }, - { "bIndex":15, "keyCode":"Key_S", "top":[127, 130], "bottom":[154, 161] }, - { "bIndex":21, "keyCode":"Key_D", "top":[169, 130], "bottom":[196, 161] }, - { "bIndex":27, "keyCode":"Key_F", "top":[211, 130], "bottom":[238, 161] }, - { "bIndex":33, "keyCode":"Key_G", "top":[253, 130], "bottom":[280, 161] }, - { "bIndex":39, "keyCode":"Key_H", "top":[294, 130], "bottom":[321, 161] }, - { "bIndex":45, "keyCode":"Key_J", "top":[336, 130], "bottom":[363, 161] }, - { "bIndex":51, "keyCode":"Key_K", "top":[378, 130], "bottom":[405, 161] }, - { "bIndex":57, "keyCode":"Key_L", "top":[419, 130], "bottom":[446, 161] }, - { "bIndex":63, "keyCode":"Key_Semi_Colon", "top":[461, 130], "bottom":[488, 161] }, - { "bIndex":69, "keyCode":"Key_Quote", "top":[502, 130], "bottom":[529, 161] }, - { "bIndex":4, "keyCode":"Key_Left_Shift", "top":[13, 172], "bottom":[91, 203] }, - { "bIndex":10, "keyCode":"Key_Z", "top":[107, 172], "bottom":[134, 203] }, - { "bIndex":16, "keyCode":"Key_X", "top":[148, 172], "bottom":[175, 203] }, - { "bIndex":22, "keyCode":"Key_C", "top":[190, 172], "bottom":[217, 203] }, - { "bIndex":28, "keyCode":"Key_V", "top":[232, 172], "bottom":[259, 203] }, - { "bIndex":34, "keyCode":"Key_B", "top":[273, 172], "bottom":[300, 203] }, - { "bIndex":40, "keyCode":"Key_N", "top":[315, 172], "bottom":[342, 203] }, - { "bIndex":46, "keyCode":"Key_M", "top":[357, 172], "bottom":[384, 203] }, - { "bIndex":52, "keyCode":"Key_Comma", "top":[398, 172], "bottom":[425, 203] }, - { "bIndex":58, "keyCode":"Key_Dot", "top":[440, 172], "bottom":[467, 203] }, - { "bIndex":64, "keyCode":"Key_Slash", "top":[482, 172], "bottom":[509, 203] }, - { "bIndex":82, "keyCode":"Key_Right_Shift", "top":[524, 172], "bottom":[622, 203] }, - { "bIndex":88, "keyCode":"Key_Up", "top":[638, 172], "bottom":[665, 203] }, - { "bIndex":5, "keyCode":"Key_Left_Control", "top":[13, 215], "bottom":[49, 246] }, - { "bIndex":11, "keyCode":"Key_Left_Super", "top":[66, 215], "bottom":[102, 246] }, - { "bIndex":17, "keyCode":"Key_Left_Alt", "top":[118, 215], "bottom":[153, 246] }, - { "bIndex":35, "keyCode":"Key_Space", "top":[170, 215], "bottom":[414, 246] }, - { "bIndex":53, "keyCode":"Key_Right_Alt", "top":[433, 215], "bottom":[465, 246] }, - { "bIndex":59, "keyCode":"Key_Fn", "top":[486, 215], "bottom":[518, 246] }, - { "bIndex":65, "keyCode":"Key_Right_Control", "top":[539, 216], "bottom":[571, 247] }, - { "bIndex":83, "keyCode":"Key_Left", "top":[597, 216], "bottom":[624, 247] }, - { "bIndex":89, "keyCode":"Key_Down", "top":[638, 216], "bottom":[665, 247] }, - { "bIndex":95, "keyCode":"Key_Right", "top":[679, 216], "bottom":[706, 247] }, - { "bIndex":81, "keyCode":"Key_Enter", "top":[545, 129], "bottom":[622, 160] } - ] -} diff --git a/keyboards/5ac/images/24f.png b/keyboards/5ac/images/24f.png deleted file mode 100644 index c1df74b..0000000 Binary files a/keyboards/5ac/images/24f.png and /dev/null differ diff --git a/keyboards/c45/configs/8008.json b/keyboards/c45/configs/8008.json deleted file mode 100755 index ab32f6f..0000000 --- a/keyboards/c45/configs/8008.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name":"RK68K", - "rgb":true, - "top":[10, 11], - "bottom":[710, 232], - "keys":[ - { "bIndex":1, "keyCode":"Key_Escape", "top":[10, 11], "bottom":[39, 44] }, - { "bIndex":92, "keyCode":"Key_Delete", "top":[680, 58], "bottom":[709, 91] }, - { "bIndex":91, "keyCode":"Key_Back_Quote", "top":[680, 11], "bottom":[709, 44] }, - { "bIndex":7, "keyCode":"Key_1", "top":[54, 11], "bottom":[83, 44] }, - { "bIndex":13, "keyCode":"Key_2", "top":[98, 11], "bottom":[127, 44] }, - { "bIndex":19, "keyCode":"Key_3", "top":[144, 11], "bottom":[173, 44] }, - { "bIndex":25, "keyCode":"Key_4", "top":[188, 11], "bottom":[217, 44] }, - { "bIndex":31, "keyCode":"Key_5", "top":[232, 11], "bottom":[261, 44] }, - { "bIndex":37, "keyCode":"Key_6", "top":[277, 11], "bottom":[306, 44] }, - { "bIndex":43, "keyCode":"Key_7", "top":[322, 11], "bottom":[351, 44] }, - { "bIndex":49, "keyCode":"Key_8", "top":[366, 11], "bottom":[395, 44] }, - { "bIndex":55, "keyCode":"Key_9", "top":[411, 11], "bottom":[440, 44] }, - { "bIndex":61, "keyCode":"Key_0", "top":[456, 11], "bottom":[485, 44] }, - { "bIndex":67, "keyCode":"Key_Hyphen", "top":[501, 11], "bottom":[530, 44] }, - { "bIndex":73, "keyCode":"Key_Equals", "top":[547, 11], "bottom":[576, 44] }, - { "bIndex":79, "keyCode":"Key_Backspace", "top":[592, 11], "bottom":[663, 44] }, - { "bIndex":2, "keyCode":"Key_Tab", "top":[11, 58], "bottom":[60, 91] }, - { "bIndex":8, "keyCode":"Key_Q", "top":[78, 58], "bottom":[107, 91] }, - { "bIndex":14, "keyCode":"Key_W", "top":[124, 58], "bottom":[153, 91] }, - { "bIndex":20, "keyCode":"Key_E", "top":[168, 58], "bottom":[197, 91] }, - { "bIndex":26, "keyCode":"Key_R", "top":[212, 58], "bottom":[241, 91] }, - { "bIndex":32, "keyCode":"Key_T", "top":[257, 58], "bottom":[286, 91] }, - { "bIndex":38, "keyCode":"Key_Y", "top":[301, 58], "bottom":[330, 91] }, - { "bIndex":44, "keyCode":"Key_U", "top":[345, 58], "bottom":[374, 91] }, - { "bIndex":50, "keyCode":"Key_I", "top":[390, 58], "bottom":[419, 91] }, - { "bIndex":56, "keyCode":"Key_O", "top":[435, 58], "bottom":[464, 91] }, - { "bIndex":62, "keyCode":"Key_P", "top":[480, 58], "bottom":[509, 91] }, - { "bIndex":68, "keyCode":"Key_Left_Bracket", "top":[524, 58], "bottom":[553, 91] }, - { "bIndex":74, "keyCode":"Key_Right_Bracket", "top":[569, 58], "bottom":[598, 91] }, - { "bIndex":80, "keyCode":"Key_Back_Slash", "top":[613, 57], "bottom":[663, 90] }, - { "bIndex":94, "keyCode":"Key_Page_Down", "top":[680, 151], "bottom":[709, 184] }, - { "bIndex":93, "keyCode":"Key_Page_Up", "top":[680, 105], "bottom":[709, 138] }, - { "bIndex":3, "keyCode":"Key_Caps_Lock", "top":[12, 104], "bottom":[72, 137] }, - { "bIndex":9, "keyCode":"Key_A", "top":[87, 104], "bottom":[116, 137] }, - { "bIndex":15, "keyCode":"Key_S", "top":[134, 104], "bottom":[163, 137] }, - { "bIndex":21, "keyCode":"Key_D", "top":[178, 104], "bottom":[207, 137] }, - { "bIndex":27, "keyCode":"Key_F", "top":[223, 104], "bottom":[252, 137] }, - { "bIndex":33, "keyCode":"Key_G", "top":[267, 104], "bottom":[296, 137] }, - { "bIndex":39, "keyCode":"Key_H", "top":[311, 104], "bottom":[340, 137] }, - { "bIndex":45, "keyCode":"Key_J", "top":[356, 104], "bottom":[385, 137] }, - { "bIndex":51, "keyCode":"Key_K", "top":[400, 104], "bottom":[429, 137] }, - { "bIndex":57, "keyCode":"Key_L", "top":[445, 104], "bottom":[474, 137] }, - { "bIndex":63, "keyCode":"Key_Semi_Colon", "top":[490, 104], "bottom":[519, 137] }, - { "bIndex":69, "keyCode":"Key_Quote", "top":[534, 104], "bottom":[563, 137] }, - { "bIndex":4, "keyCode":"Key_Left_Shift", "top":[11, 150], "bottom":[93, 183] }, - { "bIndex":10, "keyCode":"Key_Z", "top":[109, 150], "bottom":[138, 183] }, - { "bIndex":16, "keyCode":"Key_X", "top":[155, 150], "bottom":[184, 183] }, - { "bIndex":22, "keyCode":"Key_C", "top":[199, 150], "bottom":[228, 183] }, - { "bIndex":28, "keyCode":"Key_V", "top":[244, 150], "bottom":[273, 183] }, - { "bIndex":34, "keyCode":"Key_B", "top":[289, 150], "bottom":[318, 183] }, - { "bIndex":40, "keyCode":"Key_N", "top":[334, 150], "bottom":[363, 183] }, - { "bIndex":46, "keyCode":"Key_M", "top":[378, 150], "bottom":[407, 183] }, - { "bIndex":52, "keyCode":"Key_Comma", "top":[423, 150], "bottom":[452, 183] }, - { "bIndex":58, "keyCode":"Key_Dot", "top":[468, 150], "bottom":[497, 183] }, - { "bIndex":64, "keyCode":"Key_Slash", "top":[514, 150], "bottom":[543, 183] }, - { "bIndex":70, "keyCode":"Key_Right_Shift", "top":[557, 150], "bottom":[617, 183] }, - { "bIndex":88, "keyCode":"Key_Up", "top":[635, 151], "bottom":[664, 184] }, - { "bIndex":5, "keyCode":"Key_Left_Control", "top":[10, 197], "bottom":[47, 230] }, - { "bIndex":11, "keyCode":"Key_Left_Super", "top":[65, 197], "bottom":[102, 230] }, - { "bIndex":17, "keyCode":"Key_Left_Alt", "top":[121, 197], "bottom":[158, 230] }, - { "bIndex":35, "keyCode":"Key_Space", "top":[176, 197], "bottom":[440, 230] }, - { "bIndex":53, "keyCode":"Key_Right_Alt", "top":[458, 198], "bottom":[487, 231] }, - { "bIndex":59, "keyCode":"Key_Fn", "top":[502, 198], "bottom":[531, 231] }, - { "bIndex":65, "keyCode":"Key_Right_Control", "top":[547, 199], "bottom":[576, 232] }, - { "bIndex":83, "keyCode":"Key_Left", "top":[591, 198], "bottom":[620, 231] }, - { "bIndex":89, "keyCode":"Key_Down", "top":[636, 198], "bottom":[665, 231] }, - { "bIndex":95, "keyCode":"Key_Right", "top":[681, 198], "bottom":[710, 231] }, - { "bIndex":81, "keyCode":"Key_Enter", "top":[580, 104], "bottom":[662, 137] } - ] -} diff --git a/keyboards/c45/configs/8018.json b/keyboards/c45/configs/8018.json deleted file mode 100644 index 40d42be..0000000 --- a/keyboards/c45/configs/8018.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name":"RK855", - "rgb":true, - "top":[10, 11], - "bottom":[710, 232], - "keys":[ - { "bIndex":1, "keyCode":"Key_Escape", "top":[10, 11], "bottom":[39, 44] }, - { "bIndex":92, "keyCode":"Key_Delete", "top":[680, 58], "bottom":[709, 91] }, - { "bIndex":91, "keyCode":"Key_Back_Quote", "top":[680, 11], "bottom":[709, 44] }, - { "bIndex":7, "keyCode":"Key_1", "top":[54, 11], "bottom":[83, 44] }, - { "bIndex":13, "keyCode":"Key_2", "top":[98, 11], "bottom":[127, 44] }, - { "bIndex":19, "keyCode":"Key_3", "top":[144, 11], "bottom":[173, 44] }, - { "bIndex":25, "keyCode":"Key_4", "top":[188, 11], "bottom":[217, 44] }, - { "bIndex":31, "keyCode":"Key_5", "top":[232, 11], "bottom":[261, 44] }, - { "bIndex":37, "keyCode":"Key_6", "top":[277, 11], "bottom":[306, 44] }, - { "bIndex":43, "keyCode":"Key_7", "top":[322, 11], "bottom":[351, 44] }, - { "bIndex":49, "keyCode":"Key_8", "top":[366, 11], "bottom":[395, 44] }, - { "bIndex":55, "keyCode":"Key_9", "top":[411, 11], "bottom":[440, 44] }, - { "bIndex":61, "keyCode":"Key_0", "top":[456, 11], "bottom":[485, 44] }, - { "bIndex":67, "keyCode":"Key_Hyphen", "top":[501, 11], "bottom":[530, 44] }, - { "bIndex":73, "keyCode":"Key_Equals", "top":[547, 11], "bottom":[576, 44] }, - { "bIndex":79, "keyCode":"Key_Backspace", "top":[592, 11], "bottom":[663, 44] }, - { "bIndex":2, "keyCode":"Key_Tab", "top":[11, 58], "bottom":[60, 91] }, - { "bIndex":8, "keyCode":"Key_Q", "top":[78, 58], "bottom":[107, 91] }, - { "bIndex":14, "keyCode":"Key_W", "top":[124, 58], "bottom":[153, 91] }, - { "bIndex":20, "keyCode":"Key_E", "top":[168, 58], "bottom":[197, 91] }, - { "bIndex":26, "keyCode":"Key_R", "top":[212, 58], "bottom":[241, 91] }, - { "bIndex":32, "keyCode":"Key_T", "top":[257, 58], "bottom":[286, 91] }, - { "bIndex":38, "keyCode":"Key_Y", "top":[301, 58], "bottom":[330, 91] }, - { "bIndex":44, "keyCode":"Key_U", "top":[345, 58], "bottom":[374, 91] }, - { "bIndex":50, "keyCode":"Key_I", "top":[390, 58], "bottom":[419, 91] }, - { "bIndex":56, "keyCode":"Key_O", "top":[435, 58], "bottom":[464, 91] }, - { "bIndex":62, "keyCode":"Key_P", "top":[480, 58], "bottom":[509, 91] }, - { "bIndex":68, "keyCode":"Key_Left_Bracket", "top":[524, 58], "bottom":[553, 91] }, - { "bIndex":74, "keyCode":"Key_Right_Bracket", "top":[569, 58], "bottom":[598, 91] }, - { "bIndex":80, "keyCode":"Key_Back_Slash", "top":[613, 57], "bottom":[663, 90] }, - { "bIndex":94, "keyCode":"Key_Page_Down", "top":[680, 151], "bottom":[709, 184] }, - { "bIndex":93, "keyCode":"Key_Page_Up", "top":[680, 105], "bottom":[709, 138] }, - { "bIndex":3, "keyCode":"Key_Caps_Lock", "top":[12, 104], "bottom":[72, 137] }, - { "bIndex":9, "keyCode":"Key_A", "top":[87, 104], "bottom":[116, 137] }, - { "bIndex":15, "keyCode":"Key_S", "top":[134, 104], "bottom":[163, 137] }, - { "bIndex":21, "keyCode":"Key_D", "top":[178, 104], "bottom":[207, 137] }, - { "bIndex":27, "keyCode":"Key_F", "top":[223, 104], "bottom":[252, 137] }, - { "bIndex":33, "keyCode":"Key_G", "top":[267, 104], "bottom":[296, 137] }, - { "bIndex":39, "keyCode":"Key_H", "top":[311, 104], "bottom":[340, 137] }, - { "bIndex":45, "keyCode":"Key_J", "top":[356, 104], "bottom":[385, 137] }, - { "bIndex":51, "keyCode":"Key_K", "top":[400, 104], "bottom":[429, 137] }, - { "bIndex":57, "keyCode":"Key_L", "top":[445, 104], "bottom":[474, 137] }, - { "bIndex":63, "keyCode":"Key_Semi_Colon", "top":[490, 104], "bottom":[519, 137] }, - { "bIndex":69, "keyCode":"Key_Quote", "top":[534, 104], "bottom":[563, 137] }, - { "bIndex":4, "keyCode":"Key_Left_Shift", "top":[11, 150], "bottom":[93, 183] }, - { "bIndex":10, "keyCode":"Key_Z", "top":[109, 150], "bottom":[138, 183] }, - { "bIndex":16, "keyCode":"Key_X", "top":[155, 150], "bottom":[184, 183] }, - { "bIndex":22, "keyCode":"Key_C", "top":[199, 150], "bottom":[228, 183] }, - { "bIndex":28, "keyCode":"Key_V", "top":[244, 150], "bottom":[273, 183] }, - { "bIndex":34, "keyCode":"Key_B", "top":[289, 150], "bottom":[318, 183] }, - { "bIndex":40, "keyCode":"Key_N", "top":[334, 150], "bottom":[363, 183] }, - { "bIndex":46, "keyCode":"Key_M", "top":[378, 150], "bottom":[407, 183] }, - { "bIndex":52, "keyCode":"Key_Comma", "top":[423, 150], "bottom":[452, 183] }, - { "bIndex":58, "keyCode":"Key_Dot", "top":[468, 150], "bottom":[497, 183] }, - { "bIndex":64, "keyCode":"Key_Slash", "top":[514, 150], "bottom":[543, 183] }, - { "bIndex":70, "keyCode":"Key_Right_Shift", "top":[557, 150], "bottom":[617, 183] }, - { "bIndex":88, "keyCode":"Key_Up", "top":[635, 151], "bottom":[664, 184] }, - { "bIndex":5, "keyCode":"Key_Left_Control", "top":[10, 197], "bottom":[47, 230] }, - { "bIndex":11, "keyCode":"Key_Left_Super", "top":[65, 197], "bottom":[102, 230] }, - { "bIndex":17, "keyCode":"Key_Left_Alt", "top":[121, 197], "bottom":[158, 230] }, - { "bIndex":35, "keyCode":"Key_Space", "top":[176, 197], "bottom":[440, 230] }, - { "bIndex":53, "keyCode":"Key_Right_Alt", "top":[458, 198], "bottom":[487, 231] }, - { "bIndex":59, "keyCode":"Key_Fn", "top":[502, 198], "bottom":[531, 231] }, - { "bIndex":65, "keyCode":"Key_Right_Control", "top":[547, 199], "bottom":[576, 232] }, - { "bIndex":83, "keyCode":"Key_Left", "top":[591, 198], "bottom":[620, 231] }, - { "bIndex":89, "keyCode":"Key_Down", "top":[636, 198], "bottom":[665, 231] }, - { "bIndex":95, "keyCode":"Key_Right", "top":[681, 198], "bottom":[710, 231] }, - { "bIndex":81, "keyCode":"Key_Enter", "top":[580, 104], "bottom":[662, 137] } - ] -} diff --git a/keyboards/c45/images/8008.png b/keyboards/c45/images/8008.png deleted file mode 100755 index dce5f56..0000000 Binary files a/keyboards/c45/images/8008.png and /dev/null differ diff --git a/keyboards/c45/images/8018.png b/keyboards/c45/images/8018.png deleted file mode 100644 index dce5f56..0000000 Binary files a/keyboards/c45/images/8018.png and /dev/null differ diff --git a/keyboards/hid-col.json b/keyboards/hid-col.json new file mode 100644 index 0000000..fb88936 --- /dev/null +++ b/keyboards/hid-col.json @@ -0,0 +1,5 @@ +{ + "default":"05", + + "258a:57":"06" +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2e17699..62798f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,30 +12,32 @@ GNU General Public License for more details. ]] set(SOURCE_LIST - main.cpp - resources.qrc + customcolours.h customcolours.cpp + customlightmodekeys.h customlightmodekeys.cpp + custommappedkeys.h custommappedkeys.cpp + enhanceddialog.h enhanceddialog.cpp + hidconnection.h hidconnection.cpp + hidconnectionworker.h hidconnectionworker.cpp + icons.h icons.cpp key.h key.cpp keyboard.h keyboard.cpp + keyboardconfiguratorcontroller.h keyboardconfiguratorcontroller.cpp + keyboardmodel.h keyboardmodel.cpp keyboardusbid.h keyboardusbid.cpp - profile.h profile.cpp - mode.h mode.cpp - hidconnection.h hidconnection.cpp - hidconnectionworker.h hidconnectionworker.cpp keycode.h - enhanceddialog.h enhanceddialog.cpp - icons.h icons.cpp + keycodemodel.h keycodemodel.cpp + keycodemodelproxy.h keycodemodelproxy.cpp + main.cpp mainwindowcontroller.h mainwindowcontroller.cpp - keyboardmodel.h keyboardmodel.cpp - keyboardconfiguratorcontroller.h keyboardconfiguratorcontroller.cpp - customlightmodekeys.h customlightmodekeys.cpp + messagehandler.h messagehandler.cpp + mode.h mode.cpp modemodel.h modemodel.cpp + profile.h profile.cpp profilemodel.h profilemodel.cpp settingscontroller.h settingscontroller.cpp - customcolours.h customcolours.cpp - custommappedkeys.h custommappedkeys.cpp - keycodemodel.h keycodemodel.cpp - keycodemodelproxy.h keycodemodelproxy.cpp startatboot.h startatboot.cpp + + resources.qrc ) set(MACOS_APP_ICON "${CMAKE_SOURCE_DIR}/icons/rangoli.icns") @@ -50,7 +52,7 @@ qt_add_executable(rangoli ${SOURCE_LIST}) qt_add_qml_module(rangoli URI Rangoli - VERSION 1.0 + VERSION ${VERSION} QML_FILES Main.qml EnhancedDialog.qml @@ -63,8 +65,8 @@ qt_add_qml_module(rangoli set_target_properties(rangoli PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME Rangoli MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} - MACOSX_BUNDLE_COPYRIGHT "Debayan Sutradhar" - MACOSX_BUNDLE_GUI_IDENTIFIER io.github.rnayabed.rangoli + MACOSX_BUNDLE_COPYRIGHT ${MACOSX_BUNDLE_COPYRIGHT} + MACOSX_BUNDLE_GUI_IDENTIFIER ${MACOSX_BUNDLE_GUI_IDENTIFIER} MACOSX_BUNDLE_ICON_FILE rangoli.icns MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} MACOSX_BUNDLE TRUE diff --git a/src/KeyboardConfigurator.qml b/src/KeyboardConfigurator.qml index 94c960f..802be83 100644 --- a/src/KeyboardConfigurator.qml +++ b/src/KeyboardConfigurator.qml @@ -98,12 +98,7 @@ Item { function show(index, name) { this.index = index - - if (this.index > -1) - { - profileNameTextField.text = name - } - + profileNameTextField.text = name open() } diff --git a/src/Settings.qml b/src/Settings.qml index db76a12..4dcce40 100644 --- a/src/Settings.qml +++ b/src/Settings.qml @@ -26,11 +26,13 @@ Item { signal returnToHome() Component.onCompleted: { - if (settingsController.unsavedChanges) settingsController.load() - donateButton.configureText() } + onReturnToHome: { + if (settingsController.unsavedChanges) settingsController.load() + } + onWidthChanged: donateButton.configureText() Rectangle { diff --git a/src/customlightmodekeys.cpp b/src/customlightmodekeys.cpp index b991e5e..3ba9f1b 100644 --- a/src/customlightmodekeys.cpp +++ b/src/customlightmodekeys.cpp @@ -56,6 +56,8 @@ QHash CustomLightModeKeys::roleNames() const void CustomLightModeKeys::add(const int &keyIndex, const QColor &colour) { + qInfo() << "Set" << colour << "for key index" << keyIndex; + beginResetModel(); m_keys[keyIndex] = colour; m_keyIndexes << keyIndex; @@ -69,14 +71,21 @@ void CustomLightModeKeys::addIfNotExists(const int &keyIndex, const QColor &colo } } +void CustomLightModeKeys::remove(const int &keyIndex) +{ + qInfo() << "Remove colour for key index" << keyIndex; + + beginResetModel(); + m_keys.remove(keyIndex); + m_keyIndexes.removeOne(keyIndex); + endResetModel(); +} + void CustomLightModeKeys::toggle(const int& keyIndex, const QColor &colour) { if (m_keys.contains(keyIndex)) { - beginResetModel(); - m_keys.remove(keyIndex); - m_keyIndexes.removeOne(keyIndex); - endResetModel(); + remove(keyIndex); } else { @@ -101,6 +110,7 @@ const QHash &CustomLightModeKeys::keys() void CustomLightModeKeys::clear() { + qInfo() << "Clear custom colours for all key indexes"; beginResetModel(); m_keys.clear(); m_keyIndexes.clear(); diff --git a/src/customlightmodekeys.h b/src/customlightmodekeys.h index 45f7eb7..aba641c 100644 --- a/src/customlightmodekeys.h +++ b/src/customlightmodekeys.h @@ -46,6 +46,7 @@ class CustomLightModeKeys : public QAbstractListModel void add(const int& keyIndex, const QColor &colour); void addIfNotExists(const int& keyIndex, const QColor &colour); + void remove(const int& keyIndex); void toggle(const int& keyIndex, const QColor &colour); void toggle(const int& keyIndex); diff --git a/src/custommappedkeys.cpp b/src/custommappedkeys.cpp index 48ed8af..485a246 100644 --- a/src/custommappedkeys.cpp +++ b/src/custommappedkeys.cpp @@ -85,6 +85,10 @@ void CustomMappedKeys::setSelectedKeyIndex(const int &keyIndex) void CustomMappedKeys::add(const KeyCode::Code &code) { + qInfo() << "Add custom mapped key" + << KeyCode::Names[code] + << "for key index" << m_selectedKeyIndex; + beginResetModel(); if (m_keys.contains(m_selectedKeyIndex)) { @@ -111,6 +115,10 @@ void CustomMappedKeys::add(const KeyCode::Code &code) void CustomMappedKeys::remove(const int& index) { + qInfo() << "Remove custom mapped key" + << KeyCode::Names[m_keys[m_selectedKeyIndex].at(index)] + << "for key index" << m_selectedKeyIndex; + beginResetModel(); m_keys[m_selectedKeyIndex].removeAt(index); @@ -125,6 +133,7 @@ void CustomMappedKeys::remove(const int& index) void CustomMappedKeys::clear() { + qInfo() << "Clear all custom mapped keys for key index" << m_selectedKeyIndex; beginResetModel(); m_keys.remove(m_selectedKeyIndex); m_keyIndexes.removeOne(m_selectedKeyIndex); @@ -133,6 +142,7 @@ void CustomMappedKeys::clear() void CustomMappedKeys::clearAll() { + qInfo() << "Clear all custom mapped keys for all key indexes"; beginResetModel(); m_keys.clear(); m_keyIndexes.clear(); diff --git a/src/hidconnection.cpp b/src/hidconnection.cpp index ea7bd3b..904bf82 100644 --- a/src/hidconnection.cpp +++ b/src/hidconnection.cpp @@ -20,8 +20,16 @@ HIDConnection::HIDConnection(QObject *parent) connect(&m_thread, &QThread::started, m_worker, &HIDConnectionWorker::init); - connect(m_worker, &HIDConnectionWorker::initDone, this, [this](const bool& success){ - emit initDone(success); + connect(m_worker, &HIDConnectionWorker::HIDColInitFailed, this, [this](){ + emit HIDColInitFailed(); + }); + + connect(m_worker, &HIDConnectionWorker::HIDAPIInitFailed, this, [this](){ + emit HIDAPIInitFailed(); + }); + + connect(m_worker, &HIDConnectionWorker::initSuccessful, this, [this](){ + emit initSuccessful(); }); connect(this, &HIDConnection::refreshKeyboards, diff --git a/src/hidconnection.h b/src/hidconnection.h index 8b47482..5725fd4 100644 --- a/src/hidconnection.h +++ b/src/hidconnection.h @@ -35,7 +35,9 @@ class HIDConnection : public QObject QPointer m_worker; signals: - void initDone(const bool& success); + void HIDColInitFailed(); + void HIDAPIInitFailed(); + void initSuccessful(); void refreshKeyboards(QPointer connectedKeyboards); diff --git a/src/hidconnectionworker.cpp b/src/hidconnectionworker.cpp index bec6002..31fcbf4 100644 --- a/src/hidconnectionworker.cpp +++ b/src/hidconnectionworker.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include "keyboardconfiguratorcontroller.h" @@ -26,19 +25,36 @@ using namespace Qt::Literals::StringLiterals; HIDConnectionWorker::HIDConnectionWorker(QObject *parent) - : QObject{parent} + : QObject{parent}, m_HIDInitSuccessful{false} { } void HIDConnectionWorker::init() { + qDebug() << "Init HID Connection Worker"; + +#ifdef Q_OS_WINDOWS + if (!initHIDCol()) + { + emit HIDColInitFailed(); + return; + } +#endif + m_HIDInitSuccessful = ! hid_init(); + if (!m_HIDInitSuccessful) + { + emit HIDAPIInitFailed(); + return; + } - emit initDone(m_HIDInitSuccessful); + emit initSuccessful(); } void HIDConnectionWorker::exit() { + qDebug() << "Exit HID Connection Worker"; + if (m_HIDInitSuccessful) { hid_exit(); @@ -47,6 +63,8 @@ void HIDConnectionWorker::exit() void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyboards) { + qInfo() << "Refresh keyboards"; + struct hid_device_info* devs = hid_enumerate(0x0, 0x0); struct hid_device_info* devIterator = devs; @@ -54,8 +72,14 @@ void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyb QList disconnectedHIDPIDs = connectedKeyboards->keyboardUSBIDs(); QList connectedHIDPIDs; +#ifdef Q_OS_WIN + QString defaultCol = m_hidColConfig["default"].toString(); +#endif + while (devIterator) { + qDebug() << "HID Device found: " << devIterator->path; + auto usbID = KeyboardUSBID{devIterator->vendor_id, devIterator->product_id}; QFile configFile{QStringLiteral("keyboards/%1/configs/%2.json") @@ -63,28 +87,35 @@ void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyb QString::number(usbID.pid, 16))}; if (configFile.exists() - #ifdef Q_OS_WIN - && QString(devIterator->path).contains(u"&Col05"_s, Qt::CaseInsensitive) - #else +#ifdef Q_OS_WIN + && QString(devIterator->path).contains(QStringLiteral("&Col%1") + .arg(m_hidColConfig[QStringLiteral("%1:%2") + .arg(QString::number(usbID.vid, 16), + QString::number(usbID.pid, 16))].toString(defaultCol)), + Qt::CaseInsensitive) +#else && devIterator->usage == 0x0080 && devIterator->usage_page == 0x0001 - #endif +#endif && !connectedHIDPIDs.contains(usbID)) { connectedHIDPIDs << usbID; if (disconnectedHIDPIDs.contains(usbID)) { + qDebug() << "Remove" << usbID << "from disconnected hidpids"; disconnectedHIDPIDs.removeAll(usbID); continue; } if (!configFile.open(QIODevice::ReadOnly)) { + qCritical() << "Unable to open config file for" << usbID; + MainWindowController::showEnhancedDialog( this, EnhancedDialog { tr("Error"), - tr("Unable to read configuration file of keyboard with VID '%1' and PID '%2'.") + tr("Unable to open configuration file of keyboard with VID '%1' and PID '%2'.") .arg(QString::number(usbID.vid, 16), QString::number(usbID.pid, 16)) }); @@ -96,6 +127,8 @@ void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyb .arg(QString::number(usbID.vid, 16), QString::number(usbID.pid, 16))).exists()) { + qCritical() << "Unable to find image for" << usbID; + MainWindowController::showEnhancedDialog( this, EnhancedDialog { @@ -110,6 +143,8 @@ void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyb QJsonDocument configDocument{QJsonDocument::fromJson(configFile.readAll())}; + configFile.close(); + QJsonObject configObj = configDocument.object(); QString name = configObj["name"].toString(); @@ -162,8 +197,6 @@ void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyb keys, configObj["rgb"].toBool(), keyMapEnabled, topObj[0].toInt(), topObj[1].toInt(), bottomObj[0].toInt(), bottomObj[1].toInt() }); - - configFile.close(); } devIterator = devIterator->next; @@ -179,12 +212,16 @@ void HIDConnectionWorker::refreshKeyboards(QPointer connectedKeyb emit keyboardsScanComplete(); } -void HIDConnectionWorker::sendData(const QString &path, unsigned char** buffers, int bufferLength) +void HIDConnectionWorker::sendData(const QString &path, unsigned char** buffers, int buffersLength) { + qInfo() << "Sending" << buffersLength << "feature reports to keyboard at HID path" << path; + qDebug() << "Each buffer is of size" << KeyboardConfiguratorController::BufferSize; + hid_device* handle = hid_open_path(qPrintable(path)); if (!handle) { + qCritical() << "Unable to open device"; #ifdef Q_OS_MACOS emit failedToSendData(tr("Insufficient Permissions.\n%1") .arg(MainWindowController::macOSPermissionNotice())); @@ -195,11 +232,13 @@ void HIDConnectionWorker::sendData(const QString &path, unsigned char** buffers, return; } - for(int i = 0; i < bufferLength; i++) + for(int i = 0; i < buffersLength; i++) { if (hid_send_feature_report(handle, buffers[i], KeyboardConfiguratorController::BufferSize) != KeyboardConfiguratorController::BufferSize) { + qCritical() << "Unable to send report" << i; + emit failedToSendData(tr("Failed to send feature report to keyboard. " "Make sure you have sufficient permissions.")); return; @@ -214,3 +253,21 @@ void HIDConnectionWorker::sendData(const QString &path, unsigned char** buffers, hid_close(handle); } + +bool HIDConnectionWorker::initHIDCol() +{ + QFile hidColConfigFile{u"keyboards/hid-col.json"_s}; + + if (!hidColConfigFile.open(QIODevice::ReadOnly)) + { + return false; + } + + QJsonDocument configDocument{QJsonDocument::fromJson(hidColConfigFile.readAll())}; + + hidColConfigFile.close(); + + m_hidColConfig = configDocument.object(); + + return true; +} diff --git a/src/hidconnectionworker.h b/src/hidconnectionworker.h index 643a6d2..2a2af61 100644 --- a/src/hidconnectionworker.h +++ b/src/hidconnectionworker.h @@ -20,7 +20,7 @@ #include #include #include - +#include #include #include "keyboard.h" @@ -33,7 +33,10 @@ class HIDConnectionWorker : public QObject explicit HIDConnectionWorker(QObject *parent = nullptr); signals: - void initDone(const bool& success); + void HIDColInitFailed(); + void HIDAPIInitFailed(); + void initSuccessful(); + void keyboardConnected(const Keyboard& keyboard); void keyboardDisconnected(const KeyboardUSBID& id); void keyboardsScanComplete(); @@ -46,10 +49,13 @@ public slots: void refreshKeyboards(QPointer connectedKeyboards); - void sendData(const QString& path, unsigned char** buffers, int bufferLength); + void sendData(const QString& path, unsigned char** buffers, int buffersLength); private: bool m_HIDInitSuccessful; + QJsonObject m_hidColConfig; + + bool initHIDCol(); }; #endif // HIDCONNECTIONWORKER_H diff --git a/src/keyboardconfiguratorcontroller.cpp b/src/keyboardconfiguratorcontroller.cpp index e93dc8d..ce33e34 100644 --- a/src/keyboardconfiguratorcontroller.cpp +++ b/src/keyboardconfiguratorcontroller.cpp @@ -198,6 +198,8 @@ void KeyboardConfiguratorController::load(const int &keyboardIndex) { m_selectedKeyboardIndex = keyboardIndex; + qInfo() << "Load keyboard" << selectedKeyboard().id; + emit loadName(selectedKeyboard().name); emit loadImage(selectedKeyboard().imagePath); @@ -472,6 +474,8 @@ void KeyboardConfiguratorController::setBufferKey(unsigned char *buffer, const i void KeyboardConfiguratorController::saveProfile() { + qInfo() << "Save profile" << profiles()->profileName(selectedProfileIndex());; + QSettings settings; settings.beginGroup(QStringLiteral("profiles/%1").arg(getProfileID())); @@ -489,12 +493,18 @@ void KeyboardConfiguratorController::saveProfile() .arg(QString::number(selectedKeyboard().id.vid), QString::number(selectedKeyboard().id.pid))); + qDebug() << "Brightness:" << m_brightness; + qDebug() << "Animation:" << m_animation; + qDebug() << "Sleep:" << m_sleep; + qDebug() << "Mode:" << m_selectedLightModeIndex; + qDebug() << "Random Colour:" << m_randomColours; + qDebug() << "Selected Colour:" << m_selectedColour; + settings.setValue(u"brightness"_s, m_brightness); settings.setValue(u"animation"_s, m_animation); settings.setValue(u"sleep"_s, m_sleep); - settings.setValue(u"mode"_s, m_selectedLightModeIndex); - - settings.setValue(u"random_colour"_s, m_randomColours); + settings.setValue(u"selected_light_mode_index"_s, m_selectedLightModeIndex); + settings.setValue(u"random_colours"_s, m_randomColours); settings.setValue(u"selected_colour"_s, m_selectedColour); settings.remove(u"custom_light_mode_keys"_s); @@ -540,6 +550,8 @@ void KeyboardConfiguratorController::saveProfile() void KeyboardConfiguratorController::saveToKeyboard() { + qInfo() << "Save to keyboard" << selectedKeyboard().id; + setSavingChanges(true); unsigned char** buffers = new unsigned char* [1 + CustomLightModeBuffersSize + KeyMapBuffersSize]; @@ -655,6 +667,8 @@ void KeyboardConfiguratorController::saveToKeyboard() void KeyboardConfiguratorController::loadProfileSettings() { + qInfo() << "Load settings from profile" << profiles()->profileName(selectedProfileIndex()); + QSettings settings; settings.beginGroup(QStringLiteral("profiles/%1/%2:%3") @@ -665,9 +679,9 @@ void KeyboardConfiguratorController::loadProfileSettings() setBrightness(settings.value(u"brightness"_s, 5).toUInt()); setAnimation(settings.value(u"animation"_s, 3).toUInt()); setSleep(settings.value(u"sleep"_s, 5).toUInt()); - setSelectedLightModeIndex(settings.value(u"mode"_s, m_modes->neonStreamIndex()).toUInt()); + setSelectedLightModeIndex(settings.value(u"selected_light_mode_index"_s, m_modes->neonStreamIndex()).toUInt()); - setRandomColours(settings.value(u"random_colour"_s, true).toBool()); + setRandomColours(settings.value(u"random_colours"_s, true).toBool()); setSelectedColour(settings.value(u"selected_colour"_s, QColor(Qt::white)).value()); settings.beginGroup(u"custom_light_mode_keys"_s); @@ -725,6 +739,8 @@ void KeyboardConfiguratorController::loadProfileSettings() void KeyboardConfiguratorController::loadProfileCustomColours() { + qInfo() << "Load colours from profile" << profiles()->profileName(selectedProfileIndex()); + QSettings settings; QList newColours; diff --git a/src/keyboardmodel.cpp b/src/keyboardmodel.cpp index c9ee827..1d791d8 100644 --- a/src/keyboardmodel.cpp +++ b/src/keyboardmodel.cpp @@ -20,6 +20,8 @@ KeyboardModel::KeyboardModel(QObject *parent) void KeyboardModel::append(const Keyboard& keyboard) { + qInfo() << "Add keyboard" << keyboard.id; + beginInsertRows(QModelIndex(), m_keyboards.size(), m_keyboards.size()); m_keyboardUSBIDs << keyboard.id; m_keyboards << keyboard; @@ -28,6 +30,8 @@ void KeyboardModel::append(const Keyboard& keyboard) void KeyboardModel::remove(const KeyboardUSBID& id) { + qInfo() << "Remove keyboard" << id; + for (int i = 0; i < m_keyboardUSBIDs.size(); i++) { if (m_keyboardUSBIDs.at(i) == id) @@ -36,8 +40,11 @@ void KeyboardModel::remove(const KeyboardUSBID& id) m_keyboardUSBIDs.removeAt(i); m_keyboards.removeAt(i); endRemoveRows(); + return; } } + + qCritical() << "Keyboard not found"; } int KeyboardModel::rowCount(const QModelIndex &parent) const diff --git a/src/keyboardusbid.cpp b/src/keyboardusbid.cpp index 28832ce..a9ed993 100644 --- a/src/keyboardusbid.cpp +++ b/src/keyboardusbid.cpp @@ -1,6 +1,29 @@ +/* + * Copyright (C) 2023 Debayan Sutradhar (rnayabed) (debayansutradhar3@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "keyboardusbid.h" +#include bool KeyboardUSBID::operator==(const KeyboardUSBID& other) const { return vid == other.vid && pid == other.pid; } + +QDebug& operator<<(QDebug& debug, const KeyboardUSBID& id) +{ + debug.nospace(); + debug << Qt::hex << id.vid + << ":" + << Qt::hex << id.pid; + return debug; +} diff --git a/src/keyboardusbid.h b/src/keyboardusbid.h index 6f29120..9745ff9 100644 --- a/src/keyboardusbid.h +++ b/src/keyboardusbid.h @@ -1,6 +1,7 @@ #ifndef KEYBOARDUSBID_H #define KEYBOARDUSBID_H +#include struct KeyboardUSBID { unsigned short vid; @@ -9,4 +10,6 @@ struct KeyboardUSBID bool operator==(const KeyboardUSBID& other) const; }; +QDebug& operator<<(QDebug& debug, const KeyboardUSBID& id); + #endif // KEYBOARDUSBID_H diff --git a/src/main.cpp b/src/main.cpp index 06b89db..9e03241 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,23 +23,46 @@ #include "mainwindowcontroller.h" #include "settingscontroller.h" #include "icons.h" +#include "messagehandler.h" using namespace Qt::Literals::StringLiterals; int main(int argc, char *argv[]) { + if (MessageHandler::init()) + { + qInstallMessageHandler(MessageHandler::handler); + } + else + { + qCritical("Unable to start logging to file!"); + } + + qInfo() << "Rangoli" << VERSION; + + if (QQuickWindow::graphicsApi() == QSGRendererInterface::Software) + { + qInfo() << "Graphics: Software"; + } + else + { + qInfo() << "Graphics: Hardware"; + } + MainWindowController mainWindowController; KeyboardConfiguratorController keyboardConfiguratorController; SettingsController settingsController; QGuiApplication app(argc, argv); + qInfo() << "Platform:" << app.platformName(); + qInfo() << "Qt" << qVersion(); + app.setOrganizationName(u"rnayabed"_s); app.setOrganizationDomain(u"rnayabed.github.io"_s); app.setApplicationName(u"rangoli"_s); app.setApplicationDisplayName(u"Rangoli"_s); app.setApplicationVersion(QString::number(VERSION)); - app.setWindowIcon(QIcon(Icons::get(Icons::Rangoli).remove(0,3))); #ifdef Q_OS_MACOS @@ -50,6 +73,8 @@ int main(int argc, char *argv[]) QQmlApplicationEngine engine; + QObject::connect(&engine, &QQmlApplicationEngine::quit, MessageHandler::close); + engine.setContextForObject(&mainWindowController, engine.rootContext()); engine.rootContext()->setContextProperty(u"mainWindowController"_s, &mainWindowController); diff --git a/src/mainwindowcontroller.cpp b/src/mainwindowcontroller.cpp index 45633c2..35098c0 100644 --- a/src/mainwindowcontroller.cpp +++ b/src/mainwindowcontroller.cpp @@ -118,9 +118,14 @@ void MainWindowController::init() m_startToSystemTrayIcon = QCoreApplication::arguments().contains(u"start_to_system_tray_icon"_s); if (m_startToSystemTrayIcon) + { + qInfo() << "Asked to start to System Tray Icon"; emit hide(); + } else + { emit show(); + } m_profiles->registerProfiles(); @@ -139,19 +144,20 @@ void MainWindowController::init() HIDConnection& connection = HIDConnection::getInstance(); - connect(&connection, &HIDConnection::initDone, this, [this](const bool& success){ - if (success) - { - refreshKeyboards(); - } - else - { - showFatalError(tr("Unable to initialise HID API"), - tr("Please check if you have permissions and restart Rangoli. " - "The program will now exit.")); - } + connect(&connection, &HIDConnection::HIDColInitFailed, this, [this](){ + showFatalError(tr("Unable to open HID Cols Config file"), + tr("The program will now exit.")); + }, Qt::SingleShotConnection); + + connect(&connection, &HIDConnection::HIDAPIInitFailed, this, [this](){ + showFatalError(tr("Unable to initialise HID API"), + tr("Please check if you have permissions and restart Rangoli. " + "The program will now exit.")); }, Qt::SingleShotConnection); + connect(&connection, &HIDConnection::initSuccessful, this, &MainWindowController::refreshKeyboards, + Qt::SingleShotConnection); + connect(&connection, &HIDConnection::keyboardConnected, this, [this](const Keyboard& keyboard){ m_connectedKeyboards->append(keyboard); @@ -176,6 +182,8 @@ void MainWindowController::init() this, [this](){ QSettings settings; + qInfo() << "Apply default profile"; + for (int i = 0 ; i < m_connectedKeyboards->keyboards().size(); i++) { m_keyboardConfiguratorController->load(i); @@ -187,6 +195,8 @@ void MainWindowController::init() QDir keyboards{u"keyboards"_s}; if (!keyboards.exists()) { + qCritical() << "Keyboards folder not found"; + #ifdef Q_OS_MACOS showFatalError(tr("Keyboards folder not found"), tr("If you are using the portable version, you need to " @@ -201,6 +211,7 @@ void MainWindowController::init() "you need to re-install it. Otherwise, please download " "Rangoli again.")); #endif + return; } @@ -210,12 +221,14 @@ void MainWindowController::init() if (!QFile::exists(QStringLiteral(LINUX_UDEV_RULES_PATH)) || !m_settingsController->udevRulesWritten()) { + qInfo() << "Show Linux udev prompt"; emit openLinuxUdevPopup(); } #endif if(m_settingsController->firstTimeUse()) { + qInfo() << "First time use"; #ifdef Q_OS_MACOS emit loadEnhancedDialog(EnhancedDialog{tr("Notice"), macOSPermissionNotice()}); @@ -293,8 +306,11 @@ void MainWindowController::closeInterrupted() return; } + if (!m_confirmQuitDialogVisible) { + qInfo() << "Show unsaved changes prompt"; + m_confirmQuitDialogVisible = true; EnhancedDialog d(tr("Warning"), @@ -312,14 +328,17 @@ void MainWindowController::setTheme(const int& theme) { if (theme == Theme::System) { + qInfo() << "Set System theme"; emit setSystemTheme(); } else if (theme == Theme::Light) { + qInfo() << "Set Light theme"; emit setLightTheme(); } else if (theme == Theme::Dark) { + qInfo() << "Set Dark theme"; emit setDarkTheme(); } } @@ -342,6 +361,8 @@ void MainWindowController::setCloseToSystemTrayIcon(const bool &closeToSystemTra void MainWindowController::launchLinuxUdevWriter() { + qInfo() << "Launch Linux udev writer"; + setLinuxUdevPopupProceedButtonEnabled(false); if (!QFile::exists(QStringLiteral(LINUX_UDEV_RULE_WRITER_NAME))) @@ -360,13 +381,14 @@ void MainWindowController::launchLinuxUdevWriter() QString exitRuleWriteFailed{u"2"_s}; QString oldID; - QString exitFile{QStringLiteral("%1_OUTPUT").arg(QStringLiteral(LINUX_UDEV_RULE_WRITER_NAME))}; - QFile oldOutput{exitFile}; + QString outputPath{QStringLiteral("%1_OUTPUT").arg(QStringLiteral(LINUX_UDEV_RULE_WRITER_NAME))}; + QFile oldOutput{outputPath}; if (oldOutput.exists()) { if (!oldOutput.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to old output" << outputPath; emit loadEnhancedDialog(EnhancedDialog { tr("Error"), tr("Unable to read old ID.") @@ -377,21 +399,24 @@ void MainWindowController::launchLinuxUdevWriter() } oldID = oldOutput.readAll().split(':').at(0); + + oldOutput.close(); } QPointer udevWriter{new QProcess{this}}; connect(udevWriter, &QProcess::finished, this, - [this, exitFile, exitOK, exitKeyboardsReadFailed, exitRuleWriteFailed, oldID] + [this, outputPath, exitOK, exitKeyboardsReadFailed, exitRuleWriteFailed, oldID] (int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitStatus) Q_UNUSED(exitCode) setLinuxUdevPopupProceedButtonEnabled(true); - QFile output{exitFile}; + QFile output{outputPath}; if (!output.open(QIODevice::ReadOnly)) { + qCritical() << "Failed to new output" << outputPath; emit loadEnhancedDialog(EnhancedDialog { tr("Error"), tr("The udev rules writer failed to run. Did you provide incorrect password?") @@ -399,9 +424,17 @@ void MainWindowController::launchLinuxUdevWriter() return; } - QList outputs{output.readAll().split(':')}; + QByteArray outRaw = output.readAll(); + qDebug() << "Output File raw:" << outRaw; + + output.close(); + + QList outputs{outRaw.split(':')}; + qDebug() << "Outputs length:" << outputs.length(); QString newID = outputs.at(0); + qDebug() << "New ID:" << newID; + qDebug() << "Old ID:" << oldID; if (newID == oldID) { @@ -422,6 +455,7 @@ void MainWindowController::launchLinuxUdevWriter() } QString newExitCode = outputs.at(1); + qDebug() << "New exit code:" << newExitCode; if (newExitCode == exitOK) { @@ -439,6 +473,8 @@ void MainWindowController::launchLinuxUdevWriter() } else if (newExitCode == exitKeyboardsReadFailed) { + qCritical() << "Failed to read keyboards information"; + emit loadEnhancedDialog(EnhancedDialog { tr("Error"), tr("Failed to read keyboards information") @@ -446,6 +482,8 @@ void MainWindowController::launchLinuxUdevWriter() } else if (newExitCode == exitRuleWriteFailed) { + qCritical() << "Malformed output from udev writer"; + emit loadEnhancedDialog(EnhancedDialog { tr("Error"), tr("Malformed output from udev writer.") @@ -453,6 +491,8 @@ void MainWindowController::launchLinuxUdevWriter() } else { + qCritical() << "Malformed exit code from udev writer"; + emit loadEnhancedDialog(EnhancedDialog { tr("Error"), tr("Malformed exit code from udev writer.") @@ -465,6 +505,8 @@ void MainWindowController::launchLinuxUdevWriter() setLinuxUdevPopupProceedButtonEnabled(true); + qCritical() << "Failed to start" << LINUX_TERMINAL << ". Error Code:" << error; + if (error == QProcess::FailedToStart) { emit loadEnhancedDialog(EnhancedDialog{ @@ -487,7 +529,7 @@ void MainWindowController::launchLinuxUdevWriter() QStringLiteral(LINUX_UDEV_RULE_WRITER_NAME), QStringLiteral("%1/keyboards").arg(QDir::currentPath()), QStringLiteral(LINUX_UDEV_RULES_PATH), - exitFile, exitOK, exitKeyboardsReadFailed, exitRuleWriteFailed)); + outputPath, exitOK, exitKeyboardsReadFailed, exitRuleWriteFailed)); } void MainWindowController::setLinuxUdevPopupProceedButtonEnabled(const bool &linuxUdevPopupProceedButtonEnabled) @@ -507,6 +549,8 @@ void MainWindowController::showFatalError(const QString& title, const QString& m { EnhancedDialog d{title, message}; + qCritical() << message; + d.setOnAccepted([this](){ setCloseToSystemTrayIcon(false); quit(); diff --git a/src/messagehandler.cpp b/src/messagehandler.cpp new file mode 100644 index 0000000..fd3232d --- /dev/null +++ b/src/messagehandler.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 Debayan Sutradhar (rnayabed) (debayansutradhar3@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "messagehandler.h" + +#include +#include + +using namespace Qt::Literals::StringLiterals; + +bool MessageHandler::init() +{ + return m_logFile.open(QIODevice::WriteOnly); +} + +void MessageHandler::close() +{ + qInfo() << "Exit"; + + m_logFile.close(); +} + +void MessageHandler::handler(QtMsgType messageType, const QMessageLogContext &context, const QString &message) +{ + Q_UNUSED(context) + + if (messageType == QtDebugMsg && DISABLE_QDEBUG) + return; + + m_logStream << QDateTime::currentDateTime().toString(u"[dd/MM/yyyy] [hh:mm:ss] "_s); + + switch (messageType) + { + case QtInfoMsg: + m_logStream << u"[INFO] : "_s; + break; + case QtDebugMsg: + m_logStream << u"[DEBUG] : "_s; + break; + case QtWarningMsg: + m_logStream << u"[WARNING] : "_s; + break; + case QtCriticalMsg: + m_logStream << u"[CRITICAL] : "_s; + break; + case QtFatalMsg: + m_logStream << u"[FATAL] : "_s; + break; + } + + m_logStream << message << Qt::endl; + m_stdStream << message << Qt::endl; +} diff --git a/src/messagehandler.h b/src/messagehandler.h new file mode 100644 index 0000000..968d4c3 --- /dev/null +++ b/src/messagehandler.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 Debayan Sutradhar (rnayabed) (debayansutradhar3@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef MESSAGEHANDLER_H +#define MESSAGEHANDLER_H + +#include +#include +#include + +#include + +class MessageHandler +{ +public: + MessageHandler() = delete; + + static bool init(); + static void close(); + static void handler(QtMsgType messageType, + const QMessageLogContext &context, + const QString &message); + +private: + inline static QFile m_logFile{QStringLiteral("%1/rangoli.log") + .arg(QDir::homePath())}; + + inline static QTextStream m_logStream{&m_logFile}; + inline static QTextStream m_stdStream{stdout}; +}; + + +#endif // MESSAGEHANDLER_H diff --git a/src/profilemodel.cpp b/src/profilemodel.cpp index 8ac1ae9..73fe1ea 100644 --- a/src/profilemodel.cpp +++ b/src/profilemodel.cpp @@ -49,7 +49,6 @@ QVariant ProfileModel::data(const QModelIndex &index, int role) const return m_profiles.at(index.row()).name; } - return QVariant(); } @@ -76,6 +75,7 @@ bool ProfileModel::setData(const QModelIndex &index, const QVariant &value, int int ProfileModel::createNewProfile(const QString& name) { + qInfo() << "Create profile" << name; QSettings settings; settings.beginGroup(u"profiles"_s); @@ -96,10 +96,11 @@ int ProfileModel::createNewProfile(const QString& name) void ProfileModel::setProfileName(const qsizetype &row, const QString &name) { + qInfo() << "Change profile" << row << "name to" << name; + setData(index(row, 0), name, ProfileModel::NameRole); QSettings settings; - settings.beginGroup(u"profiles"_s); const Profile& p = m_profiles.at(row); @@ -110,10 +111,13 @@ void ProfileModel::setProfileName(const qsizetype &row, const QString &name) void ProfileModel::deleteProfile(const qsizetype &row) { + const Profile& profile = m_profiles.at(row); + + qInfo() << "Delete profile" << profile.name << "(" << profile.id <<")"; QSettings settings; settings.beginGroup(u"profiles"_s); - settings.remove(m_profiles.at(row).id); + settings.remove(profile.id); settings.endGroup(); beginRemoveRows(QModelIndex(), row, row); @@ -125,7 +129,6 @@ void ProfileModel::deleteProfile(const qsizetype &row) m_defaultProfileIndex--; emit defaultProfileIndexChanged(); } - } QHash ProfileModel::roleNames() const @@ -145,6 +148,8 @@ int& ProfileModel::defaultProfileIndex() void ProfileModel::registerProfiles() { + qInfo() << "Register profiles"; + QSettings settings; m_defaultProfileIndex = 0; @@ -172,9 +177,9 @@ void ProfileModel::registerProfiles() } } - if (m_profiles.size() == 0) { + qInfo() << "No profiles found. Create default profile"; createNewProfile(tr("Default Profile")); } diff --git a/src/settingscontroller.cpp b/src/settingscontroller.cpp index 8b0a2e5..1353a01 100644 --- a/src/settingscontroller.cpp +++ b/src/settingscontroller.cpp @@ -29,7 +29,7 @@ SettingsController::SettingsController(QObject *parent) m_alwaysShowSystemTrayIcon{false}, m_closeToSystemTrayIcon{false}, m_selectedDefaultProfileIndex{0}, - m_unsavedChanges{false}, + m_unsavedChanges{true}, m_checkForUpdatesQuietMode{false}, m_checkForUpdatesButtonEnabled{true} {} @@ -93,6 +93,8 @@ bool SettingsController::udevRulesWritten() void SettingsController::setUdevRulesWritten(const bool& written) { + qInfo() << "Set udev_rules_written to" << written << "for version" << VERSION; + QSettings settings; settings.remove(u"udev_rules_written"_s); settings.setValue(QStringLiteral("udev_rules_written/%1").arg(QString::number(VERSION)), written); @@ -106,6 +108,8 @@ bool SettingsController::firstTimeUse() void SettingsController::setFirstTimeUse(const bool &firstTimeUse) { + qInfo() << "Set first_time_use to" << firstTimeUse; + QSettings settings; settings.setValue(u"first_time_use"_s, firstTimeUse); } @@ -157,6 +161,7 @@ void SettingsController::init() }); load(); + applyVisualSettings(); } void SettingsController::setSelectedThemeIndex(const int &selectedThemeIndex) @@ -268,10 +273,15 @@ void SettingsController::emailAuthor() void SettingsController::load() { + qInfo() << "Load settings"; + QSettings settings; setSelectedThemeIndex(settings.value(u"theme"_s, MainWindowController::Theme::System).toInt()); - setAccentColour(settings.value(u"accent_colour"_s, QColor(DEFAULT_ACCENT_RED, DEFAULT_ACCENT_GREEN, DEFAULT_ACCENT_BLUE)).value()); + setAccentColour(settings.value(u"accent_colour"_s, QColor( + DEFAULT_ACCENT_RED, + DEFAULT_ACCENT_GREEN, + DEFAULT_ACCENT_BLUE)).value()); setSelectedDefaultProfileIndex(m_profiles->defaultProfileIndex()); setStartOnBoot(settings.value(u"start_on_boot"_s, false).toBool()); @@ -281,11 +291,12 @@ void SettingsController::load() setCloseToSystemTrayIcon(settings.value(u"system_tray_icon/close_to"_s, true).toBool()); setUnsavedChanges(false); - applyVisualSettings(); } void SettingsController::save() { + qInfo() << "Save settings"; + QSettings settings; settings.setValue(u"theme"_s, m_selectedThemeIndex); @@ -339,6 +350,9 @@ void SettingsController::save() void SettingsController::checkForUpdates(const bool& quiet) { + qInfo() << "Check for updates"; + qDebug() << "quiet:" << quiet; + setCheckForUpdatesButtonEnabled(false); m_checkForUpdatesQuietMode = quiet; @@ -362,6 +376,7 @@ void SettingsController::updatesFetched(QNetworkReply *reply) if (reply->error() != QNetworkReply::NoError) { + qCritical() << "Failed to retrieve updates. Error: " << reply->errorString(); if (!m_checkForUpdatesQuietMode) { emit m_mainWindow->loadEnhancedDialog(EnhancedDialog{ @@ -384,11 +399,15 @@ void SettingsController::updatesFetched(QNetworkReply *reply) if (!obj["prerelease"].toBool() && !obj["draft"].toBool()) { - QString tagName = obj["tag_name"].toString(); + QString tag = obj["tag_name"].toString(); + qDebug() << "Tag found" << tag; + bool ok; - float version = tagName.toFloat(&ok); + float version = tag.toFloat(&ok); if (ok && version > VERSION) { + qInfo() << "Update found"; + EnhancedDialog d{ tr("Update available"), tr("Version %1 is available for download. Open release page?").arg(version), @@ -407,6 +426,10 @@ void SettingsController::updatesFetched(QNetworkReply *reply) break; } + else if(!ok) + { + qDebug() << "Failed to convert tag to version. Ignore"; + } } } @@ -423,6 +446,8 @@ void SettingsController::updatesFetched(QNetworkReply *reply) void SettingsController::applyVisualSettings() { + qDebug() << "Apply visual settings to Main Window"; + emit m_mainWindow->setAccentColour(m_accentColour); m_mainWindow->setTheme(m_selectedThemeIndex); m_mainWindow->setAlwaysShowSystemTrayIcon(m_alwaysShowSystemTrayIcon); diff --git a/src/startatboot.cpp b/src/startatboot.cpp index 059b30c..5fd4bc3 100644 --- a/src/startatboot.cpp +++ b/src/startatboot.cpp @@ -22,18 +22,28 @@ using namespace Qt::Literals::StringLiterals; bool StartAtBoot::createStarter() { + qInfo() << "Create starter"; + #if defined(Q_OS_LINUX) QDir serviceDir{QStringLiteral("%1/.local/share/systemd/user/").arg(QDir::homePath())}; + qInfo() << "systemd services path:" << serviceDir.absolutePath(); + if (!serviceDir.exists()) { + qInfo() << "Create path because it does not exist"; if (!serviceDir.mkpath(".")) { + qCritical() << "Failed to create systemd service file path"; return false; } } - QFile service{serviceDir.absoluteFilePath(u"rangoli.service"_s)}; + QString servicePath = serviceDir.absoluteFilePath(u"rangoli.service"_s); + + qInfo() << "Create service" << servicePath; + + QFile service{servicePath}; if (service.open(QIODevice::WriteOnly)) { @@ -51,6 +61,8 @@ bool StartAtBoot::createStarter() service.close(); + qInfo() << "Refresh systemd"; + QPointer daemonReload{new QProcess}; QObject::connect(daemonReload, &QProcess::finished, StartAtBoot::linuxSystemDDaemonReloadFinished); QObject::connect(daemonReload, &QProcess::finished, daemonReload, &QProcess::deleteLater); @@ -61,10 +73,15 @@ bool StartAtBoot::createStarter() } else { + qCritical() << "Failed to create systemd service"; return false; } + #elif defined(Q_OS_WIN) - QFile starter{QStringLiteral("%1/Microsoft/Windows/Start Menu/Programs/Startup/rangoli.vbs").arg(qgetenv("APPDATA"))}; + QString starterPath{QStringLiteral("%1/Microsoft/Windows/Start Menu/Programs/Startup/rangoli.vbs").arg(qgetenv("APPDATA"))}; + QFile starter{starterPath}; + + qInfo() << "Create script" << starterPath; if (starter.open(QIODevice::WriteOnly)) { @@ -78,13 +95,17 @@ bool StartAtBoot::createStarter() } else { + qCritical() << "Failed to create script"; return false; } -#elif defined(Q_OS_MACOS) - QString plistPath{QStringLiteral("%1/Library/LaunchAgents/io.github.rnayabed.rangoli.plist").arg(QDir::homePath())}; +#elif defined(Q_OS_MACOS) + QString plistPath{QStringLiteral("%1/Library/LaunchAgents/%2.plist") + .arg(QDir::homePath(), MACOSX_BUNDLE_GUI_IDENTIFIER)}; QFile plist{plistPath}; + qInfo() << "Create plist" << plistPath; + if (plist.open(QIODevice::WriteOnly)) { QTextStream ts{&plist}; @@ -94,7 +115,7 @@ bool StartAtBoot::createStarter() "\n" " \n" " Label\n" - " io.github.rnayabed.rangoli\n" + " "_s<< MACOSX_BUNDLE_GUI_IDENTIFIER << u"\n" " Program\n" " "_s << QCoreApplication::arguments().at(0) << u"\n" " ProgramArguments\n" @@ -106,6 +127,8 @@ bool StartAtBoot::createStarter() plist.close(); + qInfo() << "Load plist"; + QPointer load{new QProcess}; QObject::connect(load, &QProcess::finished, StartAtBoot::macOSLaunchCtlLoadFinished); QObject::connect(load, &QProcess::finished, load, &QProcess::deleteLater); @@ -115,6 +138,7 @@ bool StartAtBoot::createStarter() } else { + qCritical() << "Failed to create plist"; return false; } #endif @@ -123,23 +147,47 @@ bool StartAtBoot::createStarter() bool StartAtBoot::deleteStarter() { + qInfo() << "Delete starter"; + #if defined(Q_OS_LINUX) - bool result = QFile{QStringLiteral("%1/.local/share/systemd/user/rangoli.service").arg(QDir::homePath())}.remove(); + QString servicePath{QStringLiteral("%1/.local/share/systemd/user/rangoli.service").arg(QDir::homePath())}; + bool result = QFile{servicePath}.remove(); + + if (!result) + { + qInfo() << "Failed to delete service" << servicePath; + } + + qInfo() << "Refresh systemd"; QPointer systemDReload{new QProcess}; QObject::connect(systemDReload, &QProcess::finished, systemDReload, &QProcess::deleteLater); systemDReload->start(u"systemctl --user daemon-reload"_s); return result; + #elif defined(Q_OS_WIN) - QFile starter{QStringLiteral("%1/Microsoft/Windows/Start Menu/Programs/Startup/rangoli.vbs").arg(qgetenv("APPDATA"))}; + QString starterPath{QStringLiteral("%1/Microsoft/Windows/Start Menu/Programs/Startup/rangoli.vbs").arg(qgetenv("APPDATA"))}; + bool result = QFile{starterPath}.remove(); + + if (!result) + { + qInfo() << "Failed to delete script" << starterPath; + } + + return result; - return starter.remove(); #elif defined(Q_OS_MACOS) - QString plistPath{QStringLiteral("%1/Library/LaunchAgents/io.github.rnayabed.rangoli.plist").arg(QDir::homePath())}; + QString plistPath{QStringLiteral("%1/Library/LaunchAgents/%2.plist") + .arg(QDir::homePath(), MACOSX_BUNDLE_GUI_IDENTIFIER)}; bool result = QFile{plistPath}.remove(); + if (!result) + { + qInfo() << "Failed to delete plist" << plistPath; + } + QPointer unload{new QProcess}; QObject::connect(unload, &QProcess::finished, unload, &QProcess::deleteLater); unload->start(QStringLiteral("launchctl unload -w '%1'").arg(plistPath)); @@ -154,6 +202,8 @@ void StartAtBoot::linuxSystemDDaemonReloadFinished(int exitCode, QProcess::ExitS Q_UNUSED(exitCode) Q_UNUSED(exitStatus) + qInfo() << "Enable systemd service"; + QPointer enableService{new QProcess}; QObject::connect(enableService, &QProcess::finished, enableService, &QProcess::deleteLater); enableService->start(u"systemctl --user enable rangoli.service"_s); @@ -166,5 +216,5 @@ void StartAtBoot::macOSLaunchCtlLoadFinished(int exitCode, QProcess::ExitStatus QPointer stop{new QProcess}; QObject::connect(stop, &QProcess::finished, stop, &QProcess::deleteLater); - stop->start(u"launchctl stop io.github.rnayabed.rangoli"_s); + stop->start(QStringLiteral("launchctl stop %1").arg(MACOSX_BUNDLE_GUI_IDENTIFIER)); } diff --git a/supported-keyboards.md b/supported-keyboards.md index 76f0458..6cb7083 100644 --- a/supported-keyboards.md +++ b/supported-keyboards.md @@ -1,6 +1,12 @@ # Supported Keyboards -Rangoli currently supports 88 keyboards. If you cannot find your keyboard in this list, please create an [issue](https://github.com/rnayabed/rangoli/issues/new) to bring it to my attention. +**Rangoli currently only supports boards with vendor ID `0x258a`.** + +It looks like the protocol used for keyboards with VID other than `0x258a` is totally different. Thankfully, for `0x0c45` boards, the reporter of that [issue](https://github.com/rnayabed/rangoli/issues/13) has provided packet captures with detailed context, so you are free to reverse engineer the protocol yourself. At the time of writing this, I really find myself unmotivated to work on it especially because I find it much more obfuscated than the protocol used for `0x258` boards. Thankfully, a vast majority of the models in the market are `0x258` protocol based and Rangoli supports most of the RK keyboards in the market. + +Note that some keyboards have similar names but [totally different Vendor and Product IDs](https://github.com/rnayabed/rangoli/issues/14). + +If you cannot find your keyboard in this list, or it is listed here yet you are still unable to configure it, please create an [issue](https://github.com/rnayabed/rangoli/issues/new) to bring it to my attention. | Name | PID | | ------------------------------ | ---- |