diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index deb19b20..f4a2b927 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,19 +19,19 @@ jobs:
- os: ubuntu-20.04
qt_host: linux
- qt_version: '6.8.0'
+ qt_version: '6.8.1'
qt_modules: 'qtmultimedia qtcharts qtwaylandcompositor'
qt_arch: 'linux_gcc_64'
- os: windows-2022
qt_host: windows
- qt_version: '6.8.0'
+ qt_version: '6.8.1'
qt_modules: 'qtmultimedia qtcharts'
qt_arch: 'win64_msvc2022_64'
- os: macos-latest
qt_host: mac
- qt_version: '6.7.2'
+ qt_version: '6.8.1'
qt_modules: 'qtmultimedia qtcharts'
qt_arch: 'clang_64'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 94f9649f..88ff9782 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -114,8 +114,14 @@ set(QML_ELEMENTS
dialogs/TopicView
dialogs/TabNameDialog
dialogs/TabSizeDialog
- dialogs/WidgetConfig
- dialogs/ServerDialog
+
+ dialogs/ServerTab
+ dialogs/MiscTab
+ dialogs/AppearanceTab
+ dialogs/SettingsDialog
+ dialogs/SettingsTabButton
+ dialogs/AppearanceComboBox
+
dialogs/AccentEditor
)
diff --git a/Main.qml b/Main.qml
index 7de41ffa..e1f6cbb5 100644
--- a/Main.qml
+++ b/Main.qml
@@ -10,81 +10,18 @@ ApplicationWindow {
visible: true
title: titleManager.title
- menuBar: MenuBar {
- contentWidth: parent.width
-
- Menu {
- contentWidth: 210
- title: qsTr("&Settings")
- Action {
- text: qsTr("&Server Settings...")
- onTriggered: screen.serverSettings()
- shortcut: "Ctrl+E"
- }
- MenuItem {
- text: "&Load Most Recent File?"
- checkable: true
- checked: settings.loadRecent
- onCheckedChanged: settings.loadRecent = checked
- }
-
- Menu {
- title: qsTr("&Theme")
- Repeater {
- model: ["Light", "Dark", "Midnight"]
-
- MenuItem {
- text: "&" + modelData
- checkable: true
- checked: settings.theme === modelData.toLowerCase()
- onCheckedChanged: {
- if (checked)
- Constants.setTheme(modelData.toLowerCase())
- }
- }
- }
- }
-
- Menu {
- title: qsTr("&Accent")
+ AccentEditor {
+ id: accentEditor
- Repeater {
- model: accents
-
- MenuItem {
- function toTitleCase(str) {
- return str.replace(
- /\w\S*/g,
- text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
- );
- }
+ anchors.centerIn: Overlay.overlay
+ }
- text: "&" + toTitleCase(model.name)
- checkable: true
- checked: settings.accent === model.name
- onCheckedChanged: {
- if (checked)
- Constants.setAccent(model.name)
- }
- }
- }
- }
+ menuBar: MenuBar {
+ contentWidth: parent.width
- Menu {
- title: qsTr("&Custom Accents")
- MenuItem {
- text: "&Edit Accents..."
- onTriggered: screen.editAccents()
- }
- MenuItem {
- text: "Export Accents..."
- onTriggered: screen.exportAccentsAction()
- }
- MenuItem {
- text: "Import Accents..."
- onTriggered: screen.importAccentsAction()
- }
- }
+ MenuBarItem {
+ text: qsTr("&Settings")
+ onTriggered: screen.settingsDialog()
}
Menu {
@@ -112,7 +49,11 @@ ApplicationWindow {
delegate: MenuItem {
text: qsTr("&" + index + ". " + modelData)
- onTriggered: tlm.load(modelData)
+ onTriggered: {
+ if (modelData === "" || modelData === null) return;
+ tlm.clear()
+ tlm.load(modelData)
+ }
}
}
}
diff --git a/dialogs/AppearanceComboBox.qml b/dialogs/AppearanceComboBox.qml
new file mode 100644
index 00000000..29ba84ee
--- /dev/null
+++ b/dialogs/AppearanceComboBox.qml
@@ -0,0 +1,67 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQuick.Shapes 2.15
+
+import QFRCDashboard
+
+ComboBox {
+ required property string label
+
+ /** what property to bind to */
+ required property string bindedProperty
+
+ /** the target to bind the property to */
+ required property var bindTarget
+
+ required property var choices
+
+ id: combo
+ model: choices
+ font.pixelSize: 15
+
+ function toTitleCase(str) {
+ return str.replace(
+ /\w\S*/g,
+ text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()
+ );
+ }
+
+ function open() {
+ currentIndex = indexOfValue(toTitleCase(bindTarget[bindedProperty]))
+ }
+
+ function accept() {
+ bindTarget[bindedProperty] = currentText.toLowerCase()
+ }
+
+ delegate: ItemDelegate {
+ id: delegate
+
+ width: combo.width
+ contentItem: Text {
+ text: modelData
+ color: "white"
+ font.pixelSize: 15
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+ highlighted: combo.highlightedIndex === index
+ }
+
+ Text {
+ id: floatingLabel
+ text: label
+ color: Constants.palette.text
+
+ font.pixelSize: 15
+
+ anchors {
+ left: parent.left
+ bottom: parent.top
+
+ bottomMargin: -2
+ leftMargin: 10
+ }
+ }
+}
diff --git a/dialogs/AppearanceTab.qml b/dialogs/AppearanceTab.qml
new file mode 100644
index 00000000..ebda1779
--- /dev/null
+++ b/dialogs/AppearanceTab.qml
@@ -0,0 +1,110 @@
+import QtCore
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 6.6
+import QtQuick.Dialogs
+
+import QFRCDashboard
+
+ColumnLayout {
+ spacing: 5
+
+ function editAccents() {
+ accentEditor.open()
+ }
+
+ FileDialog {
+ id: saveAccentDialog
+ currentFolder: StandardPaths.writableLocation(
+ StandardPaths.HomeLocation)
+ fileMode: FileDialog.SaveFile
+ defaultSuffix: "json"
+ selectedNameFilter.index: 0
+ nameFilters: ["JSON files (*.json)", "All files (*)"]
+
+ onAccepted: accents.exportJson(selectedFile)
+ }
+
+ function exportAccents() {
+ saveAccentDialog.open()
+ }
+
+ FileDialog {
+ id: loadAccentDialog
+ currentFolder: StandardPaths.writableLocation(
+ StandardPaths.HomeLocation)
+ fileMode: FileDialog.OpenFile
+ defaultSuffix: "json"
+ selectedNameFilter.index: 0
+ nameFilters: ["JSON files (*.json)", "All files (*)"]
+
+ onAccepted: accents.importJson(loadAccentDialog.selectedFile)
+ }
+
+ function importAccents() {
+ loadAccentDialog.open()
+ }
+
+ function accept() {
+ theme.accept()
+ accent.accept()
+
+ Constants.setTheme(settings.theme)
+ Constants.setAccent(settings.accent)
+ }
+
+ function open() {
+ theme.open()
+ accent.open()
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ AppearanceComboBox {
+ implicitWidth: 200
+ id: theme
+
+ label: "Theme"
+
+ bindedProperty: "theme"
+ bindTarget: settings
+
+ choices: ["Light", "Dark", "Midnight"]
+ }
+
+ AppearanceComboBox {
+ implicitWidth: 200
+ id: accent
+
+ label: "Accent"
+
+ bindedProperty: "accent"
+ bindTarget: settings
+
+ choices: accents.names()
+ }
+ }
+
+ SectionHeader {
+ label: "Custom Accents"
+ }
+
+ RowLayout {
+ uniformCellSizes: true
+ Layout.fillWidth: true
+
+ Button {
+ text: "&Edit"
+ onClicked: editAccents()
+ }
+ Button {
+ text: "E&xport"
+ onClicked: exportAccents()
+ }
+ Button {
+ text: "I&mport"
+ onClicked: importAccents()
+ }
+ }
+}
diff --git a/dialogs/MiscTab.qml b/dialogs/MiscTab.qml
new file mode 100644
index 00000000..6a907a5a
--- /dev/null
+++ b/dialogs/MiscTab.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 6.6
+import QtQuick.Dialogs
+
+import QFRCDashboard
+
+ColumnLayout {
+ spacing: 5
+
+ function accept() {
+ load.accept()
+ }
+
+ function open() {
+ load.open()
+ }
+
+ LabeledCheckbox {
+ id: load
+ label: "Load Recent Files?"
+
+ bindTarget: settings
+ bindedProperty: "loadRecent"
+ }
+}
diff --git a/dialogs/ServerDialog.qml b/dialogs/ServerDialog.qml
deleted file mode 100644
index 24d7b920..00000000
--- a/dialogs/ServerDialog.qml
+++ /dev/null
@@ -1,83 +0,0 @@
-import QtQuick 2.15
-import QtQuick.Controls 2.15
-import QtQuick.Layouts 6.6
-import QtQuick.Dialogs
-
-import QFRCDashboard
-
-Dialog {
- id: serverDialog
-
- anchors.centerIn: parent
-
- onAccepted: {
- settings.port = port.value
- settings.useTeam = useTeam.checked
- settings.ip = ip.text
- }
-
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- Shortcut {
- onActivated: reject()
- sequence: Qt.Key_Escape
- }
-
- ColumnLayout {
- anchors.fill: parent
- spacing: 5
-
- RowLayout {
- Layout.fillWidth: true
- uniformCellSizes: true
- Text {
- text: "Port:"
- font.pixelSize: 17
- color: Constants.palette.text
- }
-
- SpinBox {
- id: port
-
- value: settings.port
-
- from: 1
- to: 65535
-
- font.pixelSize: 17
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- uniformCellSizes: true
- Text {
- text: useTeam.checked ? "Team Number:" : "IP Address:"
- font.pixelSize: 17
- color: Constants.palette.text
- }
-
- TextField {
- id: ip
-
- text: settings.ip
-
- validator: RegularExpressionValidator {
- regularExpression: useTeam.checked ? /[0-9]{1,5}/ : /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/
- }
-
- font.pixelSize: 17
- }
- }
-
- CheckBox {
- Layout.fillWidth: true
- id: useTeam
- text: "Use Team Number?"
-
- checked: settings.useTeam
-
- font.pixelSize: 17
- }
- }
-}
diff --git a/dialogs/ServerTab.qml b/dialogs/ServerTab.qml
new file mode 100644
index 00000000..086e4932
--- /dev/null
+++ b/dialogs/ServerTab.qml
@@ -0,0 +1,66 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 6.6
+import QtQuick.Dialogs
+
+import QFRCDashboard
+
+ColumnLayout {
+ spacing: 5
+
+ function accept() {
+ team.accept()
+ ip.accept()
+ settings.mode = mode.currentIndex
+ }
+
+ function open() {
+ team.open()
+ ip.open()
+ mode.currentIndex = settings.mode
+ }
+
+ RowLayout {
+ Layout.leftMargin: 4
+ Layout.fillWidth: true
+
+ LabeledSpinBox {
+ implicitWidth: 180
+ id: team
+
+ from: 0
+ to: 99999
+
+ label: "Team Number"
+
+ bindedProperty: "team"
+ bindTarget: settings
+ }
+
+ LabeledTextField {
+ implicitWidth: 230
+ id: ip
+
+ label: "IP Address"
+
+ bindedProperty: "ip"
+ bindTarget: settings
+
+ validator: RegularExpressionValidator {
+ regularExpression: /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/
+ }
+ }
+ }
+
+ LabeledComboBox {
+ id: mode
+ implicitWidth: 250
+
+ label: "Connection Mode"
+
+ bindedProperty: "mode"
+ bindTarget: settings
+
+ choices: ["IP Address", "Team Number", "Driver Station"]
+ }
+}
diff --git a/dialogs/SettingsDialog.qml b/dialogs/SettingsDialog.qml
new file mode 100644
index 00000000..5fd82f9e
--- /dev/null
+++ b/dialogs/SettingsDialog.qml
@@ -0,0 +1,106 @@
+import QtQuick 6.7
+import QtQuick.Controls 6.6
+import QtQuick.Layouts 6.6
+import QtQuick.Dialogs
+
+import QFRCDashboard
+
+Dialog {
+ id: serverDialog
+
+ height: 350
+ width: 475
+
+ background: Rectangle {
+ color: Constants.palette.dialogBg
+
+ radius: 12
+ }
+
+ anchors.centerIn: parent
+
+ onAccepted: {
+ server.accept()
+ appearance.accept()
+ misc.accept()
+ }
+
+ standardButtons: Dialog.Ok | Dialog.Cancel
+
+ Shortcut {
+ onActivated: reject()
+ sequence: Qt.Key_Escape
+ }
+
+ function openDialog() {
+ open()
+ server.open()
+ appearance.open()
+ misc.open()
+ }
+
+ SwipeView {
+ id: swipe
+ currentIndex: tabBar.currentIndex
+ clip: true
+
+ anchors {
+ top: tabBar.bottom
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+ }
+
+ ServerTab {
+ anchors.leftMargin: 5
+
+ id: server
+ clip: true
+ }
+
+ AppearanceTab {
+ anchors.leftMargin: 5
+
+ id: appearance
+ clip: true
+ }
+
+ MiscTab {
+ anchors.leftMargin: 5
+
+ id: misc
+ clip: true
+ }
+ }
+
+ TabBar {
+ id: tabBar
+ currentIndex: swipe.currentIndex
+ position: TabBar.Header
+
+ background: Rectangle {
+ color: "transparent"
+ }
+
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+
+ leftMargin: -18
+ rightMargin: -18
+ topMargin: -16
+ }
+
+ Repeater {
+ model: ["Network", "Appearance", "Miscellaneous"]
+
+ SettingsTabButton {
+ required property string modelData
+ required property int index
+
+ label: modelData
+ }
+ }
+ }
+}
diff --git a/dialogs/SettingsTabButton.qml b/dialogs/SettingsTabButton.qml
new file mode 100644
index 00000000..3736218c
--- /dev/null
+++ b/dialogs/SettingsTabButton.qml
@@ -0,0 +1,39 @@
+import QtQuick 6.7
+import QtQuick.Controls 6.6
+import QtQuick.Layouts 6.6
+import QtQuick.Dialogs
+
+import QFRCDashboard
+
+TabButton {
+ required property string label
+
+ id: button
+
+ height: 40
+
+ contentItem: Row {
+ Image {
+ source: "qrc:/" + label + (index === tabBar.currentIndex ? "Light" : "Dark")
+ width: 25
+ height: 25
+ }
+
+ Label {
+ font.pixelSize: 18
+ text: label
+
+ verticalAlignment: Qt.AlignVCenter
+ horizontalAlignment: Qt.AlignHCenter
+
+ color: index === tabBar.currentIndex ? Constants.tab : "white"
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: parent.width
+ topLeftRadius: 12
+ topRightRadius: 12
+ color: index !== tabBar.currentIndex ? Constants.tab : "white"
+ }
+}
diff --git a/dialogs/WidgetConfig.qml b/dialogs/WidgetConfig.qml
deleted file mode 100644
index 5c8ce248..00000000
--- a/dialogs/WidgetConfig.qml
+++ /dev/null
@@ -1,916 +0,0 @@
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Dialogs
-import QtQuick.Layouts
-
-import Qt.labs.qmlmodels
-import QFRCDashboard
-
-Dialog {
- id: widgetConf
-
- anchors.centerIn: parent
-
- width: parent.width / 1.6
- height: parent.height - 60
- background: Rectangle {
- color: Constants.palette.dialogBg
- }
-
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- onAccepted: getValues()
-
- Shortcut {
- onActivated: reject()
- sequence: Qt.Key_Escape
- }
-
- ColorDialog {
- id: colorDialog
- }
-
- property var item
-
- function openUp(item) {
- lm.clear()
- for (var p in item) {
- if (p.startsWith("item_") && typeof item[p] !== "function") {
- let sub = p.substr(5)
- let typeName = MetaObjectHelper.typeName(item, p)
- var choices = []
- let obj = {}
-
- if (typeName === "QVariant") {
- choices = item[sub + "Choices"]
-
- typeName = "list"
- } else if (typeName === "QVariantList") {
- obj["valueType"] = item[sub + "ValueType"]
- obj["valueName"] = item[sub + "ValueName"]
- } else if (typeName === "int" || typeName === "double") {
- let min = item[sub + "Min"]
- let max = item[sub + "Max"]
-
- obj["min"] = (typeof min === "undefined") ? 0 : min
- obj["max"] = (typeof max === "undefined") ? 100000 : max
- }
-
- lm.append({
- "name": p,
- "type": typeName,
- "itemValue": item[p],
- "choices": choices,
- "item": item,
- "map": obj
- })
- }
- }
-
- this.item = item
-
- open()
- }
-
- ListModel {
- id: lm
- dynamicRoles: true
- }
-
- function displayText(text) {
- const result = text.substring(5).replace(/([A-Z])/g, " $1")
- return result.charAt(0).toUpperCase() + result.slice(1)
- }
-
- function getValues() {
- for (var i = 0; i < rep.count; ++i) {
- let idx = lm.get(i)
- item[idx.name] = idx.itemValue
- }
- }
-
- Flow {
- anchors {
- top: parent.top
- bottom: parent.bottom
- left: parent.left
- right: parent.right
-
- margins: 8
- }
-
- spacing: 8
-
- id: flow
-
- Repeater {
- id: rep
-
- clip: true
-
- // boundsBehavior: Flickable.StopAtBounds
- model: lm
-
- component FieldLabel: Label {
- Layout.fillWidth: true
-
- text: displayText(model.name)
- font.pixelSize: 15
- color: Constants.palette.text
- }
-
- delegate: DelegateChooser {
- role: "type"
-
- // TODO: may want to find a way to avoid all this repeat code
- DelegateChoice {
- roleValue: "QString"
-
- RowLayout {
- clip: true
-
- FieldLabel {}
-
- TextField {
- id: txt
- Layout.fillWidth: true
-
- font.pixelSize: 15
- text: model.itemValue
-
- onTextEdited: model.itemValue = text
- }
- }
- }
-
- DelegateChoice {
- roleValue: "bool"
-
- RowLayout {
- clip: true
-
- FieldLabel {}
-
- CheckBox {
- checked: model.itemValue
-
- onClicked: model.itemValue = checked
-
- indicator.implicitHeight: 20
- indicator.implicitWidth: 20
- }
- }
- }
-
- DelegateChoice {
- roleValue: "int"
-
- RowLayout {
- clip: true
-
- FieldLabel {}
-
- SpinBox {
- from: map.min
- to: map.max
-
- id: sb
-
- Layout.fillWidth: true
-
- font.pixelSize: 15
- value: model.itemValue
-
- onValueModified: model.itemValue = value
- }
- }
- }
-
- DelegateChoice {
- roleValue: "double"
-
- RowLayout {
- clip: true
-
- FieldLabel {}
-
- DoubleSpinBox {
- from: map.min
- to: map.max
-
- id: dsb
- font.pixelSize: 15
- Layout.fillWidth: true
-
- value: model.itemValue
-
- stepSize: 0.1
-
- onValueModified: model.itemValue = value
- }
- }
- }
-
- DelegateChoice {
- roleValue: "QColor"
-
- RowLayout {
- clip: true
-
- FieldLabel {}
-
- TextField {
- id: colorField
- font.pixelSize: 15
- Layout.fillWidth: true
-
- text: model.itemValue
-
- onTextEdited: model.itemValue = text
- }
-
- Button {
- Layout.fillWidth: true
- text: "Pick"
-
- function setColor() {
- colorField.text = colorDialog.selectedColor
- model.itemValue = colorDialog.selectedColor
- colorDialog.accepted.disconnect(setColor)
- }
-
- onClicked: {
- colorDialog.selectedColor = colorField.text
- colorDialog.accepted.connect(setColor)
- colorDialog.open()
- }
- }
- }
- }
-
- DelegateChoice {
- roleValue: "list"
-
- RowLayout {
- clip: true
-
- FieldLabel {}
-
- function setValue(v) {
- model.itemValue = v
- }
-
- ComboBox {
- model: choices
-
- delegate: ItemDelegate {
- id: delegate
-
- width: cb.width
- contentItem: Text {
- text: modelData
- color: "white"
- font.pixelSize: 15
- elide: Text.ElideRight
- verticalAlignment: Text.AlignVCenter
- }
- highlighted: choices.highlightedIndex === index
- }
-
- id: cb
- font.pixelSize: 15
- Layout.fillWidth: true
-
- Component.onCompleted: {
- currentIndex = choices.indexOf(itemValue)
- currentIndexChanged.connect(updateValue)
- }
-
- function updateValue() {
- setValue(valueAt(currentIndex))
- }
- }
- }
- }
-
- DelegateChoice {
- roleValue: "QVariantList"
-
- GridLayout {
- clip: true
- width: parent.width
-
- rowSpacing: 0
-
- rows: 4
- columns: 2
-
- FieldLabel {}
-
- function setValue(v) {
- model.itemValue = v
- }
-
- function getValue() {
- // stupid workaround because of cancer
- // itemValue gets corrupted to a QQmlListModel for some reason
- // kill me
- return model.item[model.name]
- }
-
- HorizontalHeaderView {
- Layout.minimumWidth: parent.width - 90
- Layout.row: 0
- Layout.column: 1
-
- Layout.fillWidth: true
-
- Layout.minimumHeight: 30
- Layout.columnSpan: 2
- id: horizontalHeader
- syncView: tbl
- clip: true
- }
-
- TableView {
- Layout.minimumWidth: parent.width - 90
- Layout.minimumHeight: 40
- columnSpacing: 1
- rowSpacing: 1
- clip: true
-
- id: tbl
-
- Layout.fillWidth: true
-
- Layout.row: 1
- Layout.column: 1
-
- Layout.rowSpan: 3
-
- interactive: false
-
- function resetHeight() {
- Layout.minimumHeight = 42 * tblModel.rowCount()
- }
-
- Component.onCompleted: {
- let vl = map.valueName
- let iv = getValue()
-
- for (var i = 0; i < iv.length; ++i) {
- tblModel.add(iv[i]["Value"], iv[i][vl])
- tbl.resetHeight()
- }
-
- setValue(tblModel.asList())
- tblModel.dataChanged.connect(
- () => setValue(tblModel.asList()))
- }
-
- model: MapModel {
- id: tblModel
- valueName: map.valueName
- }
-
- selectionModel: ItemSelectionModel {}
- selectionBehavior: TableView.SelectRows
- selectionMode: TableView.SingleSelection
-
- delegate: Rectangle {
- border {
- color: Constants.palette.text
- width: 2
- }
-
- required property bool selected
- required property bool current
-
- implicitWidth: tbl.width / 2
- implicitHeight: 40
-
- color: current ? "blue" : "black"
-
- Text {
- font.pixelSize: 15
- anchors.centerIn: parent
- text: display
- color: Constants.palette.text
- }
-
- TableView.editDelegate: TextField {
- font.pixelSize: 15
- anchors.fill: parent
- text: display
- horizontalAlignment: TextInput.AlignHCenter
- verticalAlignment: TextInput.AlignVCenter
- Component.onCompleted: selectAll()
-
- TableView.onCommit: {
- display = text
- }
- }
- }
- }
-
- Button {
- Layout.alignment: Qt.AlignTop | Qt.AlignLeft
- Layout.row: 1
- Layout.column: 0
- text: "Add"
-
- onClicked: {
- tblModel.add("", "")
- setValue(tblModel.asList())
- tbl.resetHeight()
- }
- }
-
- Button {
- Layout.alignment: Qt.AlignTop | Qt.AlignLeft
- Layout.row: 2
- Layout.column: 0
- text: "Delete"
-
- onClicked: {
- tblModel.remove(tbl.currentRow)
- setValue(tblModel.asList())
- tbl.resetHeight()
- }
- }
- }
- }
-
- DelegateChoice {
- roleValue: "QSizeF"
-
- RowLayout {
- clip: true
-
- FieldLabel {
- Layout.rowSpan: 4
- }
-
- Label {
- text: "Width:"
- font.pixelSize: 15
- }
-
- SpinBox {
- from: 0
- to: 2000
-
- id: width
-
- Layout.fillWidth: true
-
- font.pixelSize: 15
- value: model.itemValue.width
-
- onValueModified: model.itemValue.width = value
- }
-
- Label {
- text: "Height:"
- font.pixelSize: 15
- }
-
- SpinBox {
- from: 0
- to: 2000
-
- id: height
-
- Layout.fillWidth: true
-
- font.pixelSize: 15
- value: model.itemValue.height
-
- onValueModified: model.itemValue.height = value
- }
- }
- }
- }
- }
- }
-
- // ListView {
- // anchors {
- // top: parent.top
- // bottom: parent.bottom
- // left: parent.left
- // right: parent.right
-
- // margins: 8
- // }
-
- // spacing: 8
-
- // id: listView
-
- // clip: true
-
- // boundsBehavior: Flickable.StopAtBounds
-
- // model: lm
-
- // component FieldLabel: Label {
- // Layout.fillWidth: true
-
- // text: displayText(model.name)
- // font.pixelSize: 15
- // color: Constants.palette.text
- // }
-
- // delegate: DelegateChooser {
- // role: "type"
-
- // // TODO: may want to find a way to avoid all this repeat code
- // DelegateChoice {
- // roleValue: "QString"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // uniformCellSizes: true
-
- // FieldLabel {}
-
- // TextField {
- // id: txt
- // Layout.fillWidth: true
-
- // font.pixelSize: 15
- // text: model.itemValue
-
- // onTextEdited: model.itemValue = text
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "bool"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // uniformCellSizes: true
-
- // FieldLabel {}
-
- // CheckBox {
- // checked: model.itemValue
-
- // onClicked: model.itemValue = checked
-
- // indicator.implicitHeight: 20
- // indicator.implicitWidth: 20
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "int"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // uniformCellSizes: true
-
- // FieldLabel {}
-
- // SpinBox {
- // from: map.min
- // to: map.max
-
- // id: sb
-
- // Layout.fillWidth: true
-
- // font.pixelSize: 15
- // value: model.itemValue
-
- // onValueModified: model.itemValue = value
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "double"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // uniformCellSizes: true
-
- // FieldLabel {}
-
- // DoubleSpinBox {
- // from: map.min
- // to: map.max
-
- // id: dsb
- // font.pixelSize: 15
- // Layout.fillWidth: true
-
- // value: model.itemValue
-
- // stepSize: 0.1
-
- // onValueModified: model.itemValue = value
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "QColor"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // uniformCellSizes: true
-
- // FieldLabel {}
-
- // TextField {
- // id: colorField
- // font.pixelSize: 15
- // Layout.fillWidth: true
-
- // text: model.itemValue
-
- // onTextEdited: model.itemValue = text
- // }
-
- // Button {
- // Layout.fillWidth: true
- // text: "Pick"
-
- // function setColor() {
- // colorField.text = colorDialog.selectedColor
- // model.itemValue = colorDialog.selectedColor
- // colorDialog.accepted.disconnect(setColor)
- // }
-
- // onClicked: {
- // colorDialog.selectedColor = colorField.text
- // colorDialog.accepted.connect(setColor)
- // colorDialog.open()
- // }
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "list"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // uniformCellSizes: true
-
- // FieldLabel {}
-
- // function setValue(v) {
- // model.itemValue = v
- // }
-
- // ComboBox {
- // model: choices
-
- // delegate: ItemDelegate {
- // id: delegate
-
- // width: choices.width
- // contentItem: Text {
- // text: modelData
- // color: "white"
- // font.pixelSize: 15
- // elide: Text.ElideRight
- // verticalAlignment: Text.AlignVCenter
- // }
- // highlighted: choices.highlightedIndex === index
- // }
-
- // id: cb
- // font.pixelSize: 15
- // Layout.fillWidth: true
-
- // Component.onCompleted: {
- // currentIndex = choices.indexOf(itemValue)
- // currentIndexChanged.connect(updateValue)
- // }
-
- // function updateValue() {
- // setValue(valueAt(currentIndex))
- // }
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "QVariantList"
-
- // GridLayout {
- // clip: true
- // width: parent.width
-
- // rowSpacing: 0
-
- // rows: 4
- // columns: 2
-
- // FieldLabel {}
-
- // function setValue(v) {
- // model.itemValue = v
- // }
-
- // function getValue() {
- // // stupid workaround because of cancer
- // // itemValue gets corrupted to a QQmlListModel for some reason
- // // kill me
- // return model.item[model.name]
- // }
-
- // HorizontalHeaderView {
- // Layout.minimumWidth: parent.width - 90
- // Layout.row: 0
- // Layout.column: 1
-
- // Layout.fillWidth: true
-
- // Layout.minimumHeight: 30
- // Layout.columnSpan: 2
- // id: horizontalHeader
- // syncView: tbl
- // clip: true
- // }
-
- // TableView {
- // Layout.minimumWidth: parent.width - 90
- // Layout.minimumHeight: 40
- // columnSpacing: 1
- // rowSpacing: 1
- // clip: true
-
- // id: tbl
-
- // Layout.fillWidth: true
-
- // Layout.row: 1
- // Layout.column: 1
-
- // Layout.rowSpan: 3
-
- // interactive: false
-
- // function resetHeight() {
- // Layout.minimumHeight = 42 * tblModel.rowCount()
- // }
-
- // Component.onCompleted: {
- // let vl = map.valueName
- // let iv = getValue()
-
- // for (let i = 0; i < iv.length; ++i) {
- // tblModel.add(iv[i]["Value"], iv[i][vl])
- // tbl.resetHeight()
- // }
-
- // setValue(tblModel.asList())
- // tblModel.dataChanged.connect(() => setValue(tblModel.asList()))
- // }
-
- // model: MapModel {
- // id: tblModel
- // valueName: map.valueName
- // }
-
- // selectionModel: ItemSelectionModel {}
- // selectionBehavior: TableView.SelectRows
- // selectionMode: TableView.SingleSelection
-
- // delegate: Rectangle {
- // border {
- // color: Constants.palette.text
- // width: 2
- // }
-
- // required property bool selected
- // required property bool current
-
- // implicitWidth: tbl.width / 2
- // implicitHeight: 40
-
- // color: current ? "blue" : "black"
-
- // Text {
- // font.pixelSize: 15
- // anchors.centerIn: parent
- // text: display
- // color: Constants.palette.text
- // }
-
- // TableView.editDelegate: TextField {
- // font.pixelSize: 15
- // anchors.fill: parent
- // text: display
- // horizontalAlignment: TextInput.AlignHCenter
- // verticalAlignment: TextInput.AlignVCenter
- // Component.onCompleted: selectAll()
-
- // TableView.onCommit: {
- // display = text
- // }
- // }
- // }
- // }
-
- // Button {
- // Layout.alignment: Qt.AlignTop | Qt.AlignLeft
- // Layout.row: 1
- // Layout.column: 0
- // text: "Add"
-
- // onClicked: {
- // tblModel.add("", "")
- // setValue(tblModel.asList())
- // tbl.resetHeight()
- // }
- // }
-
- // Button {
- // Layout.alignment: Qt.AlignTop | Qt.AlignLeft
- // Layout.row: 2
- // Layout.column: 0
- // text: "Delete"
-
- // onClicked: {
- // tblModel.remove(tbl.currentRow)
- // setValue(tblModel.asList())
- // tbl.resetHeight()
- // }
- // }
- // }
- // }
-
- // DelegateChoice {
- // roleValue: "QSizeF"
-
- // RowLayout {
- // clip: true
- // width: parent.width
-
- // FieldLabel {
- // Layout.rowSpan: 4
- // }
-
- // Label {
- // text: "Width:"
- // font.pixelSize: 15
- // }
-
- // SpinBox {
- // from: 0
- // to: 2000
-
- // id: width
-
- // Layout.fillWidth: true
-
- // font.pixelSize: 15
- // value: model.itemValue.width
-
- // onValueModified: model.itemValue.width = value
- // }
-
- // Label {
- // text: "Height:"
- // font.pixelSize: 15
- // }
-
- // SpinBox {
- // from: 0
- // to: 2000
-
- // id: height
-
- // Layout.fillWidth: true
-
- // font.pixelSize: 15
- // value: model.itemValue.height
-
- // onValueModified: model.itemValue.height = value
- // }
- // }
- // }
- // }
- // }
-}
diff --git a/icons.qrc b/icons.qrc
index 0f014b9b..76a2c7b7 100644
--- a/icons.qrc
+++ b/icons.qrc
@@ -3,5 +3,11 @@
icons/warn.svg
icons/info.svg
icons/crit.svg
+ icons/netLight.svg
+ icons/netDark.svg
+ icons/colorLight.svg
+ icons/colorDark.svg
+ icons/miscLight.svg
+ icons/miscDark.svg
diff --git a/icons/colorDark.svg b/icons/colorDark.svg
new file mode 100644
index 00000000..a195a699
--- /dev/null
+++ b/icons/colorDark.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/icons/colorLight.svg b/icons/colorLight.svg
new file mode 100644
index 00000000..1bd2ade3
--- /dev/null
+++ b/icons/colorLight.svg
@@ -0,0 +1,8 @@
+
diff --git a/icons/miscDark.svg b/icons/miscDark.svg
new file mode 100644
index 00000000..9f1609c2
--- /dev/null
+++ b/icons/miscDark.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/icons/miscLight.svg b/icons/miscLight.svg
new file mode 100644
index 00000000..562c3ae6
--- /dev/null
+++ b/icons/miscLight.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/icons/netDark.svg b/icons/netDark.svg
new file mode 100644
index 00000000..0d67d3a7
--- /dev/null
+++ b/icons/netDark.svg
@@ -0,0 +1,8 @@
+
diff --git a/icons/netLight.svg b/icons/netLight.svg
new file mode 100644
index 00000000..3a2876d8
--- /dev/null
+++ b/icons/netLight.svg
@@ -0,0 +1,12 @@
+
diff --git a/include/Globals.h b/include/Globals.h
index b37ff016..a08078bb 100644
--- a/include/Globals.h
+++ b/include/Globals.h
@@ -6,10 +6,9 @@
// STRUCTS //
typedef struct {
- bool teamNumber;
- std::string server;
- int port;
- QString switchTopic;
+ int team;
+ std::string ip;
+ int mode;
} ServerData;
// NAMESPACES //
diff --git a/include/SettingsManager.h b/include/SettingsManager.h
index 4637c0b8..6299bb91 100644
--- a/include/SettingsManager.h
+++ b/include/SettingsManager.h
@@ -13,26 +13,24 @@ class SettingsManager : public QObject
Q_PROPERTY(bool loadRecent READ loadRecent WRITE setLoadRecent NOTIFY loadRecentChanged FINAL)
Q_PROPERTY(QStringList recentFiles READ recentFiles WRITE setRecentFiles NOTIFY recentFilesChanged FINAL)
Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QString accent READ accent WRITE setAccent NOTIFY accentChanged FINAL)
- Q_PROPERTY(bool useTeam READ useTeam WRITE setUseTeam NOTIFY useTeamChanged FINAL)
+ Q_PROPERTY(int team READ team WRITE setTeam NOTIFY teamChanged FINAL)
+ Q_PROPERTY(int mode READ mode WRITE setMode NOTIFY modeChanged FINAL)
Q_PROPERTY(QString ip READ ip WRITE setIp NOTIFY ipChanged FINAL)
- Q_PROPERTY(int port READ getPort WRITE setPort NOTIFY portChanged FINAL)
- Q_PROPERTY(QString switchTopic READ switchTopic WRITE setSwitchTopic NOTIFY switchTopicChanged FINAL)
+
public:
explicit SettingsManager(QObject *parent = nullptr);
// NT
- bool useTeam() const;
- void setUseTeam(bool newUseTeam);
-
QString ip() const;
void setIp(const QString &newIp);
- int getPort() const;
- void setPort(int newPort);
+ int team() const;
+ void setTeam(int newTeam);
- QString switchTopic() const;
- void setSwitchTopic(const QString &newTopic);
+ int mode() const;
+ void setMode(int newMode);
// other
bool loadRecent() const;
@@ -52,17 +50,14 @@ class SettingsManager : public QObject
void setAccent(const QString &newAccent);
signals:
- void useTeamChanged();
- void ipChanged();
- void portChanged();
- void switchTopicChanged();
-
void recentFilesChanged();
void loadRecentChanged();
void themeChanged();
void accentChanged();
-private:
- Q_PROPERTY(QString accent READ accent WRITE setAccent NOTIFY accentChanged FINAL)
+
+ void ipChanged();
+ void teamChanged();
+ void modeChanged();
};
#endif // SETTINGSMANAGER_H
diff --git a/include/models/AccentsListModel.h b/include/models/AccentsListModel.h
index f33e259a..32c6a3c4 100644
--- a/include/models/AccentsListModel.h
+++ b/include/models/AccentsListModel.h
@@ -55,6 +55,8 @@ class AccentsListModel : public QAbstractListModel
Q_INVOKABLE void exportJson(const QString filename);
Q_INVOKABLE void importJson(const QString filename);
+ Q_INVOKABLE QStringList names() const;
+
protected:
QHash roleNames() const override;
diff --git a/include/models/TabListModel.h b/include/models/TabListModel.h
index 390bbd9f..98979b31 100644
--- a/include/models/TabListModel.h
+++ b/include/models/TabListModel.h
@@ -57,6 +57,8 @@ class TabListModel : public QAbstractListModel
Q_INVOKABLE void loadObject(const QJsonDocument &doc);
Q_INVOKABLE void load(const QString &fileName = "");
+ Q_INVOKABLE void clear();
+
int selectedTab() const;
void selectTab(const QString &tab);
diff --git a/include/models/TabWidgetsModel.h b/include/models/TabWidgetsModel.h
index 24f2770a..7aa50e33 100644
--- a/include/models/TabWidgetsModel.h
+++ b/include/models/TabWidgetsModel.h
@@ -58,7 +58,6 @@ class TabWidgetsModel : public QAbstractListModel
Q_INVOKABLE Widget copy(int idx);
Q_INVOKABLE void add(Widget w);
Q_INVOKABLE void add(QString title, QString topic, QString type);
- Q_INVOKABLE void addCamera(QString name, QString source, QVariantList urls);
Q_INVOKABLE void setEqualTo(TabWidgetsModel *w);
diff --git a/items/MainScreen.qml b/items/MainScreen.qml
index 940d8f3a..b5059481 100644
--- a/items/MainScreen.qml
+++ b/items/MainScreen.qml
@@ -26,10 +26,6 @@ Rectangle {
onActivated: swipe.decrementCurrentIndex()
}
- function openConf(item) {
- widgetConf.openUp(item)
- }
-
function setTab() {
swipe.setCurrentIndex(tlm.selectedTab)
}
@@ -42,6 +38,9 @@ Rectangle {
}
tlm.onSelectedTabChanged.connect(setTab)
+
+ Constants.setTheme(settings.theme)
+ Constants.setAccent(settings.accent)
}
function drag(pos, fromList) {
@@ -134,10 +133,6 @@ Rectangle {
id: tabSizeDialog
}
- WidgetConfig {
- id: widgetConf
- }
-
/** SAVE */
FileDialog {
id: saveDialog
@@ -249,59 +244,12 @@ Rectangle {
}
/** SERVER SETTINGS */
- ServerDialog {
- id: serverDialog
- }
-
- function serverSettings() {
- serverDialog.open()
- }
-
- /** CUSTOM ACCENTS */
- AccentEditor {
- id: accentEditor
- }
-
- function editAccents() {
- accentEditor.open()
- }
-
- FileDialog {
- id: saveAccentDialog
- currentFolder: StandardPaths.writableLocation(
- StandardPaths.HomeLocation)
- fileMode: FileDialog.SaveFile
- defaultSuffix: "json"
- selectedNameFilter.index: 0
- nameFilters: ["JSON files (*.json)", "All files (*)"]
- }
-
- function exportAccents() {
- accents.exportJson(saveAccentDialog.selectedFile)
- }
-
- function exportAccentsAction() {
- saveAccentDialog.accepted.connect(exportAccents)
- saveAccentDialog.open()
- }
-
- FileDialog {
- id: loadAccentDialog
- currentFolder: StandardPaths.writableLocation(
- StandardPaths.HomeLocation)
- fileMode: FileDialog.OpenFile
- defaultSuffix: "json"
- selectedNameFilter.index: 0
- nameFilters: ["JSON files (*.json)", "All files (*)"]
- }
-
- function importAccents() {
- accents.importJson(loadAccentDialog.selectedFile)
+ SettingsDialog {
+ id: settingsDialog
}
- function importAccentsAction() {
- loadAccentDialog.accepted.connect(importAccents)
- loadAccentDialog.open()
+ function settingsDialog() {
+ settingsDialog.openDialog()
}
/** CONTENT */
diff --git a/main.cpp b/main.cpp
index e30f9fb5..3080b3fc 100644
--- a/main.cpp
+++ b/main.cpp
@@ -51,8 +51,7 @@ int main(int argc, char *argv[])
});
Globals::inst.StartClient4(BuildConfig.APP_NAME.toStdString());
- Globals::inst.SetServer(Globals::server.server.c_str(), NT_DEFAULT_PORT4);
- Globals::inst.StartDSClient();
+ Globals::inst.StartDSClient(NT_DEFAULT_PORT4);
Globals::inst.AddListener({{""}}, nt::EventFlags::kTopic, [topics] (const nt::Event &event) {
std::string topicName(event.GetTopicInfo()->name);
diff --git a/src/Globals.cpp b/src/Globals.cpp
index 296bf545..6aee0393 100644
--- a/src/Globals.cpp
+++ b/src/Globals.cpp
@@ -3,4 +3,4 @@
#include
nt::NetworkTableInstance Globals::inst = nt::NetworkTableInstance::GetDefault();
-ServerData Globals::server{false, "0.0.0.0", NT_DEFAULT_PORT4};
+ServerData Globals::server{0, "0.0.0.0", 0};
diff --git a/src/SettingsManager.cpp b/src/SettingsManager.cpp
index bf60a0fe..33a58faa 100644
--- a/src/SettingsManager.cpp
+++ b/src/SettingsManager.cpp
@@ -7,33 +7,28 @@ SettingsManager::SettingsManager(QObject *parent)
{}
void SettingsManager::reconnectServer() {
- std::string server = Globals::server.server;
- bool isTeamNumber = Globals::server.teamNumber;
- int port = Globals::server.port;
- QString switchTopic = Globals::server.switchTopic;
-
- if (server.empty()) return;
-
- if (isTeamNumber) {
- int team;
- try {
- team = std::stoi(server);
- } catch (std::invalid_argument const &) {
- return;
- }
-
- Globals::inst.SetServerTeam(team, port);
- } else {
- Globals::inst.SetServer(server.c_str(), port);
+ std::string server = Globals::server.ip;
+ int team = Globals::server.team;
+ int mode = Globals::server.mode;
+
+ switch (mode) {
+ // IP Address
+ case 0:
+ Globals::inst.SetServer(server.c_str(), NT_DEFAULT_PORT4);
+ break;
+ // Team Number
+ case 1:
+ Globals::inst.SetServerTeam(team, NT_DEFAULT_PORT4);
+ break;
+ // DS
+ case 2:
+ Globals::inst.StartDSClient(NT_DEFAULT_PORT4);
+ break;
+ default:
+ break;
}
Globals::inst.Disconnect();
-
- QString serverTopic = Globals::server.switchTopic;
-
- if (serverTopic != switchTopic) {
- emit switchTopicChanged();
- }
}
void SettingsManager::addRecentFile(QFile &file) {
@@ -102,50 +97,39 @@ void SettingsManager::setAccent(const QString &newAccent)
emit accentChanged();
}
-int SettingsManager::getPort() const
+QString SettingsManager::ip() const
{
- return Globals::server.port;
+ return QString::fromStdString(Globals::server.ip);
}
-void SettingsManager::setPort(int newPort)
+void SettingsManager::setIp(const QString &newIp)
{
- Globals::server.port = newPort;
- emit portChanged();
+ Globals::server.ip = newIp.toStdString();
+ emit ipChanged();
reconnectServer();
}
-QString SettingsManager::switchTopic() const
-{
- return Globals::server.switchTopic;
-}
-
-void SettingsManager::setSwitchTopic(const QString &newTopic)
-{
- Globals::server.switchTopic = newTopic;
- emit switchTopicChanged();
- reconnectServer();
-}
-QString SettingsManager::ip() const
+int SettingsManager::team() const
{
- return QString::fromStdString(Globals::server.server);
+ return Globals::server.team;
}
-void SettingsManager::setIp(const QString &newIp)
+void SettingsManager::setTeam(int newTeam)
{
- Globals::server.server = newIp.toStdString();
- emit ipChanged();
+ Globals::server.team = newTeam;
+ emit teamChanged();
reconnectServer();
}
-bool SettingsManager::useTeam() const
+int SettingsManager::mode() const
{
- return Globals::server.teamNumber;
+ return Globals::server.mode;
}
-void SettingsManager::setUseTeam(bool newUseTeam)
+void SettingsManager::setMode(int newMode)
{
- Globals::server.teamNumber = newUseTeam;
- emit useTeamChanged();
+ Globals::server.mode = newMode;
+ emit modeChanged();
reconnectServer();
}
diff --git a/src/models/AccentsListModel.cpp b/src/models/AccentsListModel.cpp
index 6eb22bdf..b3b07e1e 100644
--- a/src/models/AccentsListModel.cpp
+++ b/src/models/AccentsListModel.cpp
@@ -246,6 +246,20 @@ void AccentsListModel::importJson(const QString filename)
save();
}
+QStringList AccentsListModel::names() const
+{
+ QStringList list;
+ for (const Accent &a : m_data) {
+ // convert to title case
+ QString name = a.name;
+ QChar first = name.at(0).toUpper();
+
+ list.append(first + name.last(name.size() - 1));
+ }
+
+ return list;
+}
+
QHash AccentsListModel::roleNames() const
{
QHash rez;
diff --git a/src/models/TabListModel.cpp b/src/models/TabListModel.cpp
index a8ababd4..45054a9f 100644
--- a/src/models/TabListModel.cpp
+++ b/src/models/TabListModel.cpp
@@ -123,8 +123,8 @@ void TabListModel::save(const QString &filename)
QJsonDocument TabListModel::saveObject() const
{
QJsonObject doc;
- doc.insert("useTeamNumber", m_settings->useTeam());
- doc.insert("port", m_settings->getPort());
+ doc.insert("mode", m_settings->mode());
+ doc.insert("team", m_settings->team());
doc.insert("ip", m_settings->ip());
QJsonArray arr;
@@ -149,9 +149,9 @@ void TabListModel::loadObject(const QJsonDocument &doc)
{
QJsonObject ob = doc.object();
- Globals::server.server = ob.value("ip").toString().toStdString();
- Globals::server.port = ob.value("port").toInt();
- Globals::server.teamNumber = ob.value("useTeamNumber").toBool();
+ Globals::server.ip = ob.value("ip").toString().toStdString();
+ Globals::server.team = ob.value("team").toInteger();
+ Globals::server.mode = ob.value("mode").toInteger();
m_settings->reconnectServer();
@@ -190,14 +190,20 @@ void TabListModel::load(const QString &filename)
QByteArray data = stream.readAll().toUtf8();
QJsonDocument doc = QJsonDocument::fromJson(data);
- beginResetModel();
- m_data.clear();
- endResetModel();
+
+ clear();
loadObject(doc);
file.close();
}
+void TabListModel::clear()
+{
+ beginResetModel();
+ m_data.clear();
+ endResetModel();
+}
+
int TabListModel::selectedTab() const
{
return m_selectedTab;
diff --git a/src/models/TabWidgetsModel.cpp b/src/models/TabWidgetsModel.cpp
index 55bfc838..558d0f61 100644
--- a/src/models/TabWidgetsModel.cpp
+++ b/src/models/TabWidgetsModel.cpp
@@ -131,54 +131,6 @@ void TabWidgetsModel::add(QString title, QString topic, QString type)
emit unoccupiedCellsChanged();
}
-void TabWidgetsModel::addCamera(QString name, QString source, QVariantList urls)
-{
- Widget w;
- w.title = name;
- w.type = "camera";
-
- w.properties.insert("name", name);
- w.properties.insert("source", source);
-
- QUrl url;
- if (urls.empty()) {
- url = source;
- } else {
- for (const QVariant &u : urls) {
- // pure, unfaltered cancer
- QString str = u.value().toString();
-
- if (str.contains(".local")) {
- continue;
- }
-
- url = str;
- }
-
- if (url.isEmpty()) {
- url = urls.at(0).value().toString();
- }
- }
-
- if (!url.isEmpty()) {
- QStringList split = url.toString().split(":");
- w.properties.insert("host", (split.at(0) + ":" + split.at(1)));;
- w.properties.insert("port", split.at(2).split("/").at(0).toInt());
- }
-
- w.row = -1;
- w.col = -1;
-
- w.rowSpan = 1;
- w.colSpan = 1;
-
- beginInsertRows(QModelIndex(), rowCount(), rowCount());
- m_data << w;
- endInsertRows();
-
- emit unoccupiedCellsChanged();
-}
-
void TabWidgetsModel::setEqualTo(TabWidgetsModel *w)
{
beginResetModel();
diff --git a/widgets/BaseWidget.qml b/widgets/BaseWidget.qml
index c32b70d1..7ab30085 100644
--- a/widgets/BaseWidget.qml
+++ b/widgets/BaseWidget.qml
@@ -106,7 +106,6 @@ Rectangle {
MenuItem {
text: "Configure"
- // onTriggered: openConf(rcMenu.parent)
onTriggered: config.openDialog()
}
diff --git a/widgets/config/LabeledComboBox.qml b/widgets/config/LabeledComboBox.qml
index cd719e47..642b22a3 100644
--- a/widgets/config/LabeledComboBox.qml
+++ b/widgets/config/LabeledComboBox.qml
@@ -21,6 +21,8 @@ ComboBox {
model: choices
font.pixelSize: 15
+ height: 50
+
function open() {
currentIndex = indexOfValue(bindTarget[bindedProperty])
}
diff --git a/widgets/config/LabeledDoubleSpinBox.qml b/widgets/config/LabeledDoubleSpinBox.qml
index e7a6f3f7..84ce768d 100644
--- a/widgets/config/LabeledDoubleSpinBox.qml
+++ b/widgets/config/LabeledDoubleSpinBox.qml
@@ -19,6 +19,8 @@ DoubleSpinBox {
from: -1E9
to: 1E9
+ height: 50
+
font.pixelSize: 18
function open() {
diff --git a/widgets/misc/CameraView.qml b/widgets/misc/CameraView.qml
index 09809112..14a2226c 100644
--- a/widgets/misc/CameraView.qml
+++ b/widgets/misc/CameraView.qml
@@ -46,8 +46,6 @@ BaseWidget {
--i
}
}
-
- console.log(value)
}
function updateTopic(ntTopic, ntValue) {
diff --git a/widgets/primitive/IntDialWidget.qml b/widgets/primitive/IntDialWidget.qml
index 8437d3ca..cd519b71 100644
--- a/widgets/primitive/IntDialWidget.qml
+++ b/widgets/primitive/IntDialWidget.qml
@@ -1,9 +1,12 @@
import QtQuick
import QtQuick.Controls 6.6
+import QtQuick.Layouts 6.6
import QFRCDashboard
BaseWidget {
+ id: widget
+
property string item_topic
property int item_fontSize: 15
@@ -159,4 +162,172 @@ BaseWidget {
spin.value = topicStore.getValue(item_topic)
dial.value = topicStore.getValue(item_topic)
}
+
+ BaseConfigDialog {
+ id: config
+
+ height: 600
+
+ function openDialog() {
+ topicField.open()
+ titleFontField.open()
+ fontField.open()
+
+ upField.open()
+ lowField.open()
+ stepField.open()
+ startField.open()
+ endField.open()
+
+ open()
+ }
+
+ onAccepted: {
+ topicField.accept()
+ titleFontField.accept()
+ fontField.accept()
+ upField.accept()
+ lowField.accept()
+ stepField.accept()
+ startField.accept()
+ endField.accept()
+ }
+
+ ColumnLayout {
+ id: layout
+ spacing: 25
+
+ anchors {
+ top: parent.top
+ bottom: parent.bottom
+ left: parent.left
+ right: parent.right
+
+ topMargin: config.headerHeight + 12
+ bottomMargin: 45
+
+ leftMargin: 5
+ rightMargin: 5
+ }
+
+ SectionHeader {
+ label: "Font Settings"
+ }
+
+ RowLayout {
+ uniformCellSizes: true
+
+ LabeledSpinBox {
+ Layout.fillWidth: true
+
+ id: titleFontField
+
+ label: "Title Font Size"
+
+ bindedProperty: "item_titleFontSize"
+ bindTarget: widget
+ }
+
+ LabeledSpinBox {
+ Layout.fillWidth: true
+
+ id: fontField
+
+ label: "Font Size"
+
+ bindedProperty: "item_fontSize"
+ bindTarget: widget
+ }
+ }
+
+ SectionHeader {
+ label: "Spin Box Settings"
+ }
+
+ RowLayout {
+ uniformCellSizes: true
+
+ LabeledSpinBox {
+ Layout.fillWidth: true
+
+ id: lowField
+
+ label: "Lower Bound"
+
+ bindedProperty: "item_lowerBound"
+ bindTarget: widget
+ }
+
+ LabeledSpinBox {
+ Layout.fillWidth: true
+
+ id: upField
+
+ label: "Upper Bound"
+
+ bindedProperty: "item_upperBound"
+ bindTarget: widget
+ }
+ }
+
+ LabeledSpinBox {
+ Layout.fillWidth: true
+
+ id: stepField
+
+ label: "Step Size"
+
+ bindedProperty: "item_stepSize"
+ bindTarget: widget
+
+ from: 0
+ }
+
+ SectionHeader {
+ label: "Dial Settings"
+ }
+
+ RowLayout {
+ uniformCellSizes: true
+
+ LabeledDoubleSpinBox {
+ Layout.fillWidth: true
+
+ id: startField
+
+ label: "Start Angle"
+
+ bindedProperty: "item_startAngle"
+ bindTarget: widget
+ }
+
+ LabeledDoubleSpinBox {
+ Layout.fillWidth: true
+
+ id: endField
+
+ label: "End Angle"
+
+ bindedProperty: "item_endAngle"
+ bindTarget: widget
+ }
+ }
+
+ SectionHeader {
+ label: "NT Settings"
+ }
+
+ LabeledTextField {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignTop
+
+ id: topicField
+
+ label: "Topic"
+
+ bindedProperty: "item_topic"
+ bindTarget: widget
+ }
+ }
+ }
}