Skip to content

Commit 8e88ec0

Browse files
committed
Portrait: adapt Brief page for portrait layout
Contributes to #2829
1 parent 54d6eb0 commit 8e88ec0

17 files changed

+321
-156
lines changed

components/BriefSidePanelWidget.qml

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,55 +6,98 @@
66
import QtQuick
77
import Victron.VenusOS
88

9-
Column {
9+
/*
10+
A widget in the Brief side panel.
11+
12+
In landscape orientation, the layout is:
13+
14+
| Icon & Title |
15+
| Quantity label | Graph |
16+
| Footer |
17+
18+
In portrait orientation, the layout is:
19+
20+
| Icon & Title | Graph | Quantity label |
21+
| Footer |
22+
*/
23+
Rectangle {
1024
id: root
1125

12-
property alias title: header.title
26+
required property string title
1327
property alias icon: header.icon
1428
property alias quantityLabel: quantityLabel
15-
property alias sideComponent: sideLoader.sourceComponent
16-
property alias bottomComponent: bottomLoader.sourceComponent
29+
property alias graph: graphLoader.sourceComponent
30+
property alias footer: footerLoader.sourceComponent
1731
property bool loadersActive
1832

19-
width: parent.width
20-
bottomPadding: Theme.geometry_sidePanel_verticalMargin
33+
// True if the graph should be stretched to fill as much space as possible.
34+
property bool stretchGraph: true
2135

22-
WidgetHeader {
23-
id: header
24-
z: 1 // place the title above the side component if it overflows
25-
}
36+
implicitWidth: parent?.width ?? Theme.geometry_briefPage_sidePanel_width
37+
implicitHeight: contentItem.height + (2 * Theme.geometry_sidePanel_sideWidget_verticalMargin)
2638

27-
Row {
28-
width: parent.width
29-
height: quantityLabel.height
39+
// In portrait layout, show a background and shrink the content area to fit within that
40+
// background, with some margin between the content and the background.
41+
color: Theme.screenSize === Theme.Portrait ? Theme.color_background_secondary : "transparent"
42+
radius: Theme.geometry_button_radius
43+
44+
Item {
45+
id: contentItem
46+
47+
anchors.centerIn: parent
48+
width: parent.width - (2 * Theme.geometry_sidePanel_sideWidget_horizontalMargin)
49+
implicitHeight: footerLoader.y + footerLoader.height
50+
51+
WidgetHeader {
52+
id: header
53+
54+
anchors.left: parent.left
55+
width: Theme.screenSize === Theme.Portrait
56+
? root.stretchGraph
57+
? implicitWidth
58+
: Math.min(implicitWidth, parent.width - quantityLabel.width - graphLoader.width - Theme.geometry_sidePanel_sideWidget_spacing)
59+
: parent.width
60+
height: Theme.screenSize === Theme.Portrait ? quantityLabel.height : implicitHeight
61+
rightPadding: Theme.screenSize === Theme.Portrait ? Theme.geometry_sidePanel_sideWidget_spacing : 0
62+
text: root.title
63+
}
3064

3165
ElectricalQuantityLabel {
3266
id: quantityLabel
67+
68+
anchors {
69+
top: Theme.screenSize === Theme.Portrait ? undefined : header.bottom
70+
left: Theme.screenSize === Theme.Portrait ? undefined : parent.left
71+
right: Theme.screenSize === Theme.Portrait ? parent.right : undefined
72+
}
73+
rightPadding: Theme.screenSize === Theme.Portrait ? 0 : Theme.geometry_sidePanel_sideWidget_spacing
3374
font.pixelSize: Theme.font_briefPage_sidePanel_quantityLabel_size
34-
width: parent.width - sideLoader.width
35-
alignment: Qt.AlignLeft
75+
alignment: Theme.screenSize === Theme.Portrait ? Qt.AlignRight : Qt.AlignLeft
3676
}
3777

3878
Loader {
39-
id: sideLoader
79+
id: graphLoader
80+
4081
anchors {
41-
top: parent.top
42-
bottom: parent.bottom
43-
bottomMargin: Theme.geometry_sidePanel_sideWidget_bottomMargin
82+
left: root.stretchGraph ? (Theme.screenSize === Theme.Portrait ? header.right : quantityLabel.right) : undefined
83+
top: Theme.screenSize === Theme.Portrait ? quantityLabel.top : header.bottom
84+
bottom: Theme.screenSize === Theme.Portrait ? quantityLabel.bottom : footerLoader.top
85+
bottomMargin: Theme.screenSize === Theme.Portrait ? 0 : Theme.geometry_sidePanel_sideWidget_bottomMargin
86+
right: Theme.screenSize === Theme.Portrait ? quantityLabel.left : parent.right
87+
rightMargin: Theme.screenSize === Theme.Portrait ? Theme.geometry_sidePanel_sideWidget_spacing : 0
4488
}
45-
width: Theme.geometry_sidePanel_sideWidget_width
4689
active: root.loadersActive
90+
sourceComponent: root.graph
4791
}
48-
}
4992

50-
Item {
51-
width: 1
52-
height: bottomLoader.status === Loader.Ready ? Theme.geometry_sidePanel_quantityLabel_bottomMargin : 0
53-
}
54-
55-
Loader {
56-
id: bottomLoader
57-
width: parent.width
58-
active: root.loadersActive
93+
Loader {
94+
id: footerLoader
95+
anchors {
96+
top: quantityLabel.bottom
97+
topMargin: status === Loader.Null ? 0 : Theme.geometry_sidePanel_quantityLabel_bottomMargin
98+
}
99+
width: parent.width
100+
active: root.loadersActive
101+
}
59102
}
60103
}

components/CircularMultiGauge.qml

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Item {
1717
property real labelMargin
1818
property alias labelOpacity: textCol.opacity
1919
property int leftGaugeCount
20+
property real longCaptionWidth: width / 2
21+
property real shortCaptionWidth: width / 2
2022

2123
// Step change in the size of the bounding boxes of successive gauges
2224
readonly property real _stepSize: 2 * (strokeWidth + Theme.geometry_circularMultiGauge_spacing)
@@ -82,7 +84,6 @@ Item {
8284
anchors.topMargin: strokeWidth/2
8385
anchors.bottom: parent.verticalCenter
8486
anchors.left: parent.left
85-
anchors.leftMargin: Theme.geometry_circularMultiGauge_label_leftMargin
8687
anchors.right: parent.horizontalCenter
8788
anchors.rightMargin: Theme.geometry_circularMultiGauge_icon_rightMargin + gauges.labelMargin
8889

@@ -92,23 +93,24 @@ Item {
9293
anchors.verticalCenter: textCol.top
9394
anchors.verticalCenterOffset: index * _stepSize/2
9495
anchors.right: parent.right
95-
anchors.rightMargin: Math.max(0, Theme.geometry_circularMultiGauge_icons_maxWidth - iconImage.width)
96+
97+
// With three gauges on the left there is a risk that the last labels on
98+
// on the multi-gauge overlap with the labels on the top-left gauge.
99+
//
100+
// Increase the space for the two top-most labels or if there are less left gauges.
101+
width: (model.index < 2 || gauges.leftGaugeCount < 3 ? gauges.longCaptionWidth : gauges.shortCaptionWidth)
96102
height: iconImage.height
97103

98104
Label {
99105
anchors.verticalCenter: parent.verticalCenter
100106
rightPadding: Theme.geometry_circularMultiGauge_label_rightMargin
101107
horizontalAlignment: Text.AlignRight
102-
font.pixelSize: valueLabel.visible ? Theme.font_size_body1 : Theme.font_size_body2
108+
font.pixelSize: valueLabel.visible
109+
? valueLabel.font.pixelSize
110+
: Theme.font_circularMultiGauge_label_largeSize
103111
color: Theme.color_font_primary
104112
text: model.name
105-
106-
// With three gauges on the left there is a risk that the last labels on
107-
// on the multi-gauge overlap with the labels on the top-left gauge.
108-
//
109-
// Increase the space for the two top-most labels or if there are less left gauges.
110-
width: textCol.width - valueLabel.width - iconImage.width
111-
+ (model.index < 2 || gauges.leftGaugeCount < 3 ? Theme.geometry_circularMultiGauge_label_extraWidth : 0)
113+
width: parent.width - valueLabel.width - iconImage.width
112114
elide: Text.ElideRight
113115
}
114116

@@ -117,7 +119,7 @@ Item {
117119
anchors.verticalCenter: parent.verticalCenter
118120
rightPadding: Theme.geometry_circularMultiGauge_value_rightMargin
119121
horizontalAlignment: Text.AlignRight
120-
font.pixelSize: Theme.font_size_body1
122+
font.pixelSize: Theme.font_circularMultiGauge_label_smallSize
121123
color: Theme.color_font_primary
122124
visible: false
123125

components/GeneratorIconLabel.qml

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,32 @@ import QtQuick
77
import QtQuick.Controls.impl as CP
88
import Victron.VenusOS
99

10-
Item {
10+
Label {
1111
id: root
1212

13-
property Generator generator
14-
property alias fontSize: label.font.pixelSize
13+
required property Generator generator
1514

16-
implicitHeight: label.height
17-
implicitWidth: label.x + label.width
15+
leftPadding: icon.width + Theme.geometry_generatorIconLabel_icon_margin
16+
font.pixelSize: Theme.font_size_body2
17+
color: root.generator && root.generator_runtime > 0 ? Theme.color_font_primary : Theme.color_font_secondary
18+
verticalAlignment: Text.AlignVCenter
19+
20+
// When generator runtime < 60 it has second precision, otherwise when >= 60, it is only
21+
// updated every minute. So, show mm:ss when < 60, and hh:mm when >= 60.
22+
text: root.generator && root.generator.state !== VenusOS.Generators_State_Stopped && root.generator.runtime !== 0
23+
? Utils.formatGeneratorRuntime(root.generator.runtime)
24+
: "--:--"
1825

1926
CP.IconImage {
2027
id: icon
2128

22-
anchors.top: label.top
23-
width: Theme.geometry_generatorIconLabel_icon_width
29+
anchors.verticalCenter: parent.verticalCenter
30+
width: visible ? Theme.geometry_generatorIconLabel_icon_width : 0
2431
height: Theme.geometry_generatorIconLabel_icon_width
2532
color: Theme.color_font_primary
33+
visible: root.generator && root.generator.state !== VenusOS.Generators_RunningBy_NotRunning
2634
source: {
27-
if (!root.generator || root.generator.state === VenusOS.Generators_RunningBy_NotRunning) {
35+
if (!visible) {
2836
return ""
2937
}
3038
if (root.generator.runningBy === VenusOS.Generators_RunningBy_Manual) {
@@ -36,23 +44,5 @@ Item {
3644
}
3745
return "qrc:/images/icon_autostart_24.svg"
3846
}
39-
40-
}
41-
42-
Label {
43-
id: label
44-
45-
anchors {
46-
left: icon.right
47-
leftMargin: Theme.geometry_generatorIconLabel_icon_margin
48-
}
49-
font.pixelSize: Theme.font_size_body2
50-
color: root.generator && root.generator_runtime > 0 ? Theme.color_font_primary : Theme.color_font_secondary
51-
52-
// When generator runtime < 60 it has second precision, otherwise when >= 60, it is only
53-
// updated every minute. So, show mm:ss when < 60, and hh:mm when >= 60.
54-
text: root.generator && root.generator.state !== VenusOS.Generators_State_Stopped && root.generator.runtime !== 0
55-
? Utils.formatGeneratorRuntime(root.generator.runtime)
56-
: "--:--"
5747
}
5848
}

components/SolarYieldGraph.qml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import Victron.VenusOS
1111
Item {
1212
id: root
1313

14-
property int maximumBarCount
15-
property real spacing: (width - (Theme.geometry_overviewPage_widget_solar_graph_bar_width * yieldModel.count)) / (yieldModel.count - 1)
14+
readonly property int maximumBarCount: (width + Theme.geometry_overviewPage_widget_solar_graph_bar_spacing)
15+
/ (Theme.geometry_overviewPage_widget_solar_graph_bar_width + Theme.geometry_overviewPage_widget_solar_graph_bar_spacing)
1616

1717
Repeater {
1818
model: SolarYieldModel {
@@ -23,7 +23,7 @@ Item {
2323

2424
delegate: Rectangle {
2525
x: model.index * Theme.geometry_overviewPage_widget_solar_graph_bar_width
26-
+ (root.spacing * model.index)
26+
+ (Theme.geometry_overviewPage_widget_solar_graph_bar_spacing * model.index)
2727
y: parent.height - height
2828
height: yieldModel.maximumYield > 0
2929
? root.height * (model.yieldKwh / yieldModel.maximumYield)

components/widgets/OverviewWidget.qml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ Rectangle {
1414
property int preferredSize: VenusOS.OverviewWidget_PreferredSize_Any
1515

1616
property alias icon: widgetHeader.icon
17-
property alias title: widgetHeader.title
18-
property alias secondaryTitle: widgetHeader.secondaryText
17+
property string title
1918
property alias quantityLabel: quantityLabel
2019

2120
signal clicked
@@ -121,6 +120,8 @@ Rectangle {
121120

122121
WidgetHeader {
123122
id: widgetHeader
123+
width: parent.width
124+
text: root.title
124125
}
125126

126127
ElectricalQuantityLabel {

components/widgets/SolarYieldWidget.qml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ OverviewWidget {
9191
anchors.horizontalCenter: parent.horizontalCenter
9292
height: parent.height
9393
width: parent.width - (2 * Theme.geometry_overviewPage_widget_solar_graph_margins)
94-
maximumBarCount: Theme.geometry_overviewPage_widget_solar_graph_bar_count
9594
}
9695
}
9796
}

components/widgets/WidgetHeader.qml

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,22 @@ import QtQuick
77
import Victron.VenusOS
88
import QtQuick.Controls.impl as CP
99

10-
Row {
10+
Label {
1111
id: root
1212

13-
property alias title: titleLabel.text
14-
property alias secondaryText: secondaryLabel.text
1513
property alias icon: icon
1614

17-
width: parent ? parent.width : 0
18-
spacing: Theme.geometry_widgetHeader_spacing
15+
leftPadding: icon.width + Theme.geometry_widgetHeader_spacing
16+
elide: Text.ElideRight
17+
verticalAlignment: Text.AlignVCenter
1918

2019
CP.ColorImage {
2120
id: icon
2221

23-
anchors.verticalCenter: titleLabel.verticalCenter
22+
anchors.verticalCenter: parent.verticalCenter
2423
width: Theme.geometry_widgetHeader_icon_size
2524
height: Theme.geometry_widgetHeader_icon_size
2625
fillMode: Image.Pad
27-
color: titleLabel.color
28-
}
29-
30-
Label {
31-
id: titleLabel
32-
width: parent.width - icon.width - secondaryLabel.implicitWidth - (2 * Theme.geometry_widgetHeader_spacing)
33-
elide: Text.ElideRight
34-
}
35-
36-
Label {
37-
id: secondaryLabel
38-
color: Theme.color_font_secondary
26+
color: parent.color
3927
}
4028
}
41-

pages/BriefPage.qml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ SwipeViewPage {
6767

6868
y: (root._unexpandedHeight - height) / 2
6969
width: Theme.geometry_mainGauge_size
70-
height: width
70+
height: Theme.geometry_mainGauge_size
7171
x: sidePanel.x/2 - width/2
7272
sourceComponent: gaugeModel.count === 0 ? singleGauge : multiGauge
7373
onStatusChanged: if (status === Loader.Error) console.warn("Unable to load main gauge")
@@ -84,6 +84,11 @@ SwipeViewPage {
8484
labelMargin: root._gaugeLabelMargin
8585
leftGaugeCount: root._leftGaugeCount
8686

87+
// Caption spans from the centre to the left quantity label.
88+
// Longer captions span further, to the edge of the left gauge bars.
89+
shortCaptionWidth: longCaptionWidth - (acInputGauge.item?.quantityWidth ?? 0)
90+
longCaptionWidth: (root.width / 2) - (acInputGaugeColumn.x + acInputGaugeColumn.width + Theme.geometry_circularMultiGauge_spacing)
91+
8792
BriefCenterDisplay {
8893
anchors.centerIn: parent
8994
width: parent.width - (gaugeModel.count * circularMultiGauge._stepSize) + Theme.geometry_circularMultiGauge_spacing
@@ -114,6 +119,8 @@ SwipeViewPage {
114119

115120
// Left gauge column
116121
Column {
122+
id: acInputGaugeColumn
123+
117124
anchors {
118125
verticalCenter: mainGauge.verticalCenter
119126
left: parent.left
@@ -132,6 +139,7 @@ SwipeViewPage {
132139
active: Global.acInputs.findValidSource() !== VenusOS.AcInputs_InputSource_NotAvailable && root.state !== "panelOpened"
133140

134141
sourceComponent: SideMultiGauge {
142+
readonly property real quantityWidth: acInGaugeQuantity.width - acInputDirectionIcon.width
135143
readonly property var gaugeParams: Gauges.leftGaugeParameters(
136144
(solarYieldGauge.active ? 1 : 0) + (dcInputGauge.active ? 1 : 0),
137145
_leftGaugeCount,
@@ -366,7 +374,7 @@ SwipeViewPage {
366374
id: sidePanel
367375
width: Theme.geometry_briefPage_sidePanel_width
368376
sourceComponent: BriefSidePanel {
369-
width: parent.width
377+
width: Theme.geometry_briefPage_sidePanel_width
370378
height: Math.max(root._unexpandedHeight, implicitHeight)
371379
animationEnabled: root.animationEnabled
372380
}

0 commit comments

Comments
 (0)