From 28f2e85802af777ce46d75127a2e98a69870bb88 Mon Sep 17 00:00:00 2001 From: consti10 Date: Mon, 12 Feb 2024 15:07:03 +0100 Subject: [PATCH] add joystick navigation to sidebar --- qml/qml.qrc | 1 + qml/ui/HUDOverlayGrid.qml | 2 +- qml/ui/sidebar/BaseJoyEditElement.qml | 14 +- qml/ui/sidebar/Panel1Link.qml | 98 +++--------- qml/ui/sidebar/Panel2Video.qml | 10 ++ qml/ui/sidebar/Panel3Camera.qml | 34 +++- qml/ui/sidebar/Panel4Recording.qml | 12 +- qml/ui/sidebar/Panel5RC.qml | 12 +- qml/ui/sidebar/Panel6Misc.qml | 19 ++- qml/ui/sidebar/Panel7Status.qml | 1 - qml/ui/sidebar/SideBarMain.qml | 220 ++++++++++++-------------- qml/ui/sidebar/SidebarStackButton.qml | 89 +++++++++++ 12 files changed, 314 insertions(+), 198 deletions(-) create mode 100644 qml/ui/sidebar/SidebarStackButton.qml diff --git a/qml/qml.qrc b/qml/qml.qrc index b88204cd8..a18720fb9 100644 --- a/qml/qml.qrc +++ b/qml/qml.qrc @@ -298,5 +298,6 @@ ui/sidebar/Panel4Recording.qml ui/sidebar/Panel6Misc.qml ui/sidebar/Panel7Status.qml + ui/sidebar/SidebarStackButton.qml diff --git a/qml/ui/HUDOverlayGrid.qml b/qml/ui/HUDOverlayGrid.qml index 677f0fce9..27f1d828d 100644 --- a/qml/ui/HUDOverlayGrid.qml +++ b/qml/ui/HUDOverlayGrid.qml @@ -208,7 +208,7 @@ Item { if(event.key==Qt.Key_Left || event.key == Qt.Key_Right || event.key == Qt.Key_Up || event.key == Qt.Key_Down){ // If the user presses any navigation key, we open up the sidebar and hand over the inputs to it if(!sidebar.m_extra_is_visible){ - sidebar.open_and_take_control(); + sidebar.open_and_take_control(true); event.accepted=true; } } diff --git a/qml/ui/sidebar/BaseJoyEditElement.qml b/qml/ui/sidebar/BaseJoyEditElement.qml index fe2a8510c..b908ba265 100644 --- a/qml/ui/sidebar/BaseJoyEditElement.qml +++ b/qml/ui/sidebar/BaseJoyEditElement.qml @@ -44,6 +44,10 @@ Item{ // Emitted if the button right is clicked signal choice_right(); + // Emitted if the button up is clicked (navigate to previous eelement) + signal goto_previous(); + signal goto_next(); + Keys.onPressed: (event)=> { console.log("BaseJoyElement"+m_title+" key was pressed:"+event); if(event.key == Qt.Key_Left){ @@ -58,13 +62,21 @@ Item{ }else{ _qopenhd.show_toast("NOT AVAILABLE"); } + }else if(event.key==Qt.Key_Up){ + goto_previous() + }else if(event.key==Qt.Key_Down){ + goto_next(); } } + function takeover_control(){ + focus=true; + } + Rectangle{ width: parent.width height:parent.height - border.color: "black" + border.color: "white" border.width: base_joy_edit_element.focus ? 3 : 0; color: "#333c4c" opacity: base_joy_edit_element.focus ? 1.0 : 0.3; diff --git a/qml/ui/sidebar/Panel1Link.qml b/qml/ui/sidebar/Panel1Link.qml index cc2584b44..832be6200 100644 --- a/qml/ui/sidebar/Panel1Link.qml +++ b/qml/ui/sidebar/Panel1Link.qml @@ -3,6 +3,11 @@ import QtQuick 2.0 SideBarBasePanel{ override_title: "Link" + + function takeover_control(){ + edit_frequency_element.takeover_control(); + } + Column { anchors.top: parent.top anchors.topMargin: secondaryUiHeight/8 @@ -10,91 +15,32 @@ SideBarBasePanel{ EditFrequencyElement{ id: edit_frequency_element + onGoto_previous: { + sidebar.regain_control_on_sidebar_stack() + } + onGoto_next: { + edit_channel_width_element.takeover_control() + } } EditChannelWidthElement{ id: edit_channel_width_element + onGoto_previous: { + edit_frequency_element.takeover_control(); + } + onGoto_next: { + edit_rate_element.takeover_control() + } } EditRateElement{ id: edit_rate_element - } - - /*Text{ - text: "Range -> Quality" + " (MCS" + _ohdSystemAir.curr_mcs_index + ")" - font.pixelSize: 14 - font.family: "AvantGarde-Medium" - color: "#ffffff" - smooth: true + onGoto_previous: { + edit_channel_width_element.takeover_control() } - Slider { - id: valueSlider - from: 0 - to: 3 - stepSize: 1 - //snapMode: Slider.SnapToStep - value: 0 // Initial value - Material.accent: Material.Grey - onValueChanged: { - // Handle the slider value change here - console.log("MCS Slider:", value) - } + onGoto_next: { + sidebar.regain_control_on_sidebar_stack() } - Text{ - text: "Frequency" + " (" + _ohdSystemGround.curr_channel_mhz + ")" - font.pixelSize: 14 - font.family: "AvantGarde-Medium" - color: "#ffffff" - smooth: true - } - ComboBox { - width: 200 - model: [ "2312", "2332", "2352", "2372", "2392", "2412", "2432", "2452", "2472", "2492", "2512", "2532", "2572", "2592", "2612", "2632", "2652", "2672", "2692", "2712", "5180", "5200", "5220", "5240", "5260", "5280", "5300", "5320", "5500", "5520", "5540", "5560", "5580", "5600", "5620", "5640", "5660", "5680", "5700", "5745", "5765", "5785", "5805", "5825", "5845", "5865", "5885" ] - } - Text{ - text: "TX Power Air" + " (" + "TODO" + ")" - font.pixelSize: 14 - font.family: "AvantGarde-Medium" - color: "#ffffff" - smooth: true - } - Slider { - id: txPowerAirSlider - from: 22 - to: 58 - stepSize: 4 - //snapMode: Slider.SnapToStep - value: 22 // Initial value - Material.accent: Material.Grey - onValueChanged: { - // Handle the slider value change here - console.log("TX Power Air Slider:", value) - } - } - Text{ - text: "Bandwith" - font.pixelSize: 14 - font.family: "AvantGarde-Medium" - color: "#ffffff" - smooth: true - } - TabBar { - id: control - Material.accent: "#fff" - Material.foreground: "white" - background: Rectangle { - implicitWidth: 100 - implicitHeight: 40 - color: secondaryUiColor - } - TabButton { - text: qsTr("20MHZ") - } - TabButton { - text: qsTr("40MHZ") - } - }*/ - + } } - } diff --git a/qml/ui/sidebar/Panel2Video.qml b/qml/ui/sidebar/Panel2Video.qml index 07356f105..f22537177 100644 --- a/qml/ui/sidebar/Panel2Video.qml +++ b/qml/ui/sidebar/Panel2Video.qml @@ -14,6 +14,10 @@ import "../elements" SideBarBasePanel{ override_title: "Video" + function takeover_control(){ + edit_resolution_element.takeover_control(); + } + Column { anchors.top: parent.top anchors.topMargin: secondaryUiHeight/8 @@ -21,6 +25,12 @@ SideBarBasePanel{ EditResolutionElement{ id: edit_resolution_element + onGoto_previous: { + sidebar.regain_control_on_sidebar_stack() + } + onGoto_next: { + sidebar.regain_control_on_sidebar_stack() + } } /*ComboBox { diff --git a/qml/ui/sidebar/Panel3Camera.qml b/qml/ui/sidebar/Panel3Camera.qml index 734288657..1afe9c1d2 100644 --- a/qml/ui/sidebar/Panel3Camera.qml +++ b/qml/ui/sidebar/Panel3Camera.qml @@ -12,31 +12,63 @@ import OpenHD 1.0 import "../elements" SideBarBasePanel{ - id: cameraUI override_title: "Camera" + + function takeover_control(){ + brightness.takeover_control(); + } + Column { anchors.top: parent.top anchors.topMargin: secondaryUiHeight/8 spacing: 5 MavlinkIntChoiceElement{ + id: brightness m_title: "BRIGHTNESS" m_param_id: "BRIGHTNESS" m_settings_model: _airCameraSettingsModel + onGoto_previous: { + sidebar.regain_control_on_sidebar_stack() + } + onGoto_next: { + saturation.takeover_control(); + } } MavlinkIntChoiceElement{ + id: saturation m_title: "SATURATION" m_param_id: "SATURATION" m_settings_model: _airCameraSettingsModel + onGoto_previous: { + brightness.takeover_control(); + } + onGoto_next: { + contrast.takeover_control(); + } } MavlinkIntChoiceElement{ + id: contrast m_title: "CONTRAST" m_param_id: "CONTRAST" m_settings_model: _airCameraSettingsModel + onGoto_previous: { + saturation.takeover_control(); + } + onGoto_next: { + sharpness.takeover_control(); + } } MavlinkIntChoiceElement{ + id: sharpness m_title: "SHARPNESS" m_param_id: "SHARPNESS" m_settings_model: _airCameraSettingsModel + onGoto_previous: { + contrast.takeover_control(); + } + onGoto_next: { + sidebar.regain_control_on_sidebar_stack() + } } } } diff --git a/qml/ui/sidebar/Panel4Recording.qml b/qml/ui/sidebar/Panel4Recording.qml index 1b8dd955f..fa8f814f0 100644 --- a/qml/ui/sidebar/Panel4Recording.qml +++ b/qml/ui/sidebar/Panel4Recording.qml @@ -12,18 +12,28 @@ import OpenHD 1.0 import "../elements" SideBarBasePanel{ - id: recordingUI override_title: "Air recording" + function takeover_control(){ + recording_mode.takeover_control(); + } + Column { anchors.top: parent.top anchors.topMargin: secondaryUiHeight/8 spacing: 5 MavlinkIntChoiceElement{ + id: recording_mode m_title: "RECORDING MODE" m_param_id: "AIR_RECORDING_E" m_settings_model: _airCameraSettingsModel + onGoto_previous: { + sidebar.regain_control_on_sidebar_stack() + } + onGoto_next: { + // Do nothing + } } Text{ text: { diff --git a/qml/ui/sidebar/Panel5RC.qml b/qml/ui/sidebar/Panel5RC.qml index 8fe7f4458..c8ceb505e 100644 --- a/qml/ui/sidebar/Panel5RC.qml +++ b/qml/ui/sidebar/Panel5RC.qml @@ -12,9 +12,12 @@ import OpenHD 1.0 import "../elements" SideBarBasePanel{ - id: displayUI override_title: "OpenHD RC" + function takeover_control(){ + joy_rc_enable.takeover_control(); + } + property int m_control_yaw : settings.control_widget_use_fc_channels ? _rcchannelsmodelfc.control_yaw : _rcchannelsmodelground.control_yaw property int m_control_roll: settings.control_widget_use_fc_channels ? _rcchannelsmodelfc.control_roll : _rcchannelsmodelground.control_roll property int m_control_pitch: settings.control_widget_use_fc_channels ? _rcchannelsmodelfc.control_pitch : _rcchannelsmodelground.control_pitch @@ -27,9 +30,16 @@ SideBarBasePanel{ MavlinkIntChoiceElement{ + id: joy_rc_enable m_title: "JOY RC" m_param_id: "ENABLE_JOY_RC"; m_settings_model: _ohdSystemGroundSettings + onGoto_previous: { + sidebar.regain_control_on_sidebar_stack() + } + onGoto_next: { + sidebar.regain_control_on_sidebar_stack() + } } Text{ diff --git a/qml/ui/sidebar/Panel6Misc.qml b/qml/ui/sidebar/Panel6Misc.qml index d012ea240..9bcd70543 100644 --- a/qml/ui/sidebar/Panel6Misc.qml +++ b/qml/ui/sidebar/Panel6Misc.qml @@ -12,22 +12,39 @@ import OpenHD 1.0 import "../elements" SideBarBasePanel{ - id: displayUI override_title: "Misc" + function takeover_control(){ + air_wifi_hs.takeover_control(); + } + Column { anchors.top: parent.top anchors.topMargin: secondaryUiHeight/8 spacing: 5 MavlinkIntChoiceElement{ + id: air_wifi_hs m_title: "AIR WIFI HS" m_param_id: "WIFI_HOTSPOT_E" m_settings_model: _ohdSystemAirSettingsModel + onGoto_previous: { + sidebar.regain_control_on_sidebar_stack() + } + onGoto_next: { + gnd_wifi_hs.takeover_control(); + } } MavlinkIntChoiceElement{ + id: gnd_wifi_hs m_title: "GND WIFI HS" m_param_id: "WIFI_HOTSPOT_E" m_settings_model: _ohdSystemGroundSettings + onGoto_previous: { + air_wifi_hs.takeover_control(); + } + onGoto_next: { + sidebar.regain_control_on_sidebar_stack() + } } } } diff --git a/qml/ui/sidebar/Panel7Status.qml b/qml/ui/sidebar/Panel7Status.qml index 684ee03c5..1d9f7d499 100644 --- a/qml/ui/sidebar/Panel7Status.qml +++ b/qml/ui/sidebar/Panel7Status.qml @@ -12,7 +12,6 @@ import OpenHD 1.0 import "../elements" SideBarBasePanel{ - id: miscUI override_title: "Status / Advanced" Column { diff --git a/qml/ui/sidebar/SideBarMain.qml b/qml/ui/sidebar/SideBarMain.qml index d1f599600..4ed5474d4 100644 --- a/qml/ui/sidebar/SideBarMain.qml +++ b/qml/ui/sidebar/SideBarMain.qml @@ -37,25 +37,27 @@ Item { // Gives (keyboard / joystick) control to this element - function open_and_take_control(){ + function open_and_take_control(enable_joy){ m_extra_is_visible=true; m_stack_index=0; m_is_active = true - hudOverlayGrid.focus=false; - focus=true; - stack_manager.focus=true; + stack_manager.visible=true; + if(enable_joy){ + hudOverlayGrid.focus=false; + handover_joystick_control_to_button(m_stack_index); + } } // This is called whenever the user clicks on the 'WBLIink' widget function open_link_category(){ - open_and_take_control(); + open_and_take_control(false); m_stack_index=0; } // This is called when the user clicks on the configure button of the CAM1 / CAM2 widget function open_video_stream_category(is_primary){ if(is_primary){ - open_and_take_control(); + open_and_take_control(false); m_stack_index=3; } } @@ -65,9 +67,48 @@ Item { m_stack_index=-1; m_is_active=false; m_extra_is_visible=false; + stack_manager.visible=false; hudOverlayGrid.focus=true; } + function regain_control_on_sidebar_stack(){ + handover_joystick_control_to_button(m_stack_index); + } + + function handover_joystick_control_to_button(stack_index){ + if(stack_index==0){ + b1.takeover_control(); + }else if(stack_index==1){ + b2.takeover_control(); + }else if(stack_index==2){ + b3.takeover_control(); + }else if(stack_index==3){ + b4.takeover_control(); + }else if(stack_index==4){ + b5.takeover_control(); + }else if(stack_index==5){ + b6.takeover_control(); + }else if(stack_index==6){ + b7.takeover_control(); + } + } + + function handover_joystick_control_to_panel(stack_index){ + if(stack_index==0){ + panel1.takeover_control(); + }else if(stack_index==1){ + panel2.takeover_control(); + }else if(stack_index==2){ + panel3.takeover_control(); + }else if(stack_index==3){ + panel4.takeover_control(); + }else if(stack_index==4){ + panel5.takeover_control(); + }else if(stack_index==5){ + panel6.takeover_control(); + } + } + // Item that opens up the sidebar Item { @@ -102,120 +143,62 @@ Item { } } - - // Item that manages the stack on the right - Rectangle{ - id: stack_manager + Column{ anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - width: secondaryUiHeight / 8 //number of items - height: secondaryUiHeight - color: highlightColor - opacity: 0.7 - visible: m_stack_index!=-1; - - Keys.onPressed: (event)=> { - console.log("stack_manager"+" key was pressed:"+event); - if(event.key === Qt.Key_Up){ - m_stack_index--; - if(m_stack_index<-1){ - m_stack_index=-1; - } - return true; - }else if(event.key === Qt.Key_Down){ - m_stack_index++; - if(m_stack_index>6){ - m_stack_index=6; - } - return true; - } - return false; - } - - ListView { - width: parent.width - height: parent.height - focus: true - keyNavigationEnabled: true - interactive: false - - model: ListModel { - ListElement { text: " \uf053"; subText: "back" } - ListElement { text: " \uf1eb"; subText: "link" } - ListElement { text: " \uf03d"; subText: "video" } - ListElement { text: " \uf030"; subText: "camera" } - ListElement { text: " \uf0c7"; subText: "recording" } - ListElement { text: " \uf11b"; subText: "rc" } - ListElement { text: " \uf26c"; subText: "misc" } - ListElement { text: " \uf55b"; subText: "status" } - } - - delegate: Item { - width: parent.width - height: secondaryUiHeight / 8 //number of items - - MouseArea { - id: mouseArea - anchors.fill: parent - - onClicked: { - // Update the selected item index - console.log("Item clicked: " + model.subText) - var uiElementName = model.subText + "UI"; - if (model.subText === "back") { - close(); - } else if (model.subText === "link") { - m_stack_index=0; - } else if (model.subText === "video") { - m_stack_index=1; - } else if (model.subText === "camera") { - m_stack_index=2; - } else if (model.subText === "recording") { - m_stack_index=3; - } else if (model.subText === "rc") { - m_stack_index=4; - } else if (model.subText === "misc") { - m_stack_index=5; - } else if (model.subText === "status") { - m_stack_index=6; - } - } - - Rectangle { - width: parent.width - height: parent.height - color: index-1 === m_stack_index ? highlightColor : mainDarkColor - } - - RowLayout { - width: parent.width - height: parent.height - - Text { - text: model.text - font.pixelSize: secondaryUiHeight / 16 - opacity: 1.0 - font.family: "Font Awesome 5 Free" - color: "white" - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - Text { - text: model.subText - visible: false - font.pixelSize: secondaryUiHeight / 16 - opacity: 1.0 - color: "white" - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight - } - } - } - } + id: stack_manager + visible: false + SidebarStackButton{ + id: b0 + override_text: "\uf053" + override_tag: "back" + override_index: -1 + } + SidebarStackButton{ + id: b1 + override_text: "\uf1eb" + override_tag: "link" + override_index: 0 + } + SidebarStackButton{ + id: b2 + override_text: "\uf03d" + override_tag: "video" + override_index: 1 + } + SidebarStackButton{ + id: b3 + override_text: "\uf030" + override_tag: "camera" + override_index: 2 + } + SidebarStackButton{ + id: b4 + override_text: "\uf0c7" + override_tag: "recording" + override_index: 3 + } + SidebarStackButton{ + id: b5 + override_text: "\uf11b" + override_tag: "rc" + override_index: 4 + } + SidebarStackButton{ + id: b6 + override_text: "\uf26c" + override_tag: "misc" + override_index: 5 + } + SidebarStackButton{ + id: b7 + override_text: "\uf55b" + override_tag: "status" + override_index: 6 } } + Item{ width: secondaryUiWidth height: secondaryUiHeight @@ -223,27 +206,34 @@ Item { anchors.top: stack_manager.top Panel1Link{ + id: panel1 visible: m_stack_index==0; } Panel2Video{ + id: panel2 visible: m_stack_index==1; } Panel3Camera{ + id: panel3 visible: m_stack_index==2; } Panel4Recording{ + id: panel4 visible: m_stack_index==3; } Panel5RC{ + id: panel5 visible: m_stack_index==4; } Panel6Misc{ + id: panel6 visible: m_stack_index==5; } Panel7Status{ + id: panel7 visible: m_stack_index==6; } } diff --git a/qml/ui/sidebar/SidebarStackButton.qml b/qml/ui/sidebar/SidebarStackButton.qml new file mode 100644 index 000000000..fe40850dc --- /dev/null +++ b/qml/ui/sidebar/SidebarStackButton.qml @@ -0,0 +1,89 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.12 +import QtGraphicalEffects 1.12 +import QtQuick.Shapes 1.0 +import QtQuick.Controls.Material 2.0 + +import Qt.labs.settings 1.0 + +import OpenHD 1.0 + +import "../elements" + +// +// Joystick controllable (override the events) +// +Item { + id: sidebar_stack_button + height: secondaryUiHeight / 8 //number of items + width: height + + property string override_text: "OVERRIDE ME" + property string override_tag: "OVERRIDE ME" + property int override_index: -100; + + + function takeover_control(){ + focus=true; + } + + + // Background + Rectangle{ + width: parent.width + height: parent.height + color: (mouseArea.containsMouse || m_stack_index==override_index) ? highlightColor : mainDarkColor + border.color: "white" + border.width: sidebar_stack_button.focus ? 3 : 0; + } + // Icon + Text { + anchors.fill: parent + text: override_text + font.pixelSize: secondaryUiHeight / 16 + opacity: 1.0 + font.family: "Font Awesome 5 Free" + color: "white" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: { + console.log("Item clicked: " + override_tag) + if(override_index<0){ + // close the sidebar + sidebar.close(); + }else{ + sidebar.m_stack_index=override_index; + } + } + } + + Keys.onPressed: (event)=> { + console.log("SidebarStackButton"+override_tag+" key was pressed:"+event); + if(event.key === Qt.Key_Up){ + m_stack_index--; + if(m_stack_index<-1){ + m_stack_index=-1; + } + sidebar.handover_joystick_control_to_button(m_stack_index); + if(m_stack_index==-1){ + sidebar.close(); + } + event.accepted=true; + }else if(event.key === Qt.Key_Down){ + m_stack_index++; + if(m_stack_index>6){ + m_stack_index=6; + } + sidebar.handover_joystick_control_to_button(m_stack_index); + event.accepted=true; + }else if(event.key==Qt.Key_Right && focus){ + sidebar.handover_joystick_control_to_panel(sidebar.m_stack_index); + event.accepted=true; + } + } +}