Changeset View
Changeset View
Standalone View
Standalone View
Modules/energy/package/contents/ui/main.qml
Show All 10 Lines | |||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
12 | * GNU General Public License for more details. * | 12 | * GNU General Public License for more details. * | ||
13 | * * | 13 | * * | ||
14 | * You should have received a copy of the GNU General Public License * | 14 | * You should have received a copy of the GNU General Public License * | ||
15 | * along with this program; if not, write to the * | 15 | * along with this program; if not, write to the * | ||
16 | * Free Software Foundation, Inc., * | 16 | * Free Software Foundation, Inc., * | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * | 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * | ||
18 | ***************************************************************************/ | 18 | ***************************************************************************/ | ||
19 | 19 | | |||
20 | import QtQuick 2.2 | 20 | import QtQuick 2.5 | ||
broulik: and also getting rid of QQC1 | |||||
21 | import QtQuick.Controls 1.3 | 21 | import QtQuick.Controls 2.12 | ||
I might be too aggressive here, what would be the best version to set here ? meven: I might be too aggressive here, what would be the best version to set here ? | |||||
ngraham: 2.5 is always a safe bet. | |||||
22 | import QtQuick.Controls 2.0 as QQC2 | | |||
23 | import QtQuick.Layouts 1.1 | 22 | import QtQuick.Layouts 1.1 | ||
23 | import org.kde.kirigami 2.5 as Kirigami | ||||
24 | 24 | | |||
25 | import org.kde.kquickcontrolsaddons 2.0 | 25 | import org.kde.kquickcontrolsaddons 2.0 | ||
26 | import org.kde.kinfocenter.energy.private 1.0 | 26 | import org.kde.kinfocenter.energy.private 1.0 | ||
27 | 27 | | |||
28 | //We need units from it | 28 | //We need units from it | ||
29 | import org.kde.plasma.core 2.0 as PlasmaCore | 29 | import org.kde.plasma.core 2.0 as PlasmaCore | ||
broulik: A goal is to get rid of these plasma imports, too | |||||
Now that you've imported Kirigami, you can use Kirigami.Units and drop the PlasmaCore import filipf: Now that you've imported Kirigami, you can use Kirigami.Units and drop the PlasmaCore import | |||||
30 | import org.kde.plasma.extras 2.0 as PlasmaExtras | 30 | import org.kde.plasma.extras 2.0 as PlasmaExtras | ||
31 | 31 | | |||
32 | import org.kde.plasma.workspace.components 2.0 as WorkspaceComponents | 32 | import org.kde.plasma.workspace.components 2.0 as WorkspaceComponents | ||
33 | 33 | | |||
34 | Item { | 34 | Item { | ||
35 | id: root | 35 | id: root | ||
36 | property QtObject currentBattery: null | 36 | property QtObject currentBattery: null | ||
37 | property string currentUdi: "" | 37 | property string currentUdi: "" | ||
38 | property bool compact: (root.width / units.gridUnit) < 25 | 38 | property bool compact: (root.width / units.gridUnit) < 25 | ||
39 | 39 | | |||
40 | onCurrentBatteryChanged: { | 40 | onCurrentBatteryChanged: { | ||
41 | if (!currentBattery) { | 41 | if (!currentBattery) { | ||
42 | currentBattery = kcm.batteries.get(0) | 42 | currentBattery = kcm.batteries.get(0) | ||
43 | currentUdi = kcm.batteries.udi(0) | 43 | currentUdi = kcm.batteries.udi(0) | ||
44 | } | 44 | } | ||
45 | } | 45 | } | ||
46 | 46 | | |||
47 | SystemPalette { id: sysPal; colorGroup: SystemPalette.Active } | 47 | SystemPalette { id: sysPal; colorGroup: SystemPalette.Active } | ||
48 | 48 | | |||
filipf: there is trailing space in this row | |||||
49 | property bool showWakeUps: true | 49 | property bool showWakeUps: true | ||
50 | property int historyType: HistoryModel.ChargeType | 50 | property int historyType: HistoryModel.ChargeType | ||
51 | 51 | | |||
52 | readonly property var details: [ | 52 | readonly property var details: [ | ||
53 | { | 53 | { | ||
54 | title: i18n("Battery"), | 54 | title: i18n("Battery"), | ||
55 | data: [ | 55 | data: [ | ||
56 | {label: i18n("Rechargeable"), value: "rechargeable"}, | 56 | {label: i18n("Rechargeable"), value: "rechargeable"}, | ||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | |||||
102 | Component.onCompleted: { | 102 | Component.onCompleted: { | ||
103 | currentBattery = kcm.batteries.get(0) | 103 | currentBattery = kcm.batteries.get(0) | ||
104 | currentUdi = kcm.batteries.udi(0) | 104 | currentUdi = kcm.batteries.udi(0) | ||
105 | } | 105 | } | ||
106 | 106 | | |||
107 | implicitWidth: units.gridUnit * 25 | 107 | implicitWidth: units.gridUnit * 25 | ||
108 | implicitHeight: !!currentBattery ? units.gridUnit * 25 : units.gridUnit * 12 | 108 | implicitHeight: !!currentBattery ? units.gridUnit * 25 : units.gridUnit * 12 | ||
109 | 109 | | |||
110 | SystemPalette { | 110 | readonly property var timespanComboChoices: [i18n("Last hour"),i18n("Last 2 hours"),i18n("Last 12 hours"),i18n("Last 24 hours"),i18n("Last 48 hours"), i18n("Last 7 days")] | ||
111 | id: syspal | 111 | readonly property var timespanComboDurations: [3600, 7200, 43200, 86400, 172800, 604800] | ||
112 | } | | |||
113 | 112 | | |||
114 | ScrollView { | 113 | Kirigami.ScrollablePage { | ||
115 | id: scrollView | | |||
116 | anchors.fill: parent | 114 | anchors.fill: parent | ||
117 | 115 | | |||
118 | horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff | | |||
119 | | ||||
120 | ColumnLayout { | 116 | ColumnLayout { | ||
121 | id: column | 117 | id: column | ||
122 | 118 | Kirigami.ScrollablePage { | |||
123 | width: scrollView.viewport.width | | |||
124 | spacing: units.largeSpacing | | |||
125 | | ||||
126 | ScrollView { | | |||
127 | id: tabView | 119 | id: tabView | ||
128 | Layout.fillWidth: true | | |||
129 | Layout.minimumHeight: units.gridUnit * 3 | 120 | Layout.minimumHeight: units.gridUnit * 3 | ||
130 | Layout.maximumHeight: Layout.minimumHeight | 121 | Layout.maximumHeight: Layout.minimumHeight | ||
131 | 122 | | |||
132 | frameVisible: true | 123 | // frameVisible: true | ||
133 | visible: kcm.batteries.count > 1 | 124 | visible: kcm.batteries.count > 1 | ||
134 | 125 | | |||
135 | verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff | 126 | verticalScrollBarPolicy: ScrollBar.AlwaysOff | ||
136 | 127 | | |||
137 | Row { | 128 | Row { | ||
138 | Repeater { | 129 | Repeater { | ||
139 | model: kcm.batteries | 130 | model: kcm.batteries | ||
140 | 131 | | |||
141 | Button { | 132 | Button { | ||
142 | id: button | 133 | id: button | ||
143 | width: height | 134 | width: height | ||
144 | height: tabView.viewport.height | 135 | height: tabView.height | ||
145 | checked: model.battery == root.currentBattery | 136 | checked: model.battery == root.currentBattery | ||
146 | checkable: true | 137 | checkable: true | ||
147 | onClicked: { | 138 | onClicked: { | ||
148 | root.currentUdi = model.udi | 139 | root.currentUdi = model.udi | ||
149 | root.currentBattery = model.battery | 140 | root.currentBattery = model.battery | ||
150 | // override checked property | 141 | // override checked property | ||
151 | checked = Qt.binding(function() { | 142 | checked = Qt.binding(function() { | ||
152 | return model.battery == root.currentBattery | 143 | return model.battery == root.currentBattery | ||
Show All 26 Lines | 160 | batteryType: { | |||
179 | } | 170 | } | ||
180 | } | 171 | } | ||
181 | percent: model.battery.chargePercent | 172 | percent: model.battery.chargePercent | ||
182 | //pluggedIn: model.battery.chargeState === 1 // Makes it hard to see | 173 | //pluggedIn: model.battery.chargeState === 1 // Makes it hard to see | ||
183 | } | 174 | } | ||
184 | 175 | | |||
185 | ProgressBar { // TODO make progress bar not eat mouse events | 176 | ProgressBar { // TODO make progress bar not eat mouse events | ||
186 | Layout.fillWidth: true | 177 | Layout.fillWidth: true | ||
187 | minimumValue: 0 | 178 | from: 0 | ||
188 | maximumValue: 100 | 179 | to: 100 | ||
189 | value: model.battery.chargePercent | 180 | value: model.battery.chargePercent | ||
190 | enabled: button.checked ? false : true | 181 | enabled: button.checked ? false : true | ||
191 | } | 182 | } | ||
192 | } | 183 | } | ||
193 | } | 184 | } | ||
194 | } | 185 | } | ||
195 | } | 186 | } | ||
196 | } | 187 | } | ||
Show All 30 Lines | 194 | GridLayout { | |||
227 | 218 | | |||
228 | Item { | 219 | Item { | ||
229 | Layout.fillWidth: true | 220 | Layout.fillWidth: true | ||
230 | } | 221 | } | ||
231 | 222 | | |||
232 | ComboBox { | 223 | ComboBox { | ||
233 | id: timespanCombo | 224 | id: timespanCombo | ||
234 | Layout.minimumWidth: units.gridUnit * 6 | 225 | Layout.minimumWidth: units.gridUnit * 6 | ||
235 | model: [ | 226 | model: timespanComboChoices | ||
236 | {text: i18n("Last hour"), value: 3600}, | | |||
237 | {text: i18n("Last 2 hours"), value: 7200}, | | |||
238 | {text: i18n("Last 12 hours"), value: 43200}, | | |||
239 | {text: i18n("Last 24 hours"), value: 86400}, | | |||
240 | {text: i18n("Last 48 hours"), value: 172800}, | | |||
241 | {text: i18n("Last 7 days"), value: 604800} | | |||
242 | ] | | |||
243 | Accessible.name: i18n("Timespan") | 227 | Accessible.name: i18n("Timespan") | ||
244 | Accessible.description: i18n("Timespan of data to display") | 228 | Accessible.description: i18n("Timespan of data to display") | ||
245 | } | 229 | } | ||
246 | 230 | | |||
247 | Button { | 231 | Button { | ||
248 | iconName: "view-refresh" | 232 | icon.name: "view-refresh" | ||
249 | tooltip: i18n("Refresh") | 233 | hoverEnabled: true | ||
250 | Accessible.name: tooltip | 234 | ToolTip.text: i18n("Refresh") | ||
235 | ToolTip.visible: hovered | ||||
236 | ToolTip.delay: Kirigami.Units.toolTipDelay | ||||
237 | Accessible.name: ToolTip.text | ||||
251 | onClicked: history.refresh() | 238 | onClicked: history.refresh() | ||
252 | } | 239 | } | ||
253 | } | 240 | } | ||
254 | 241 | | |||
255 | HistoryModel { | 242 | HistoryModel { | ||
256 | id: history | 243 | id: history | ||
257 | duration: timespanCombo.model[timespanCombo.currentIndex].value | 244 | duration: timespanComboDurations[timespanCombo.currentIndex] | ||
258 | device: currentUdi | 245 | device: currentUdi | ||
259 | type: root.historyType | 246 | type: root.historyType | ||
260 | } | 247 | } | ||
261 | 248 | | |||
262 | Graph { | 249 | Graph { | ||
263 | id: graph | 250 | id: graph | ||
264 | Layout.fillWidth: true | 251 | Layout.fillWidth: true | ||
265 | Layout.minimumHeight: column.width / 3 | 252 | Layout.minimumHeight: column.width / 3 | ||
Show All 15 Lines | 260 | yMax: { | |||
281 | } else { | 268 | } else { | ||
282 | return 100; | 269 | return 100; | ||
283 | } | 270 | } | ||
284 | } | 271 | } | ||
285 | yStep: root.historyType == HistoryModel.RateType ? 10 : 20 | 272 | yStep: root.historyType == HistoryModel.RateType ? 10 : 20 | ||
286 | visible: history.count > 1 | 273 | visible: history.count > 1 | ||
287 | } | 274 | } | ||
288 | 275 | | |||
289 | QQC2.Label { | 276 | Label { | ||
290 | Layout.fillWidth: true | 277 | Layout.fillWidth: true | ||
291 | Layout.minimumHeight: column.width / 3 | 278 | Layout.minimumHeight: column.width / 3 | ||
292 | Layout.maximumHeight: column.width / 3 | 279 | Layout.maximumHeight: column.width / 3 | ||
293 | horizontalAlignment: Text.AlignHCenter | 280 | horizontalAlignment: Text.AlignHCenter | ||
294 | verticalAlignment: Text.AlignVCenter | 281 | verticalAlignment: Text.AlignVCenter | ||
295 | text: i18n("This type of history is currently not available for this device.") | 282 | text: i18n("This type of history is currently not available for this device.") | ||
296 | wrapMode: Text.WordWrap | 283 | wrapMode: Text.WordWrap | ||
297 | visible: !graph.visible | 284 | visible: !graph.visible | ||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Line(s) | 339 | RowLayout { | |||
361 | 348 | | |||
362 | ColumnLayout { | 349 | ColumnLayout { | ||
363 | Layout.fillWidth: true | 350 | Layout.fillWidth: true | ||
364 | spacing: 0 | 351 | spacing: 0 | ||
365 | 352 | | |||
366 | RowLayout { | 353 | RowLayout { | ||
367 | Layout.fillWidth: true | 354 | Layout.fillWidth: true | ||
368 | 355 | | |||
369 | QQC2.Label { | 356 | Label { | ||
370 | Layout.fillWidth: true | 357 | Layout.fillWidth: true | ||
371 | elide: Text.ElideRight | 358 | elide: Text.ElideRight | ||
372 | text: model.prettyName || model.name | 359 | text: model.prettyName || model.name | ||
373 | } | 360 | } | ||
374 | 361 | | |||
375 | /*Label { | 362 | /*Label { | ||
376 | text: i18n("System Service") | 363 | text: i18n("System Service") | ||
377 | visible: !model.userSpace | 364 | visible: !model.userSpace | ||
378 | opacity: 0.6 | 365 | opacity: 0.6 | ||
379 | }*/ | 366 | }*/ | ||
380 | } | 367 | } | ||
381 | 368 | | |||
382 | ProgressBar { | 369 | ProgressBar { | ||
383 | Layout.fillWidth: true | 370 | Layout.fillWidth: true | ||
384 | minimumValue: 0 | 371 | from: 0 | ||
385 | maximumValue: 100 | 372 | to: 100 | ||
386 | value: model.wakeUps / kcm.wakeUps.total * 100 | 373 | value: model.wakeUps / kcm.wakeUps.total * 100 | ||
387 | } | 374 | } | ||
388 | } | 375 | } | ||
389 | } | 376 | } | ||
390 | } | 377 | } | ||
391 | } | 378 | } | ||
392 | } | 379 | } | ||
393 | } | 380 | } | ||
394 | 381 | | |||
395 | Rectangle { | 382 | Rectangle { | ||
396 | Layout.fillWidth: true | 383 | Layout.fillWidth: true | ||
397 | height: 1 | 384 | height: 1 | ||
398 | color: "#ccc" // FIXME palette | 385 | color: "#ccc" // FIXME palette | ||
399 | //Layout.topMargin: (compact ? units.gridUnit * 2 : 0) | 386 | //Layout.topMargin: (compact ? units.gridUnit * 2 : 0) | ||
400 | visible: wakeUpsGrid.visible | 387 | visible: wakeUpsGrid.visible | ||
401 | } | 388 | } | ||
402 | 389 | | |||
403 | ColumnLayout { | 390 | ColumnLayout { | ||
404 | id: detailsColumn | 391 | id: detailsColumn | ||
405 | property int legendWidth: 10 | | |||
406 | 392 | | |||
407 | Layout.fillWidth: true | 393 | Layout.fillWidth: true | ||
408 | spacing: 0 | | |||
409 | visible: !!currentBattery | 394 | visible: !!currentBattery | ||
410 | 395 | | |||
411 | Repeater { | 396 | Repeater { | ||
397 | id: detailsrepeater | ||||
412 | model: root.details | 398 | model: root.details | ||
399 | property list<Kirigami.FormLayout> layouts | ||||
413 | 400 | | |||
414 | ColumnLayout { | 401 | Kirigami.FormLayout { | ||
415 | spacing: 0//units.smallSpacing | 402 | id: currentLayout | ||
403 | Component.onCompleted: { | ||||
404 | if (currentLayout.visible) { | ||||
405 | // ensure that all visible FormLayout share the same set of twinFormLayouts | ||||
406 | detailsrepeater.layouts.push(currentLayout); | ||||
407 | for ( var i = 0, length = detailsrepeater.layouts.length; i < length; ++i) { | ||||
408 | detailsrepeater.layouts[i].twinFormLayouts = detailsrepeater.layouts; | ||||
409 | } | ||||
410 | } | ||||
411 | } | ||||
416 | 412 | | |||
417 | PlasmaExtras.Heading { | 413 | Kirigami.Heading { | ||
418 | level: 4 | | |||
419 | color: sysPal.text | | |||
420 | text: modelData.title | 414 | text: modelData.title | ||
415 | Kirigami.FormData.isSection: true | ||||
416 | level: 4 | ||||
421 | // HACK hide section header if all labels are invisible | 417 | // HACK hide section header if all labels are invisible | ||
422 | visible: { | 418 | visible: { | ||
423 | for (var i = 0, length = detailsRepeater.count; i < length; ++i) { | 419 | for (var i = 0, length = detailsRepeater.count; i < length; ++i) { | ||
424 | var item = detailsRepeater.itemAt(i) | 420 | var item = detailsRepeater.itemAt(i) | ||
425 | if (item && item.visible) { | 421 | if (item && item.visible) { | ||
426 | return true | 422 | return true | ||
427 | } | 423 | } | ||
428 | } | 424 | } | ||
429 | 425 | | |||
430 | return false | 426 | return false | ||
431 | } | 427 | } | ||
432 | } | 428 | } | ||
433 | 429 | | |||
434 | Repeater { | 430 | Repeater { | ||
435 | id: detailsRepeater | 431 | id: detailsRepeater | ||
436 | model: modelData.data || [] | 432 | model: modelData.data || [] | ||
437 | 433 | | |||
438 | RowLayout { | 434 | Label { | ||
filipf: trailing space her as well, as well as in the preceding row | |||||
439 | Layout.fillWidth: true | | |||
440 | spacing: units.smallSpacing * 2 | | |||
441 | visible: valueLabel.text !== "" | | |||
442 | | ||||
443 | QQC2.Label { | | |||
444 | Layout.minimumWidth: detailsColumn.legendWidth + units.gridUnit | | |||
445 | horizontalAlignment: Text.AlignRight | | |||
446 | text: i18n("%1:", modelData.label) | | |||
447 | wrapMode: Text.NoWrap | | |||
448 | opacity: 0.8 | | |||
449 | onPaintedWidthChanged: { | | |||
450 | if (paintedWidth > detailsColumn.legendWidth) { | | |||
451 | detailsColumn.legendWidth = paintedWidth | | |||
452 | } | | |||
453 | } | | |||
454 | } | | |||
455 | | ||||
456 | QQC2.Label { | | |||
457 | id: valueLabel | 435 | id: valueLabel | ||
458 | Layout.fillWidth: true | 436 | Kirigami.FormData.label: i18n("%1:", modelData.label) | ||
459 | text: { | 437 | text: { | ||
460 | var value = currentBattery[modelData.value] | 438 | var value = currentBattery[modelData.value] | ||
461 | 439 | | |||
462 | if (typeof value === "boolean") { | 440 | if (typeof value === "boolean") { | ||
463 | if (value) { | 441 | if (value) { | ||
464 | return i18n("Yes") | 442 | return i18n("Yes") | ||
465 | } else { | 443 | } else { | ||
466 | return i18n("No") | 444 | return i18n("No") | ||
467 | } | 445 | } | ||
468 | } | 446 | } | ||
469 | 447 | | |||
470 | if (!value) { | 448 | if (!value) { | ||
broulik: Shouldn't be neccessary as it's `QQC2.Label` | |||||
For breeze dark this makes the label, dark gray on a dark background. See before screenshot. Could it be a breeze dark bug ? meven: For breeze dark this makes the label, dark gray on a dark background. See before screenshot. | |||||
471 | return "" | 449 | return "" | ||
472 | } | 450 | } | ||
473 | 451 | | |||
474 | var precision = modelData.precision | 452 | var precision = modelData.precision | ||
475 | if (typeof precision === "number") { // round to decimals | 453 | if (typeof precision === "number") { // round to decimals | ||
476 | value = Number(value).toLocaleString(Qt.locale(), "f", precision) | 454 | value = Number(value).toLocaleString(Qt.locale(), "f", precision) | ||
477 | } | 455 | } | ||
478 | 456 | | |||
479 | if (modelData.modifier && root["modifier_" + modelData.modifier]) { | 457 | if (modelData.modifier && root["modifier_" + modelData.modifier]) { | ||
480 | value = root["modifier_" + modelData.modifier](value) | 458 | value = root["modifier_" + modelData.modifier](value) | ||
481 | } | 459 | } | ||
482 | 460 | | |||
483 | if (modelData.unit) { | 461 | if (modelData.unit) { | ||
484 | value = i18nc("%1 is value, %2 is unit", "%1 %2", value, modelData.unit) | 462 | value = i18nc("%1 is value, %2 is unit", "%1 %2", value, modelData.unit) | ||
485 | } | 463 | } | ||
486 | 464 | | |||
487 | return value | 465 | return value | ||
488 | } | 466 | } | ||
489 | } | 467 | visible: valueLabel.text !== "" | ||
490 | } | 468 | } | ||
491 | } | 469 | } | ||
492 | } | 470 | } | ||
493 | } | 471 | } | ||
494 | } | 472 | } | ||
495 | } | 473 | } | ||
496 | } | 474 | } | ||
497 | } | 475 | } |
and also getting rid of QQC1