KCM.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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.2
  22. import QtQuick.Dialogs 1.2
  23. import org.kde.kcm 1.0
  24. import Fancontrol.Qml 1.0 as Fancontrol
  25. Item {
  26. property QtObject loader: Fancontrol.base.loader
  27. property QtObject systemdCom: Fancontrol.base.systemdCom
  28. property QtObject pwmFanModel: Fancontrol.base.pwmFanModel
  29. property QtObject tempModel: Fancontrol.base.tempModel
  30. property var locale: Qt.locale()
  31. property real textWidth: 0
  32. property var pwmFans: pwmFanModel ? pwmFanModel.fans : []
  33. id: root
  34. implicitWidth: 1024
  35. implicitHeight: 768
  36. Connections {
  37. target: loader
  38. onConfigFileChanged: kcm.needsSave = true
  39. }
  40. Connections {
  41. target: Fancontrol.base
  42. onMinTempChanged: kcm.needsSave = true
  43. onMaxTempChanged: kcm.needsSave = true
  44. onServiceNameChanged: kcm.needsSave = true
  45. onConfigUrlChanged: kcm.needsSave = true
  46. }
  47. Connections {
  48. target: kcm
  49. onAboutToSave: {
  50. base.save(true);
  51. if (systemdCom.serviceActive && enabledBox.checked) {
  52. systemdCom.restartService();
  53. } else {
  54. systemdCom.serviceActive = enabledBox.checked;
  55. }
  56. systemdCom.serviceEnabled = enabledBox.checked;
  57. }
  58. onAboutToLoad: {
  59. Fancontrol.base.load();
  60. enabledBox.checked = systemdCom.serviceEnabled && systemdCom.serviceActive;
  61. }
  62. onAboutToDefault: enabledBox.checked = false
  63. }
  64. ColumnLayout {
  65. id: noFansInfo
  66. width: parent.width
  67. anchors.verticalCenter: parent.verticalCenter
  68. spacing: 20
  69. visible: pwmFans.length === 0
  70. Label {
  71. Layout.alignment: Qt.AlignCenter
  72. text: i18n("There are no pwm capable fans in your system.")
  73. font.pointSize: 14
  74. font.bold: true
  75. }
  76. Button {
  77. Layout.alignment: Qt.AlignCenter
  78. text: loader.sensorsDetected ? i18n("Detect fans again") : i18n("Detect fans")
  79. iconName: kcm.needsAuthorization ? "dialog-password" : ""
  80. onClicked: loader.detectSensors()
  81. }
  82. }
  83. CheckBox {
  84. id: enabledBox
  85. anchors.top: parent.top
  86. visible: pwmFans.length > 0
  87. text: i18n("Control fans manually")
  88. checked: systemdCom.serviceEnabled && systemdCom.serviceActive;
  89. onCheckedChanged: if (checked !== systemdCom.serviceActive || checked !== systemdCom.serviceEnabled) kcm.needsSave = true
  90. }
  91. ColumnLayout {
  92. id: bodyLayout
  93. width: parent.width
  94. anchors.bottom: advancedButton.top
  95. anchors.top: enabledBox.bottom
  96. anchors.bottomMargin: advancedButton.height / 4
  97. visible: enabledBox.checked
  98. RowLayout {
  99. visible: enabledBox.checked && pwmFanModel.count > 0
  100. Label {
  101. text: i18n("Fan:")
  102. Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
  103. renderType: Text.NativeRendering
  104. }
  105. ComboBox {
  106. id: fanComboBox
  107. model: pwmFanModel
  108. textRole: "display"
  109. Layout.fillWidth: true
  110. Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
  111. }
  112. Button {
  113. Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
  114. text: i18n("Detect fans")
  115. iconName: kcm.needsAuthorization ? "dialog-password" : ""
  116. onClicked: loader.detectSensors()
  117. }
  118. }
  119. Loader {
  120. Layout.fillWidth: true
  121. Layout.fillHeight: true
  122. active: !!pwmFans[fanComboBox.currentIndex]
  123. sourceComponent: Fancontrol.PwmFan {
  124. unit: Fancontrol.base.unit
  125. fan: pwmFans[fanComboBox.currentIndex]
  126. systemdCom: root.systemdCom
  127. tempModel: root.tempModel
  128. minTemp: Fancontrol.base.minTemp
  129. maxTemp: Fancontrol.base.maxTemp
  130. }
  131. }
  132. }
  133. Item {
  134. id: advancedButton
  135. property bool expanded: false
  136. anchors.bottom: settingsArea.top
  137. width: parent.width
  138. height: advancedArrow.height
  139. visible: enabledBox.checked
  140. Image {
  141. id: advancedArrow
  142. source: parent.expanded ? "image://icon/go-down" : "image://icon/go-next"
  143. fillMode: Image.PreserveAspectFit
  144. height: advancedLabel.implicitHeight
  145. }
  146. Label {
  147. id: advancedLabel
  148. anchors.left: advancedArrow.right
  149. text: i18n("Advanced settings")
  150. font.bold: true
  151. }
  152. MouseArea {
  153. anchors.fill: parent
  154. onClicked: parent.expanded = !parent.expanded
  155. }
  156. }
  157. ColumnLayout {
  158. id: settingsArea
  159. visible: enabledBox.checked && parent.height - enabledBox.height - bodyLayout.height - advancedButton.height > height
  160. width: parent.width
  161. anchors.bottom: parent.bottom
  162. clip: true
  163. state: advancedButton.expanded ? "VISIBLE" : "HIDDEN"
  164. states: [
  165. State {
  166. name: "VISIBLE"
  167. PropertyChanges {
  168. target: settingsArea
  169. height: settingsArea.implicitHeight
  170. }
  171. },
  172. State {
  173. name: "HIDDEN"
  174. PropertyChanges {
  175. target: settingsArea
  176. height: 0
  177. }
  178. }
  179. ]
  180. transitions: Transition {
  181. NumberAnimation {
  182. properties: "height"
  183. easing.type: Easing.InOutQuad
  184. }
  185. }
  186. RowLayout {
  187. width: parent.width
  188. Label {
  189. Layout.preferredWidth: root.textWidth
  190. clip: true
  191. text: i18n("Interval:")
  192. horizontalAlignment: Text.AlignRight
  193. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  194. }
  195. SpinBox {
  196. Layout.minimumWidth: implicitWidth
  197. Layout.fillWidth: true
  198. value: !!loader ? loader.interval : 1
  199. suffix: " " + i18np("second", "seconds", loader.interval)
  200. minimumValue: 1.0
  201. onValueChanged: loader.interval = value
  202. }
  203. }
  204. RowLayout {
  205. width: parent.width
  206. Label {
  207. Layout.preferredWidth: root.textWidth
  208. clip: true
  209. text: i18n("Minimum temperature for fan graphs:")
  210. horizontalAlignment: Text.AlignRight
  211. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  212. }
  213. SpinBox {
  214. id: minTempBox
  215. Layout.minimumWidth: implicitWidth
  216. Layout.fillWidth: true
  217. decimals: 2
  218. maximumValue: maxTempBox.value
  219. minimumValue: Units.fromKelvin(0, Fancontrol.base.unit)
  220. value: Units.fromCelsius(Fancontrol.base.minTemp, Fancontrol.base.unit)
  221. suffix: Fancontrol.base.unit == 0 ? i18n("°C") : Fancontrol.base.unit == 1 ? i18n("K") : i18n("°F")
  222. onValueChanged: Fancontrol.base.minTemp = value
  223. }
  224. }
  225. RowLayout {
  226. width: parent.width
  227. Label {
  228. Layout.preferredWidth: root.textWidth
  229. clip: true
  230. text: i18n("Maximum temperature for fan graphs:")
  231. horizontalAlignment: Text.AlignRight
  232. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  233. }
  234. SpinBox {
  235. id: maxTempBox
  236. Layout.minimumWidth: implicitWidth
  237. Layout.fillWidth: true
  238. decimals: 2
  239. maximumValue: Number.POSITIVE_INFINITY
  240. minimumValue: minTempBox.value
  241. value: Units.fromCelsius(Fancontrol.base.maxTemp, Fancontrol.base.unit)
  242. suffix: Fancontrol.base.unit == 0 ? i18n("°C") : Fancontrol.base.unit == 1 ? i18n("K") : i18n("°F")
  243. onValueChanged: Fancontrol.base.maxTemp = value
  244. }
  245. }
  246. RowLayout {
  247. width: parent.width
  248. Label {
  249. Layout.preferredWidth: root.textWidth
  250. clip: true
  251. text: i18n("Name of the fancontrol systemd service:")
  252. horizontalAlignment: Text.AlignRight
  253. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  254. }
  255. Fancontrol.OptionInput {
  256. Layout.minimumWidth: implicitWidth
  257. Layout.fillWidth: true
  258. color: systemdCom.serviceExists ? "green" : "red"
  259. value: Fancontrol.base.serviceName
  260. onTextChanged: Fancontrol.base.serviceName = text
  261. }
  262. }
  263. RowLayout {
  264. width: parent.width
  265. Label {
  266. Layout.preferredWidth: root.textWidth
  267. clip: true
  268. text: i18n("Path to the fancontrol config file:")
  269. horizontalAlignment: Text.AlignRight
  270. Component.onCompleted: root.textWidth = Math.max(root.textWidth, contentWidth)
  271. }
  272. Fancontrol.OptionInput {
  273. Layout.minimumWidth: implicitWidth
  274. Layout.fillWidth: true
  275. text: Fancontrol.base.configUrl.toString().replace("file://", "")
  276. color: Fancontrol.base.configValid ? "green" : "red"
  277. onTextChanged: Fancontrol.base.configUrl = text
  278. }
  279. Button {
  280. action: loadAction
  281. }
  282. }
  283. }
  284. Action {
  285. id: loadAction
  286. iconName: "document-open"
  287. onTriggered: openFileDialog.open()
  288. tooltip: i18n("Load configuration file")
  289. shortcut: StandardKey.Open
  290. }
  291. FileDialog {
  292. id: openFileDialog
  293. title: i18n("Please choose a configuration file")
  294. folder: "file:///etc"
  295. selectExisting: true
  296. selectMultiple: false
  297. onAccepted: Fancontrol.base.configUrl = fileUrl;
  298. }
  299. Fancontrol.ErrorDialog {
  300. id: errorDialog
  301. modality: Qt.ApplicationModal
  302. loader: root.loader
  303. }
  304. }