diff --git a/resources/AdvancedTab.qml b/resources/AdvancedTab.qml
index 57bb02914..bc0529646 100644
--- a/resources/AdvancedTab.qml
+++ b/resources/AdvancedTab.qml
@@ -5,66 +5,34 @@ import QtQuick 2.5
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.15
-Item {
+MainTab {
id: advancedTab
- width: parent.width
- height: parent.height
+ subTabNames: ["System Monitor", "IMU", "Magnetometer", "Networking", "Spectrum Analyzer", "INS"]
+ curSubTabIndex: Globals.initialMainTabIndex == 6 ? Globals.initialSubTabIndex : 0
- TabBar {
- id: advancedBar
+ StackLayout {
+ id: advancedBarLayout
- z: Constants.commonChart.zAboveCharts
- currentIndex: Globals.initialMainTabIndex == 6 ? Globals.initialSubTabIndex : 0
- contentHeight: Constants.tabBarHeight
-
- Repeater {
- model: ["System Monitor", "IMU", "Magnetometer", "Networking", "Spectrum Analyzer", "INS"]
-
- TabButton {
- text: modelData
- width: implicitWidth
- }
+ anchors.fill: parent
+ currentIndex: curSubTabIndex
+ AdvancedTabComponents.AdvancedSystemMonitorTab {
}
- }
-
- Rectangle {
- id: advancedTabBackground
-
- width: parent.width
- height: parent.height
- anchors.top: advancedBar.bottom
- anchors.bottom: advancedTab.bottom
- Component.onCompleted: {
+ AdvancedTabComponents.AdvancedImuTab {
}
- StackLayout {
- id: advancedBarLayout
-
- width: parent.width
- height: parent.height
- currentIndex: advancedBar.currentIndex
-
- AdvancedTabComponents.AdvancedSystemMonitorTab {
- }
-
- AdvancedTabComponents.AdvancedImuTab {
- }
-
- AdvancedTabComponents.AdvancedMagnetometerTab {
- }
-
- AdvancedTabComponents.AdvancedNetworkingTab {
- }
+ AdvancedTabComponents.AdvancedMagnetometerTab {
+ }
- AdvancedTabComponents.AdvancedSpectrumAnalyzerTab {
- }
+ AdvancedTabComponents.AdvancedNetworkingTab {
+ }
- AdvancedTabComponents.AdvancedInsTab {
- }
+ AdvancedTabComponents.AdvancedSpectrumAnalyzerTab {
+ }
+ AdvancedTabComponents.AdvancedInsTab {
}
}
diff --git a/resources/BaselineTab.qml b/resources/BaselineTab.qml
index 2741f3d69..fa0fdbe22 100644
--- a/resources/BaselineTab.qml
+++ b/resources/BaselineTab.qml
@@ -5,12 +5,9 @@ import QtQuick 2.5
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
-Item {
+MainTab {
id: baselineTab
- width: parent.width
- height: parent.height
-
SplitView {
id: baselineSplitView
diff --git a/resources/Constants/Constants.qml b/resources/Constants/Constants.qml
index 84381e6ea..786540ca8 100644
--- a/resources/Constants/Constants.qml
+++ b/resources/Constants/Constants.qml
@@ -49,10 +49,11 @@ QtObject {
readonly property real smallPointSize: 7
readonly property real mediumPointSize: 8
readonly property real largePointSize: 9
+ readonly property string infoPath: "qrc:///images/fontawesome/info-circle-solid.svg"
readonly property bool debugMode: false
readonly property color swiftGrey: "#323F48"
readonly property color swiftLightGrey: "#3C464F"
- readonly property color swiftControlBackground: "#ECECEC"
+ readonly property color swiftControlBackground: "#E0E0E0"
readonly property color tabButtonUnselectedTextColor: "#767676"
readonly property color materialGrey: "dimgrey"
readonly property color swiftOrange: "#FF8300"
@@ -95,13 +96,16 @@ QtObject {
readonly property string settingsPath: "qrc:///images/fontawesome/cogs-solid.svg"
readonly property string updatePath: "qrc:///images/fontawesome/chevron-circle-up-solid.svg"
readonly property string advancedPath: "qrc:///images/fontawesome/lock-solid.svg"
- readonly property real tabBarHeight: 45
- readonly property real tabBarWidth: 50
+ readonly property real tabBarHeight: 48
+ readonly property real tabBarWidth: 62
readonly property int buttonPadding: 0
readonly property int buttonInset: 0
readonly property int separatorMargin: 10
readonly property int separatorHeight: 1
- readonly property color backgroundColor: "#fafafa"
+ readonly property color backgroundColor: swiftGrey
+ readonly property color statusGoodColor: "#07DD01"
+ readonly property color statusOkColor: "yellow"
+ readonly property color statusBadColor: "red"
}
updateTab: QtObject {
@@ -572,6 +576,7 @@ QtObject {
readonly property string solidCirclePath: "qrc:///images/fontawesome/circle-solid.svg"
readonly property string squareSolidPath: "qrc:///images/fontawesome/square-solid.svg"
readonly property string swiftLogoPath: "qrc:///images/icon.png"
+ readonly property string swiftLogoWidePath: "qrc:///images/swiftLogoWide.svg"
}
insSettingsPopup: QtObject {
diff --git a/resources/MainTab.qml b/resources/MainTab.qml
new file mode 100644
index 000000000..efecffc6d
--- /dev/null
+++ b/resources/MainTab.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.5
+
+Item {
+ property var subTabNames: []
+ property int curSubTabIndex: -1
+}
diff --git a/resources/MainTabs.qml b/resources/MainTabs.qml
index bcb9ebc44..6b8fb0cd4 100644
--- a/resources/MainTabs.qml
+++ b/resources/MainTabs.qml
@@ -4,7 +4,11 @@ import QtQuick.Layouts 1.15
import SwiftConsole 1.0
Item {
+ id: mainTabs
+
property alias currentIndex: stackLayout.currentIndex
+ property var subTabNames: mainTabs.currentIndex < 0 ? [] : stackLayout.children[stackLayout.currentIndex].subTabNames
+ property int curSubTabIndex: -1
StackLayout {
id: stackLayout
@@ -12,24 +16,31 @@ Item {
anchors.fill: parent
TrackingTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
SolutionTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
BaselineTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
ObservationTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
SettingsTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
UpdateTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
AdvancedTab {
+ curSubTabIndex: mainTabs.curSubTabIndex
}
}
diff --git a/resources/ObservationTab.qml b/resources/ObservationTab.qml
index 61686cfe3..e1206c555 100644
--- a/resources/ObservationTab.qml
+++ b/resources/ObservationTab.qml
@@ -6,12 +6,9 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import SwiftConsole 1.0
-Item {
+MainTab {
id: observationTab
- width: parent.width
- height: parent.height
-
SplitView {
id: observationView
diff --git a/resources/SettingsTab.qml b/resources/SettingsTab.qml
index 2073897a1..f1794bb47 100644
--- a/resources/SettingsTab.qml
+++ b/resources/SettingsTab.qml
@@ -1,15 +1,13 @@
import "Constants"
import Qt.labs.platform 1.1 as LabsPlatform
-import QtCharts 2.2
-import QtQuick 2.7
-import QtQuick.Controls 1.4
+import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.15
import "SettingsTabComponents" as SettingsTabComponents
import SwiftConsole 1.0
-Item {
+MainTab {
id: settingsTab
function selectedRow() {
@@ -40,9 +38,6 @@ Item {
return text;
}
- width: parent.width
- height: parent.height
-
SettingsTabData {
id: settingsTabData
}
diff --git a/resources/SideNavBar.qml b/resources/SideNavBar.qml
index 0ef266782..7f380cb90 100644
--- a/resources/SideNavBar.qml
+++ b/resources/SideNavBar.qml
@@ -9,6 +9,7 @@ Item {
id: top
property alias currentIndex: navButtons.currentIndex
+ property string currentTabName: top.currentIndex < 0 ? "" : tabModel[top.currentIndex].tooltip
property bool enabled: true
property var tabModel: [{
"name": "Tracking",
@@ -23,7 +24,7 @@ Item {
"tooltip": "Baseline",
"source": Constants.sideNavBar.baselinePath
}, {
- "name": "Obs ",
+ "name": "Observations",
"tooltip": "Observations",
"source": Constants.sideNavBar.observationsPath
}, {
@@ -40,17 +41,22 @@ Item {
"source": Constants.sideNavBar.advancedPath
}]
+ function clickButton(index) {
+ navButtons.itemAtIndex(index).toggle();
+ }
+
ConnectionData {
id: connectionData
}
ColumnLayout {
anchors.fill: parent
+ spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
- color: Constants.swiftGrey
+ color: Constants.sideNavBar.backgroundColor
ButtonGroup {
id: navButtonGroup
@@ -67,18 +73,15 @@ Item {
anchors.fill: parent
model: tabModel
- currentIndex: Globals.initialMainTabIndex
+ currentIndex: -1
enabled: top.enabled
highlightMoveDuration: 200
highlightResizeDuration: 0
highlightFollowsCurrentItem: true
- Component.onCompleted: {
- currentItem.checked = true;
- }
highlight: Item {
// TODO: This is an odd z order which depends on the Z order of some things in the buttons, refactor.
- z: 6
+ z: 11
Rectangle {
height: 2
@@ -90,29 +93,29 @@ Item {
}
delegate: SideNavButton {
+ text: modelData.name
+ icon.source: modelData.source
+ ToolTip.text: modelData.tooltip
buttonGroup: navButtonGroup
+ height: Constants.sideNavBar.tabBarHeight
}
}
}
- TabButton {
+ SideNavButton {
id: connectButton
Layout.alignment: Qt.AlignBottom
- Layout.preferredWidth: Constants.sideNavBar.tabBarWidth
- border: false
+ Layout.fillWidth: true
+ height: Constants.sideNavBar.tabBarHeight
+ text: "Connection"
icon.source: Constants.icons.lightningBoltPath
- icon.color: !enabled ? Constants.materialGrey : Constants.swiftOrange
- backgroundColor: hovered ? Qt.darker("white", 1.1) : "white"
- checkable: false
- padding: Constants.sideNavBar.buttonPadding
- rightInset: Constants.sideNavBar.buttonInset
- leftInset: Constants.sideNavBar.buttonInset
- ToolTip.visible: hovered
ToolTip.text: "Connection Dialog"
+ checkable: false
enabled: Globals.connected_at_least_once
+ silenceButtonGroupWarning: true
onClicked: {
if (stack.connectionScreenVisible())
stack.mainView();
@@ -121,13 +124,81 @@ Item {
}
}
- Timer {
- interval: Utils.hzToMilliseconds(Constants.staticTimerSlowIntervalRate)
- running: true
- repeat: true
- onTriggered: {
- connectButton.checked = Globals.conn_state == Constants.connection.connected;
+ Rectangle {
+ id: connectionStatusIndicator
+
+ property real speed: 0
+
+ Layout.alignment: Qt.AlignBottom
+ Layout.fillWidth: true
+ height: Constants.sideNavBar.tabBarHeight
+ enabled: top.enabled
+ color: Constants.sideNavBar.backgroundColor
+ state: "bad"
+ states: [
+ State {
+ name: "good"
+
+ PropertyChanges {
+ target: connectionStatusCircle
+ color: Constants.sideNavBar.statusGoodColor
+ }
+
+ },
+ State {
+ name: "ok"
+
+ PropertyChanges {
+ target: connectionStatusCircle
+ color: Constants.sideNavBar.statusOkColor
+ }
+
+ },
+ State {
+ name: "bad"
+
+ PropertyChanges {
+ target: connectionStatusCircle
+ color: Constants.sideNavBar.statusBadColor
+ }
+
+ }
+ ]
+
+ Column {
+ anchors.centerIn: parent
+ spacing: 2
+
+ Label {
+ anchors.horizontalCenter: parent.horizontalCenter
+ bottomPadding: 0
+ bottomInset: 0
+ text: connectionStatusIndicator.speed + " KB/s"
+ font.pointSize: Constants.smallPointSize
+ font.letterSpacing: -1
+ color: Qt.darker("white", enabled ? 1 : 1.4)
+ }
+
+ Rectangle {
+ id: connectionStatusCircle
+
+ property int diameter: 15
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: diameter
+ height: diameter
+ radius: diameter / 2
+
+ Behavior on color {
+ ColorAnimation {
+ }
+
+ }
+
+ }
+
}
+
}
}
diff --git a/resources/SideNavBarComponents/SideNavButton.qml b/resources/SideNavBarComponents/SideNavButton.qml
index 96dd5f086..7e7335232 100644
--- a/resources/SideNavBarComponents/SideNavButton.qml
+++ b/resources/SideNavBarComponents/SideNavButton.qml
@@ -12,25 +12,23 @@ Button {
property QtObject buttonGroup
property QtObject view: ListView.view
+ property bool separator: true
+ property bool silenceButtonGroupWarning: false
ButtonGroup.group: buttonGroup
- width: view.width
- height: implicitHeight < width ? width : implicitHeight
+ width: view ? view.width : 0
z: visualFocus ? 10 : control.checked || control.highlighted ? 5 : 1
display: AbstractButton.TextUnderIcon
checkable: true
- text: modelData.name
- ToolTip.text: modelData.tooltip
+ icon.width: 22
+ icon.height: 22
+ icon.color: control.checked || control.highlighted ? Qt.darker(Constants.swiftOrange, control.enabled ? 1 : 1.4) : control.flat && !control.down ? (control.visualFocus ? Constants.swiftOrange : control.palette.windowText) : Qt.darker("white", control.enabled ? 1 : 1.4)
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: ToolTip.text.length != 0 && hovered
- icon.source: modelData.source
- icon.width: 22
- icon.height: 22
- icon.color: control.checked || control.highlighted ? Qt.darker(Constants.swiftOrange, control.enabled ? 1 : 1.5) : control.flat && !control.down ? (control.visualFocus ? Constants.swiftOrange : control.palette.windowText) : Qt.darker("white", control.enabled ? 1 : 1.5)
font.pointSize: Constants.smallPointSize
font.capitalization: Font.MixedCase
- font.letterSpacing: -1
+ font.letterSpacing: 0
// No idea why the insets are set, but they need to be 0 so there are no gaps between buttons.
topInset: 0
bottomInset: 0
@@ -42,7 +40,9 @@ Button {
// 3 to match the new style mockups.
spacing: 3
Component.onCompleted: {
- console.assert(buttonGroup != undefined, "No buttonGroup assigned to SideNavButton! Undesired behavior will result.");
+ if (!silenceButtonGroupWarning)
+ console.assert(buttonGroup != undefined, "No buttonGroup assigned to SideNavButton! Undesired behavior will result.");
+
}
contentItem: IconLabel {
@@ -52,14 +52,14 @@ Button {
icon: control.icon
text: control.text
font: control.font
- color: control.checked || control.highlighted ? Qt.darker(control.palette.dark, control.enabled ? 1 : 1.5) : control.flat && !control.down ? (control.visualFocus ? Constants.swiftOrange : control.palette.windowText) : Qt.darker("white", control.enabled ? 1 : 1.5)
+ color: control.checked || control.highlighted ? Qt.darker(control.palette.dark, control.enabled ? 1 : 1.5) : control.flat && !control.down ? (control.visualFocus ? Constants.swiftOrange : control.palette.windowText) : Qt.darker("white", control.enabled ? 1 : 1.4)
}
background: Rectangle {
implicitWidth: 100
implicitHeight: 40
visible: !control.flat || control.down || control.checked || control.highlighted
- color: Color.blend(control.checked || control.highlighted ? Qt.darker("white", control.enabled ? 1 : 1.5) : Constants.swiftGrey, control.palette.mid, control.down ? 0.5 : 0)
+ color: Color.blend(control.checked || control.highlighted ? Qt.darker("white", control.enabled ? 1 : 1.4) : Constants.sideNavBar.backgroundColor, control.palette.mid, control.down ? 0.5 : 0)
border.color: Constants.swiftOrange
border.width: control.visualFocus ? 1 : 0
@@ -68,8 +68,8 @@ Button {
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
- color: Qt.darker("white", control.enabled ? 1 : 1.5)
- visible: !control.visualFocus && !(control.view.itemAtIndex(index + 1) != null ? control.view.itemAtIndex(index + 1).visualFocus : false)
+ color: Qt.darker("white", control.enabled ? 1 : 1.4)
+ visible: control.separator && !control.visualFocus && !(control.view && control.view.itemAtIndex(index + 1) ? control.view.itemAtIndex(index + 1).visualFocus : false)
}
Repeater {
diff --git a/resources/SolutionTab.qml b/resources/SolutionTab.qml
index bbb4e6edd..047807591 100644
--- a/resources/SolutionTab.qml
+++ b/resources/SolutionTab.qml
@@ -1,16 +1,15 @@
import "Constants"
import QtCharts 2.2
import QtQuick 2.5
-import QtQuick.Controls 2.12
-import QtQuick.Controls 1.4
+import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import "SolutionTabComponents" as SolutionTabComponents
-Item {
+MainTab {
id: solutionTab
- width: parent.width
- height: parent.height
+ subTabNames: ["Position", "Velocity"]
+ curSubTabIndex: Globals.initialMainTabIndex == 1 ? Globals.initialSubTabIndex : 0
SplitView {
id: solutionSplitView
@@ -19,56 +18,21 @@ Item {
orientation: Qt.Horizontal
SolutionTabComponents.SolutionTable {
- width: Constants.solutionTable.width
+ SplitView.minimumWidth: 240
}
- Rectangle {
- id: solutionPlots
+ StackLayout {
+ id: solutionBarLayout
- Layout.minimumWidth: 200
- Layout.fillWidth: true
-
- TabBar {
- id: solutionBar
-
- currentIndex: Globals.initialMainTabIndex == 1 ? Globals.initialSubTabIndex : 0
- z: Constants.commonChart.zAboveCharts
- contentHeight: Constants.tabBarHeight
-
- Repeater {
- model: ["Position", "Velocity"]
-
- TabButton {
- text: modelData
- width: implicitWidth
- }
-
- }
+ SplitView.minimumWidth: 410
+ SplitView.fillWidth: true
+ SplitView.fillHeight: true
+ currentIndex: curSubTabIndex
+ SolutionTabComponents.SolutionPositionTab {
}
- Rectangle {
- id: solutionTabBackground
-
- width: parent.width
- height: parent.height
- anchors.top: solutionBar.bottom
-
- StackLayout {
- id: solutionBarLayout
-
- width: parent.width
- height: parent.height
- currentIndex: solutionBar.currentIndex
-
- SolutionTabComponents.SolutionPositionTab {
- }
-
- SolutionTabComponents.SolutionVelocityTab {
- }
-
- }
-
+ SolutionTabComponents.SolutionVelocityTab {
}
}
diff --git a/resources/SolutionTabComponents/SolutionTable.qml b/resources/SolutionTabComponents/SolutionTable.qml
index eedd7832b..61ae30840 100644
--- a/resources/SolutionTabComponents/SolutionTable.qml
+++ b/resources/SolutionTabComponents/SolutionTable.qml
@@ -26,6 +26,8 @@ Item {
}
+ implicitWidth: Constants.solutionTable.width
+
SolutionTableEntries {
id: solutionTableEntries
}
diff --git a/resources/TabInfoBar.qml b/resources/TabInfoBar.qml
new file mode 100644
index 000000000..31cc5bd84
--- /dev/null
+++ b/resources/TabInfoBar.qml
@@ -0,0 +1,184 @@
+import "Constants"
+import QtQuick 2.5
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import SwiftConsole 1.0
+
+Rectangle {
+ id: tabInfoBar
+
+ property string tabName: "Tracking"
+ property var subTabNames: ["Hello World", "Foo Bar", "Quux Quuux"]
+ property alias curSubTabIndex: tabBar.currentIndex
+ property int rhsItemSpacing: 15
+
+ signal aboutClicked()
+
+ implicitHeight: rowLayout.implicitHeight
+ implicitWidth: rowLayout.implicitWidth
+
+ // Top grey line separating the bar from the window title area
+ Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ height: 1
+ color: "#C2C2C2"
+ z: 2
+ }
+
+ // Bottom grey line separating the bar from the main tab area
+ Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ height: 1
+ color: "#C2C2C2"
+ z: 2
+ }
+
+ RowLayout {
+ id: rowLayout
+
+ anchors.fill: parent
+ spacing: 0
+
+ Label {
+ id: tabLabel
+
+ Layout.fillWidth: false
+ padding: 8
+ leftPadding: 13
+ rightPadding: 13
+ text: tabName
+ color: Constants.swiftOrange
+ font.family: "Roboto Condensed"
+ font.capitalization: Font.AllUppercase
+ font.letterSpacing: 1
+ font.pointSize: 20
+ font.bold: true // Could also try playing with font.weight
+ }
+
+ TabBar {
+ id: tabBar
+
+ visible: tabBarRepeater.count > 0
+ Layout.fillWidth: false
+ spacing: 1
+
+ Repeater {
+ id: tabBarRepeater
+
+ model: subTabNames
+
+ TabButton {
+ width: implicitWidth
+ topPadding: 16
+ bottomPadding: 16
+ rightInset: -0.5
+ text: modelData
+ border: false
+ }
+
+ }
+
+ }
+
+ // Spacer item
+ Item {
+ implicitHeight: tabBar.implicitHeight
+ Layout.fillWidth: true
+ }
+
+ Item {
+ implicitWidth: children[0].implicitWidth + rhsItemSpacing
+ Layout.fillHeight: true
+
+ Image {
+ anchors.top: parent.top
+ anchors.topMargin: 7
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 7
+ source: Constants.icons.swiftLogoWidePath
+ fillMode: Image.PreserveAspectFit
+ }
+
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.topMargin: 7
+ Layout.bottomMargin: 7
+ width: 1
+ color: "#C2C2C2"
+ Layout.alignment: Qt.AlignVCenter
+ }
+
+ Label {
+ leftPadding: rhsItemSpacing
+ rightPadding: rhsItemSpacing
+ text: "Console"
+ color: Constants.swiftLightGrey
+ font.family: "Roboto Condensed"
+ font.capitalization: Font.AllUppercase
+ font.letterSpacing: 2
+ font.pointSize: 20
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.topMargin: 7
+ Layout.bottomMargin: 7
+ width: 1
+ color: "#C2C2C2"
+ Layout.alignment: Qt.AlignVCenter
+ }
+
+ Item {
+ implicitWidth: children[0].implicitWidth + rhsItemSpacing * 4 / 3
+ Layout.fillHeight: true
+
+ RoundButton {
+ anchors.centerIn: parent
+ flat: true
+ icon.source: Constants.infoPath
+ icon.width: 20
+ icon.height: 20
+ icon.color: Constants.swiftLightGrey
+ padding: rhsItemSpacing / 3
+ onClicked: tabInfoBar.aboutClicked()
+ }
+
+ }
+
+ }
+
+ // Add in single-line separators between the items.
+ Repeater {
+ model: tabInfoBar.tabName.length > 0 ? tabBar.count + 1 : 0
+
+ Rectangle {
+ property var tabButton: tabBar.itemAt(index)
+
+ height: rowLayout.height
+ width: 1
+ color: "#C2C2C2"
+ x: tabBar.count > 0 ? tabBar.x + (tabButton ? tabButton.x - 1 : tabBar.width) : tabLabel.x + tabLabel.width
+ }
+
+ }
+
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "white"
+ }
+
+ GradientStop {
+ position: 1
+ color: Constants.swiftControlBackground
+ }
+
+ }
+
+}
diff --git a/resources/Theme/Theme.qml b/resources/Theme/Theme.qml
deleted file mode 100644
index 4ccd822d5..000000000
--- a/resources/Theme/Theme.qml
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.12
-pragma Singleton
-
-QtObject {
- readonly property color gray: "#b2b1b1"
- readonly property color lightGray: "#dddddd"
- readonly property color light: "#ffffff"
- readonly property color blue: "#2d548b"
- property color mainColor: "#17a81a"
- readonly property color dark: "#222222"
- readonly property color mainColorDarker: Qt.darker(mainColor, 1.5)
- property int baseSize: 10
- readonly property int smallSize: 10
- readonly property int largeSize: 16
- property font font
-
- font.bold: true
- font.underline: false
- font.pixelSize: 14
- font.family: "arial"
-}
diff --git a/resources/Theme/qmldir b/resources/Theme/qmldir
deleted file mode 100644
index 4a58c13a9..000000000
--- a/resources/Theme/qmldir
+++ /dev/null
@@ -1,2 +0,0 @@
-module Theme
-singleton Theme 1.0 Theme.qml
diff --git a/resources/TrackingTab.qml b/resources/TrackingTab.qml
index fb851c119..e3fc86850 100644
--- a/resources/TrackingTab.qml
+++ b/resources/TrackingTab.qml
@@ -1,64 +1,26 @@
import "Constants"
import QtCharts 2.2
import QtQuick 2.5
-import QtQuick.Controls 2.12
+import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import "TrackingTabComponents" as TrackingTabComponents
-Item {
+MainTab {
id: trackingTab
- width: parent.width
- height: parent.height
+ subTabNames: ["Signals", "Sky Plot"]
+ curSubTabIndex: Globals.initialMainTabIndex == 0 ? Globals.initialSubTabIndex : 0
- TabBar {
- id: trackingBar
+ StackLayout {
+ id: trackingBarLayout
- anchors.left: parent.left
- anchors.right: parent.right
- z: Constants.commonChart.zAboveCharts
- currentIndex: Globals.initialMainTabIndex == 0 ? Globals.initialSubTabIndex : 0
- contentHeight: Constants.tabBarHeight
-
- Repeater {
- model: ["Signals", "Sky Plot"]
-
- TabButton {
- text: modelData
- width: implicitWidth
- }
+ anchors.fill: parent
+ currentIndex: curSubTabIndex
+ TrackingTabComponents.TrackingSignalsTab {
}
- }
-
- Rectangle {
- id: trackingTabBackground
-
- width: parent.width
- height: parent.height
- anchors.top: trackingBar.bottom
- anchors.bottom: trackingTab.bottom
- Component.onCompleted: {
- }
-
- StackLayout {
- id: trackingBarLayout
-
- width: parent.width
- height: parent.height
- currentIndex: trackingBar.currentIndex
-
- TrackingTabComponents.TrackingSignalsTab {
- Layout.fillWidth: true
- Layout.fillHeight: true
- }
-
- TrackingTabComponents.TrackingSkyPlotTab {
- Layout.fillWidth: true
- Layout.fillHeight: true
- }
-
+ TrackingTabComponents.TrackingSkyPlotTab {
}
}
diff --git a/resources/UpdateTab.qml b/resources/UpdateTab.qml
index c0b3d48d9..112919d63 100644
--- a/resources/UpdateTab.qml
+++ b/resources/UpdateTab.qml
@@ -5,7 +5,7 @@ import QtQuick.Layouts 1.15
import SwiftConsole 1.0
import "UpdateTabComponents" as UpdateTabComponents
-Item {
+MainTab {
id: updateTab
property bool consoleVersionDialogAlready: false
@@ -51,9 +51,6 @@ Item {
return text;
}
- width: parent.width
- height: parent.height
-
UpdateTabData {
id: updateTabData
}
diff --git a/resources/console_resources.qrc b/resources/console_resources.qrc
index f503d316a..786f7e94f 100644
--- a/resources/console_resources.qrc
+++ b/resources/console_resources.qrc
@@ -4,6 +4,7 @@
fonts/Roboto-LICENSE.txt
fonts/Roboto-Regular.ttf
fonts/Roboto-Bold.ttf
+ fonts/RobotoCondensed-Regular.ttf
view.qml
MainDialogView.qml
MainTabs.qml
@@ -71,12 +72,14 @@
images/fontawesome/bars-solid.svg
images/fontawesome/play-solid.svg
images/fontawesome/power-off-solid.svg
+ images/fontawesome/info-circle-solid.svg
images/iconic/media-pause.svg
images/fontawesome/crosshairs-solid.svg
images/fontawesome/eraser-solid.svg
images/fontawesome/expand-solid.svg
images/ConnectionIcon.svg
images/LogoBackground.jpg
+ images/swiftLogoWide.svg
images/fontawesome/folder-open-regular.svg
images/fontawesome/folder-solid.svg
images/fontawesome/square-solid.svg
@@ -101,9 +104,10 @@
BaseComponents/SmallCheckBox.qml
BaseComponents/SwiftGroupBox.qml
ChartLegend.qml
- Theme/qmldir
- Theme/Theme.qml
styles/SwiftNav/TabBar.qml
styles/SwiftNav/TabButton.qml
+ styles/SwiftNav/RoundButton.qml
+ MainTab.qml
+ TabInfoBar.qml
diff --git a/resources/fonts/RobotoCondensed-Regular.ttf b/resources/fonts/RobotoCondensed-Regular.ttf
new file mode 100644
index 000000000..62dd61e5d
Binary files /dev/null and b/resources/fonts/RobotoCondensed-Regular.ttf differ
diff --git a/resources/images/fontawesome/info-circle-solid.svg b/resources/images/fontawesome/info-circle-solid.svg
new file mode 100644
index 000000000..5cf096d17
--- /dev/null
+++ b/resources/images/fontawesome/info-circle-solid.svg
@@ -0,0 +1 @@
+
diff --git a/resources/images/swiftLogoWide.svg b/resources/images/swiftLogoWide.svg
new file mode 100644
index 000000000..0cddc1527
--- /dev/null
+++ b/resources/images/swiftLogoWide.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/styles/SwiftNav/RoundButton.qml b/resources/styles/SwiftNav/RoundButton.qml
new file mode 100644
index 000000000..bb1421a49
--- /dev/null
+++ b/resources/styles/SwiftNav/RoundButton.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Controls.impl 2.12
+import QtQuick.Templates 2.12 as T
+
+T.RoundButton {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding)
+ padding: 6
+ spacing: 6
+ icon.width: 24
+ icon.height: 24
+ icon.color: control.checked || control.highlighted ? control.palette.brightText : control.flat && !control.down ? (control.visualFocus ? control.palette.highlight : control.palette.windowText) : control.palette.buttonText
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: control.checked || control.highlighted ? control.palette.brightText : control.flat && !control.down ? (control.visualFocus ? control.palette.highlight : control.palette.windowText) : control.palette.buttonText
+ }
+
+ background: Rectangle {
+ implicitWidth: control.icon.width + 2
+ implicitHeight: control.icon.height + 2
+ radius: control.radius
+ opacity: enabled ? 1 : 0.3
+ visible: !control.flat || control.down || control.checked || control.highlighted
+ color: Color.blend(control.checked || control.highlighted ? control.palette.dark : control.palette.button, control.palette.mid, control.down ? 0.5 : 0)
+ border.color: control.palette.highlight
+ border.width: control.visualFocus ? 2 : 0
+ }
+
+}
diff --git a/resources/styles/SwiftNav/TabBar.qml b/resources/styles/SwiftNav/TabBar.qml
index cb258f4c2..d32125b91 100644
--- a/resources/styles/SwiftNav/TabBar.qml
+++ b/resources/styles/SwiftNav/TabBar.qml
@@ -10,7 +10,6 @@ T.TabBar {
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, contentHeight + topPadding + bottomPadding)
- spacing: -1
contentItem: ListView {
model: control.contentModel
@@ -31,9 +30,8 @@ T.TabBar {
z: 2
Rectangle {
- x: 1
height: 2
- width: parent.width - 2
+ width: parent.width
y: control.position === T.TabBar.Footer ? 0 : parent.height - height
color: control.Material.accentColor
}
@@ -55,22 +53,6 @@ T.TabBar {
}
- Rectangle {
- z: 2
- anchors.top: parent.top
- width: parent.width
- height: 1
- color: "#C2C2C2"
- }
-
- Rectangle {
- z: 2
- anchors.bottom: parent.bottom
- width: parent.width
- height: 1
- color: "#C2C2C2"
- }
-
}
}
diff --git a/resources/styles/SwiftNav/TabButton.qml b/resources/styles/SwiftNav/TabButton.qml
index 2d242f3fd..42cc76520 100644
--- a/resources/styles/SwiftNav/TabButton.qml
+++ b/resources/styles/SwiftNav/TabButton.qml
@@ -46,6 +46,7 @@ T.TabButton {
id: control
property color labelColor: !control.enabled ? control.Material.hintTextColor : control.down || control.checked ? "white" : Constants.tabButtonUnselectedTextColor
+ property color gradientStartColor: down || checked ? Qt.lighter(Constants.swiftGrey, 1.7) : hovered ? Qt.lighter(Constants.swiftControlBackground, 1.1) : "white"
property color backgroundColor: down || checked ? Constants.swiftGrey : hovered ? Qt.darker(Constants.swiftControlBackground, 1.1) : Constants.swiftControlBackground
property bool border: true
@@ -79,6 +80,20 @@ T.TabButton {
implicitHeight: control.Material.touchTarget
clip: true
color: backgroundColor
+
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: gradientStartColor
+ }
+
+ GradientStop {
+ position: 1
+ color: backgroundColor
+ }
+
+ }
+
}
}
diff --git a/resources/view.qml b/resources/view.qml
index 4ab5237f8..a81b3c49e 100644
--- a/resources/view.qml
+++ b/resources/view.qml
@@ -1,8 +1,7 @@
import "Constants"
-import QtCharts 2.2
-import QtQuick 2.5
+import QtQuick 2.15
import QtQuick.Controls 2.15
-import QtQuick.Controls.Material 2.12
+import QtQuick.Controls.Material 2.15
import QtQuick.Layouts 1.15
import SwiftConsole 1.0
@@ -29,10 +28,182 @@ ApplicationWindow {
anchors.fill: parent
}
+ MouseArea {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ z: 1
+ height: 30
+ visible: tabInfoBar.state == "closed"
+ hoverEnabled: true
+ acceptedButtons: Qt.NoButton
+ onPositionChanged: tabInfoBarOpenTimer.restart()
+ onExited: tabInfoBarOpenTimer.stop()
+
+ Timer {
+ id: tabInfoBarOpenTimer
+
+ interval: 200
+ onTriggered: tabInfoBar.open()
+ }
+
+ }
+
+ TabInfoBar {
+ id: tabInfoBar
+
+ property int openDuration: 1000
+ property int closeDuration: 350
+
+ function open() {
+ state = "opened";
+ }
+
+ function close() {
+ state = "closed";
+ }
+
+ function cancelAutoClose() {
+ tabInfoBarCloseTimer.stop();
+ }
+
+ function closeAfterDelaySubtabless() {
+ if (tabName.length > 0 && subTabNames.length == 0)
+ tabInfoBarCloseTimer.restart();
+ else
+ cancelAutoClose();
+ }
+
+ // We explicitly do not anchor in the vertical, so the item can
+ // be slid up "under" the window.
+ anchors.left: parent.left
+ anchors.right: parent.right
+ z: 2
+ tabName: sideNavBar.currentTabName
+ subTabNames: mainTabs.subTabNames
+ state: "opened"
+ onAboutClicked: logoPopup.open()
+ // When the tab name changes, make sure this item is shown.
+ // If there is no subtabs, then close it after some time.
+ onTabNameChanged: {
+ open();
+ closeAfterDelaySubtabless();
+ }
+ states: [
+ // The opened state sets the y position so the item is
+ // positioned so it's top is right at the top of the parent
+ // item.
+ State {
+ name: "opened"
+
+ PropertyChanges {
+ target: tabInfoBar
+ y: 0
+ }
+
+ },
+ // The closed state sets the y position so the item is
+ // positioned so it's bottom is right at the top of the
+ // parent item, and all but one pixel height of the item is
+ // hidden. One pixel is still shown so there is a border
+ // line at the top of the view.
+ State {
+ name: "closed"
+
+ PropertyChanges {
+ target: tabInfoBar
+ y: -height + 1
+ }
+
+ }
+ ]
+ // Make the opened/closed state transitions smooth.
+ transitions: [
+ Transition {
+ from: "opened"
+ to: "closed"
+
+ NumberAnimation {
+ target: tabInfoBar
+ properties: "y"
+ duration: tabInfoBar.closeDuration
+ easing.type: Easing.OutQuad
+ }
+
+ },
+ Transition {
+ from: "closed"
+ to: "opened"
+
+ NumberAnimation {
+ target: tabInfoBar
+ properties: "y"
+ duration: tabInfoBar.openDuration
+ easing.type: Easing.OutQuad
+ }
+
+ }
+ ]
+
+ Timer {
+ id: tabInfoBarCloseTimer
+
+ interval: 3000
+ onTriggered: parent.close()
+ }
+
+ // This captures any clicks outside of the buttons, and toggles
+ // the state from opened to closed or vice versa.
+ MouseArea {
+ anchors.fill: parent
+ z: -1
+ onClicked: parent.state = parent.state == "opened" ? "closed" : "opened"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ acceptedButtons: Qt.NoButton
+ onEntered: parent.cancelAutoClose()
+ onExited: parent.closeAfterDelaySubtabless()
+ }
+
+ }
+
+ Rectangle {
+ anchors.right: parent.right
+ anchors.rightMargin: 5
+ y: -3
+ z: 1
+ implicitHeight: tabInfoBarOpenText.implicitHeight + 9
+ implicitWidth: 30
+ color: Constants.swiftControlBackground
+ radius: 3
+
+ Text {
+ id: tabInfoBarOpenText
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 3
+ text: "▼"
+ color: Constants.swiftLightGrey
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: tabInfoBar.open()
+ }
+
+ }
+
RowLayout {
property alias stackView: dialogStack.dialogStack
- anchors.fill: parent
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: tabInfoBar.bottom
+ anchors.bottom: parent.bottom
spacing: 0
SideNavBar {
@@ -55,6 +226,9 @@ ApplicationWindow {
}
function mainView() {
+ if (sideNavBar.currentIndex < 0)
+ sideNavBar.clickButton(Globals.initialMainTabIndex);
+
stack.currentIndex = 1;
}
@@ -83,6 +257,7 @@ ApplicationWindow {
MainTabs {
id: mainTabs
+ curSubTabIndex: tabInfoBar.curSubTabIndex
SplitView.fillHeight: true
SplitView.fillWidth: true
Layout.leftMargin: Constants.margins
diff --git a/swiftnav_console/main.py b/swiftnav_console/main.py
index 625b40699..6255817f8 100644
--- a/swiftnav_console/main.py
+++ b/swiftnav_console/main.py
@@ -801,6 +801,8 @@ def main():
app.setApplicationName(ApplicationMetadata.APPLICATION_NAME)
QFontDatabase.addApplicationFont(":/fonts/Roboto-Regular.ttf")
QFontDatabase.addApplicationFont(":/fonts/Roboto-Bold.ttf")
+ QFontDatabase.addApplicationFont(":/fonts/RobotoCondensed-Regular.ttf")
+ # We specifically *don't* want the RobotoCondensed-Bold.ttf font so we get the right look when bolded.
qmlRegisterType(LogPanelData, "SwiftConsole", 1, 0, "LogPanelData") # type: ignore
qmlRegisterType(ConnectionData, "SwiftConsole", 1, 0, "ConnectionData") # type: ignore