ConnectionStatus.qml 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. import QtQuick.Layouts 1.15
  4. import "." as Components
  5. // Connection dot + the connected table's name (firmware hostname), shown in
  6. // every page header. Tapping it opens the table switcher: a dropdown of the
  7. // tables discovered on the network, one tap to jump between them.
  8. Rectangle {
  9. id: connectionStatus
  10. property var backend: null
  11. readonly property bool connected: backend && backend.serialConnected
  12. readonly property string tableName: connected ? (backend.tableName || "Table") : "No table"
  13. implicitHeight: 40
  14. implicitWidth: statusRow.implicitWidth + 2 * Components.ThemeManager.spaceMd
  15. radius: height / 2
  16. color: switchArea.pressed || tablePopup.opened
  17. ? Components.ThemeManager.pressedColor : "transparent"
  18. Row {
  19. id: statusRow
  20. anchors.centerIn: parent
  21. spacing: 6
  22. Rectangle {
  23. width: 9
  24. height: 9
  25. radius: 4.5
  26. anchors.verticalCenter: parent.verticalCenter
  27. color: connectionStatus.connected ? Components.ThemeManager.ok
  28. : Components.ThemeManager.danger
  29. Behavior on color {
  30. ColorAnimation {
  31. duration: 300
  32. easing.type: Easing.OutQuart
  33. }
  34. }
  35. }
  36. Text {
  37. anchors.verticalCenter: parent.verticalCenter
  38. text: connectionStatus.tableName
  39. font.family: Components.ThemeManager.fontMedium
  40. font.pixelSize: Components.ThemeManager.fontSizeCaption
  41. color: Components.ThemeManager.textSecondary
  42. }
  43. Components.Icon {
  44. anchors.verticalCenter: parent.verticalCenter
  45. name: "expand_more"
  46. size: 16
  47. color: Components.ThemeManager.textTertiary
  48. }
  49. }
  50. MouseArea {
  51. id: switchArea
  52. anchors.fill: parent
  53. onClicked: {
  54. if (!backend)
  55. return
  56. backend.refreshSerialPorts() // fresh mDNS browse while the list shows
  57. tablePopup.open()
  58. }
  59. }
  60. Popup {
  61. id: tablePopup
  62. y: parent.height + Components.ThemeManager.spaceSm
  63. x: 0
  64. width: 300
  65. padding: Components.ThemeManager.spaceMd
  66. closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
  67. background: Rectangle {
  68. color: Components.ThemeManager.surfaceColor
  69. radius: Components.ThemeManager.radiusMd
  70. border.color: Components.ThemeManager.borderColor
  71. border.width: 1
  72. }
  73. contentItem: ColumnLayout {
  74. spacing: Components.ThemeManager.spaceSm
  75. SectionLabel {
  76. text: "Switch table"
  77. Layout.leftMargin: Components.ThemeManager.spaceXs
  78. }
  79. Repeater {
  80. model: backend ? backend.discoveredTables : []
  81. delegate: Rectangle {
  82. required property var modelData
  83. readonly property bool isCurrent:
  84. connectionStatus.connected && modelData.url === backend.currentPort
  85. Layout.fillWidth: true
  86. Layout.preferredHeight: 56
  87. radius: Components.ThemeManager.radiusSm
  88. color: isCurrent ? Components.ThemeManager.accentSoft
  89. : (rowArea.pressed ? Components.ThemeManager.pressedColor
  90. : Components.ThemeManager.cardColor)
  91. border.width: 1
  92. border.color: isCurrent ? Components.ThemeManager.accent
  93. : Components.ThemeManager.borderLight
  94. RowLayout {
  95. anchors.fill: parent
  96. anchors.leftMargin: Components.ThemeManager.spaceMd
  97. anchors.rightMargin: Components.ThemeManager.spaceMd
  98. spacing: Components.ThemeManager.spaceSm
  99. Column {
  100. Layout.fillWidth: true
  101. spacing: 1
  102. Label {
  103. text: modelData.name || modelData.url
  104. font.family: Components.ThemeManager.fontMedium
  105. font.pixelSize: Components.ThemeManager.fontSizeBody
  106. color: Components.ThemeManager.textPrimary
  107. elide: Text.ElideRight
  108. width: parent.width
  109. }
  110. Label {
  111. text: modelData.url
  112. font.family: Components.ThemeManager.fontBody
  113. font.pixelSize: 11
  114. color: Components.ThemeManager.textTertiary
  115. elide: Text.ElideRight
  116. width: parent.width
  117. }
  118. }
  119. Components.Icon {
  120. visible: parent.parent.isCurrent
  121. name: "check"
  122. size: 18
  123. color: Components.ThemeManager.accent
  124. }
  125. }
  126. MouseArea {
  127. id: rowArea
  128. anchors.fill: parent
  129. enabled: !parent.isCurrent
  130. onClicked: {
  131. if (backend)
  132. backend.connectSerial(parent.modelData.url)
  133. tablePopup.close()
  134. }
  135. }
  136. }
  137. }
  138. Label {
  139. visible: !backend || backend.discoveredTables.length === 0
  140. text: "Searching your network for tables..."
  141. font.family: Components.ThemeManager.fontBody
  142. font.pixelSize: Components.ThemeManager.fontSizeCaption
  143. color: Components.ThemeManager.textTertiary
  144. Layout.fillWidth: true
  145. Layout.margins: Components.ThemeManager.spaceXs
  146. wrapMode: Text.WordWrap
  147. }
  148. }
  149. }
  150. }