KCM.qml 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (C) 2015 Malte Veerman <maldela@halloarsch.de>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. *
  18. */
  19. import QtQuick 2.4
  20. import QtQuick.Controls 1.3
  21. import QtQuick.Layouts 1.1
  22. import QtQuick.Dialogs 1.2
  23. import org.kde.kcm 1.0
  24. import "../scripts/units.js" as Units
  25. Item {
  26. property QtObject base: kcm.base
  27. property var locale: Qt.locale()
  28. property real textWidth: 0
  29. property QtObject pwmFanModel: base ? base.pwmFanModel : null
  30. property QtObject tempModel: base ? base.tempModel : null
  31. property var pwmFans: pwmFanModel ? pwmFanModel.fans : null
  32. id: root
  33. implicitWidth: 1024
  34. implicitHeight: 768
  35. ColumnLayout {
  36. id: noFansInfo
  37. width: parent.width
  38. anchors.verticalCenter: parent.verticalCenter
  39. spacing: 20
  40. visible: pwmFanModel.count == 0
  41. Label {
  42. Layout.alignment: Qt.AlignCenter
  43. text: i18n("There are no pwm capable fans in your system.")
  44. font.pointSize: 14
  45. font.bold: true
  46. }
  47. Button {
  48. Layout.alignment: Qt.AlignCenter
  49. text: i18n("Detect fans")
  50. iconName: kcm.needsAuthorization ? "dialog-password" : ""
  51. onClicked: kcm.loader.detectSensors()
  52. }
  53. }
  54. CheckBox {
  55. id: enabledBox
  56. visible: pwmFanModel.count > 0
  57. Layout.alignment: Qt.AlignLeft | Qt.AlignTop
  58. text: i18n("Control fans manually")
  59. checked: kcm.manualControl
  60. onCheckedChanged: kcm.manualControl = checked
  61. Connections {
  62. target: kcm
  63. onManualControlChanged: enabledBox.checked = kcm.manualControl
  64. }
  65. }
  66. ColumnLayout {
  67. width: parent.width
  68. anchors.bottom: parent.bottom
  69. anchors.top: enabledBox.bottom
  70. visible: enabledBox.checked
  71. RowLayout {
  72. visible: enabledBox.checked && pwmFanModel.count > 0
  73. Label {
  74. text: i18n("Fan:")
  75. Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
  76. renderType: Text.NativeRendering
  77. }
  78. ComboBox {
  79. id: fanComboBox
  80. model: pwmFanModel
  81. textRole: "display"
  82. Layout.fillWidth: true
  83. Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
  84. }
  85. Button {
  86. Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
  87. text: i18n("Detect fans")
  88. iconName: kcm.needsAuthorization ? "dialog-password" : ""
  89. onClicked: kcm.loader.detectSensors()
  90. }
  91. }
  92. Loader {
  93. Layout.fillWidth: true
  94. Layout.fillHeight: true
  95. active: !!pwmFans[fanComboBox.currentIndex]
  96. sourceComponent: PwmFan {
  97. unit: kcm.base.unit
  98. fan: pwmFans[fanComboBox.currentIndex]
  99. systemdCom: kcm.systemdCom
  100. tempModel: root.tempModel
  101. minTemp: kcm.base.minTemp
  102. maxTemp: kcm.base.maxTemp
  103. }
  104. }
  105. Row {
  106. property bool expanded: false
  107. id: expand
  108. Image {
  109. id: arrow
  110. source: parent.expanded ? "image://icon/go-down" : "image://icon/go-next"
  111. fillMode: Image.PreserveAspectFit
  112. height: advancedLabel.implicitHeight
  113. }
  114. Label {
  115. id: advancedLabel
  116. text: i18n("Advanced settings")
  117. font.bold: true
  118. }
  119. }
  120. MouseArea {
  121. anchors.fill: expand
  122. onClicked: expand.expanded = expand.expanded ? false : true
  123. }
  124. RowLayout {
  125. visible: expand.expanded
  126. Label {
  127. Layout.preferredWidth: root.textWidth
  128. clip: true
  129. text: i18n("Interval:")
  130. horizontalAlignment: Text.AlignRight
  131. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  132. }
  133. SpinBox {
  134. Layout.minimumWidth: implicitWidth
  135. Layout.fillWidth: true
  136. value: base.loader ? base.loader.interval : 1
  137. suffix: " " + (value > 1 ? i18n("seconds") : i18n("second"))
  138. minimumValue: 1.0
  139. onValueChanged: base.loader.interval = value
  140. }
  141. }
  142. RowLayout {
  143. visible: expand.expanded
  144. Label {
  145. Layout.preferredWidth: root.textWidth
  146. clip: true
  147. text: i18n("Minimum temperature for fan graphs:")
  148. horizontalAlignment: Text.AlignRight
  149. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  150. }
  151. SpinBox {
  152. id: minTempBox
  153. Layout.minimumWidth: implicitWidth
  154. Layout.fillWidth: true
  155. decimals: 2
  156. maximumValue: maxTempBox.value
  157. minimumValue: Units.fromKelvin(0, base.unit)
  158. value: Units.fromCelsius(base.minTemp, base.unit)
  159. suffix: base.unit == 0 ? i18n("°C") : base.unit == 1 ? i18n("K") : i18n("°F")
  160. onValueChanged: base.minTemp = value
  161. }
  162. }
  163. RowLayout {
  164. visible: expand.expanded
  165. Label {
  166. Layout.preferredWidth: root.textWidth
  167. clip: true
  168. text: i18n("Maximum temperature for fan graphs:")
  169. horizontalAlignment: Text.AlignRight
  170. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  171. }
  172. SpinBox {
  173. id: maxTempBox
  174. Layout.minimumWidth: implicitWidth
  175. Layout.fillWidth: true
  176. decimals: 2
  177. maximumValue: Number.POSITIVE_INFINITY
  178. minimumValue: minTempBox.value
  179. value: Units.fromCelsius(base.maxTemp, base.unit)
  180. suffix: base.unit == 0 ? i18n("°C") : base.unit == 1 ? i18n("K") : i18n("°F")
  181. onValueChanged: base.maxTemp = value
  182. }
  183. }
  184. RowLayout {
  185. visible: expand.expanded
  186. Label {
  187. Layout.preferredWidth: root.textWidth
  188. clip: true
  189. text: i18n("Name of the fancontrol systemd service:")
  190. horizontalAlignment: Text.AlignRight
  191. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  192. }
  193. OptionInput {
  194. Layout.minimumWidth: implicitWidth
  195. Layout.fillWidth: true
  196. color: base.systemdCom.serviceExists ? "green" : "red"
  197. value: base.serviceName
  198. onTextChanged: base.serviceName = text
  199. }
  200. }
  201. RowLayout {
  202. visible: expand.expanded
  203. Label {
  204. Layout.preferredWidth: root.textWidth
  205. clip: true
  206. text: i18n("Path to the fancontrol config file:")
  207. horizontalAlignment: Text.AlignRight
  208. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  209. }
  210. OptionInput {
  211. Layout.minimumWidth: implicitWidth
  212. Layout.fillWidth: true
  213. text: base.configUrl.toString().replace("file://", "")
  214. color: base.configValid ? "green" : "red"
  215. onTextChanged: base.configUrl = text
  216. }
  217. Button {
  218. action: loadAction
  219. }
  220. }
  221. }
  222. Action {
  223. id: loadAction
  224. iconName: "document-open"
  225. onTriggered: openFileDialog.open()
  226. tooltip: i18n("Load configuration file")
  227. shortcut: StandardKey.Open
  228. }
  229. FileDialog {
  230. id: openFileDialog
  231. title: i18n("Please choose a configuration file")
  232. folder: "file:///etc"
  233. selectExisting: true
  234. selectMultiple: false
  235. onAccepted: base.configUrl = fileUrl;
  236. }
  237. ErrorDialog {
  238. id: errorDialog
  239. modality: Qt.ApplicationModal
  240. text: base.loader.error
  241. }
  242. Connections {
  243. target: base.loader
  244. onCriticalError: errorDialog.open()
  245. }
  246. }