GODT-1411: refactor SettingView content to fill height

This commit is contained in:
Alexander Bilyak
2021-11-09 13:18:11 +00:00
committed by Jakub
parent 2e52b8db87
commit 31920a4468
10 changed files with 251 additions and 167 deletions

View File

@ -40,195 +40,208 @@ Item {
property int _lineWidth: 1 property int _lineWidth: 1
ScrollView { ScrollView {
id: scrollView
clip: true clip: true
anchors.fill: parent anchors.fill: parent
ColumnLayout { Item {
width: root.width // can't use parent here because parent is not ScrollView (Flickable inside contentItem inside ScrollView)
spacing: 0 width: scrollView.availableWidth
height: scrollView.availableHeight
Rectangle { implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
id: topRectangle // do not set implicitWidth because implicit width of ColumnLayout will be equal to maximum implicit width of
color: root.colorScheme.background_norm // internal items. And if one of internal items would be a Text or Label - implicit width of those is always
// equal to non-wrapped text (i.e. one line only). That will lead to enabling horizontal scroll when not needed
implicitWidth: width
implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin ColumnLayout {
implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin spacing: 0
Layout.fillWidth: true anchors.fill: parent
ColumnLayout { Rectangle {
spacing: root._spacing id: topRectangle
color: root.colorScheme.background_norm
anchors.fill: parent implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
anchors.leftMargin: root._leftMargin implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin
anchors.rightMargin: root._rightMargin
anchors.topMargin: root._topMargin
anchors.bottomMargin: root._bottomMargin
Layout.fillWidth: true
RowLayout { // account delegate with action buttons ColumnLayout {
Layout.fillWidth: true spacing: root._spacing
AccountDelegate { anchors.fill: parent
anchors.leftMargin: root._leftMargin
anchors.rightMargin: root._rightMargin
anchors.topMargin: root._topMargin
anchors.bottomMargin: root._bottomMargin
RowLayout { // account delegate with action buttons
Layout.fillWidth: true Layout.fillWidth: true
AccountDelegate {
Layout.fillWidth: true
colorScheme: root.colorScheme
user: root.user
type: AccountDelegate.LargeView
enabled: root.user ? root.user.loggedIn : false
}
Button {
Layout.alignment: Qt.AlignTop
colorScheme: root.colorScheme
text: qsTr("Sign out")
secondary: true
visible: root.user ? root.user.loggedIn : false
onClicked: {
if (!root.user) return
root.user.logout()
}
}
Button {
Layout.alignment: Qt.AlignTop
colorScheme: root.colorScheme
text: qsTr("Sign in")
secondary: true
visible: root.user ? !root.user.loggedIn : false
onClicked: {
if (!root.user) return
root.parent.rightContent.showSignIn()
}
}
Button {
Layout.alignment: Qt.AlignTop
colorScheme: root.colorScheme
icon.source: "icons/ic-trash.svg"
secondary: true
onClicked: {
if (!root.user) return
root.user.remove()
}
}
}
Rectangle {
Layout.fillWidth: true
height: root._lineWidth
color: root.colorScheme.border_weak
}
SettingsItem {
colorScheme: root.colorScheme colorScheme: root.colorScheme
user: root.user text: qsTr("Email clients")
type: AccountDelegate.LargeView actionText: qsTr("Configure")
description: qsTr("Proton Mail Bridge works with email clients that support IMAP/SMPT to send and receive messages. Using the mailbox details below, you can (re)configure your client at any point.")
type: SettingsItem.Button
enabled: root.user ? root.user.loggedIn : false enabled: root.user ? root.user.loggedIn : false
} visible: root.user ? !root.user.splitMode || root.user.addresses.length==1 : false
showSeparator: splitMode.visible
Button {
Layout.alignment: Qt.AlignTop
colorScheme: root.colorScheme
text: qsTr("Sign out")
secondary: true
visible: root.user ? root.user.loggedIn : false
onClicked: { onClicked: {
if (!root.user) return if (!root.user) return
root.user.logout() root.showSetupGuide(root.user, user.addresses[0])
} }
}
Button {
Layout.alignment: Qt.AlignTop
colorScheme: root.colorScheme
text: qsTr("Sign in")
secondary: true
visible: root.user ? !root.user.loggedIn : false
onClicked: {
if (!root.user) return
root.parent.rightContent.showSignIn()
}
}
Button {
Layout.alignment: Qt.AlignTop
colorScheme: root.colorScheme
icon.source: "icons/ic-trash.svg"
secondary: true
onClicked: {
if (!root.user) return
root.user.remove()
}
}
}
Rectangle {
Layout.fillWidth: true
height: root._lineWidth
color: root.colorScheme.border_weak
}
SettingsItem {
colorScheme: root.colorScheme
text: qsTr("Email clients")
actionText: qsTr("Configure")
description: qsTr("Proton Mail Bridge works with email clients that support IMAP/SMPT to send and receive messages. Using the mailbox details below, you can (re)configure your client at any point.")
type: SettingsItem.Button
enabled: root.user ? root.user.loggedIn : false
visible: root.user ? !root.user.splitMode || root.user.addresses.length==1 : false
showSeparator: splitMode.visible
onClicked: {
if (!root.user) return
root.showSetupGuide(root.user, user.addresses[0])
}
Layout.fillWidth: true
}
SettingsItem {
id: splitMode
colorScheme: root.colorScheme
text: qsTr("Split addresses")
description: qsTr("Split addresses allows you to configure multiple email addresses individually. Changing its mode will require you to delete your accounts(s) from your email client and begin the setup process from scratch.")
type: SettingsItem.Toggle
checked: root.user ? root.user.splitMode : false
visible: root.user ? root.user.addresses.length > 1 : false
enabled: root.user ? root.user.loggedIn : false
showSeparator: addressSelector.visible
onClicked: {
if (!splitMode.checked){
root.notifications.askEnableSplitMode(user)
} else {
root.user.toggleSplitMode(!splitMode.checked)
}
}
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
enabled: root.user ? root.user.loggedIn : false
visible: root.user ? root.user.splitMode : false
ComboBox {
id: addressSelector
colorScheme: root.colorScheme
Layout.fillWidth: true Layout.fillWidth: true
model: root.user ? root.user.addresses : null
} }
Button { SettingsItem {
id: splitMode
colorScheme: root.colorScheme colorScheme: root.colorScheme
text: qsTr("Configure") text: qsTr("Split addresses")
secondary: true description: qsTr("Split addresses allows you to configure multiple email addresses individually. Changing its mode will require you to delete your accounts(s) from your email client and begin the setup process from scratch.")
type: SettingsItem.Toggle
checked: root.user ? root.user.splitMode : false
visible: root.user ? root.user.addresses.length > 1 : false
enabled: root.user ? root.user.loggedIn : false
showSeparator: addressSelector.visible
onClicked: { onClicked: {
if (!root.user) return if (!splitMode.checked){
root.showSetupGuide(root.user, addressSelector.displayText) root.notifications.askEnableSplitMode(user)
} else {
root.user.toggleSplitMode(!splitMode.checked)
}
}
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
enabled: root.user ? root.user.loggedIn : false
visible: root.user ? root.user.splitMode : false
ComboBox {
id: addressSelector
colorScheme: root.colorScheme
Layout.fillWidth: true
model: root.user ? root.user.addresses : null
}
Button {
colorScheme: root.colorScheme
text: qsTr("Configure")
secondary: true
onClicked: {
if (!root.user) return
root.showSetupGuide(root.user, addressSelector.displayText)
}
} }
} }
} }
} }
}
Rectangle { Rectangle {
color: root.colorScheme.background_weak color: root.colorScheme.background_weak
implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin
Layout.fillWidth: true Layout.fillWidth: true
ColumnLayout { ColumnLayout {
id: configuration id: configuration
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: root._leftMargin anchors.leftMargin: root._leftMargin
anchors.rightMargin: root._rightMargin anchors.rightMargin: root._rightMargin
anchors.topMargin: root._detailsTopMargin anchors.topMargin: root._detailsTopMargin
anchors.bottomMargin: root._spacing anchors.bottomMargin: root._spacing
spacing: root._spacing spacing: root._spacing
visible: root.user ? root.user.loggedIn : false visible: root.user ? root.user.loggedIn : false
property string currentAddress: addressSelector.displayText property string currentAddress: addressSelector.displayText
Label { Label {
colorScheme: root.colorScheme colorScheme: root.colorScheme
text: qsTr("Mailbox details") text: qsTr("Mailbox details")
type: Label.Body_semibold type: Label.Body_semibold
} }
Configuration { Configuration {
colorScheme: root.colorScheme colorScheme: root.colorScheme
title: qsTr("IMAP") title: qsTr("IMAP")
hostname: root.backend.hostname hostname: root.backend.hostname
port: root.backend.portIMAP.toString() port: root.backend.portIMAP.toString()
username: configuration.currentAddress username: configuration.currentAddress
password: root.user ? root.user.password : "" password: root.user ? root.user.password : ""
security: "STARTTLS" security: "STARTTLS"
} }
Configuration { Configuration {
colorScheme: root.colorScheme colorScheme: root.colorScheme
title: qsTr("SMTP") title: qsTr("SMTP")
hostname : root.backend.hostname hostname : root.backend.hostname
port : root.backend.portSMTP.toString() port : root.backend.portSMTP.toString()
username : configuration.currentAddress username : configuration.currentAddress
password : root.user ? root.user.password : "" password : root.user ? root.user.password : ""
security : root.backend.useSSLforSMTP ? "SSL" : "STARTTLS" security : root.backend.useSSLforSMTP ? "SSL" : "STARTTLS"
}
} }
} }
} }

View File

@ -24,6 +24,8 @@ import Proton 4.0
SettingsView { SettingsView {
id: root id: root
fillHeight: true
property var selectedAddress property var selectedAddress
Label { Label {
@ -41,7 +43,8 @@ SettingsView {
label: qsTr("Description") label: qsTr("Description")
colorScheme: root.colorScheme colorScheme: root.colorScheme
Layout.fillWidth: true Layout.fillWidth: true
Layout.minimumHeight: 100 Layout.fillHeight: true
Layout.minimumHeight: heightForLinesVisible(4)
hint: description.text.length + "/" + _maxLength hint: description.text.length + "/" + _maxLength
placeholderText: qsTr("Tell us what went wrong or isn't working (min. %1 characters).").arg(_minLength) placeholderText: qsTr("Tell us what went wrong or isn't working (min. %1 characters).").arg(_minLength)
@ -66,6 +69,11 @@ SettingsView {
KeyNavigation.priority: KeyNavigation.BeforeItem KeyNavigation.priority: KeyNavigation.BeforeItem
KeyNavigation.tab: address KeyNavigation.tab: address
// set implicitHeight to explicit height because se don't
// want TextArea implicitHeight (which is height of all text)
// to be considered in SettingsView internal scroll view
implicitHeight: height
} }

View File

@ -41,4 +41,15 @@ Rectangle {
color: "black" color: "black"
colorScheme: ProtonStyle.currentStyle colorScheme: ProtonStyle.currentStyle
} }
Rectangle {
width: target.implicitWidth
height: target.implicitHeight
color: "transparent"
border.color: "green"
border.width: 1
//z: parent.z - 1
z: 10000000
}
} }

View File

@ -28,6 +28,8 @@ SettingsView {
property bool _isAdvancedShown: false property bool _isAdvancedShown: false
property var notifications property var notifications
fillHeight: false
Label { Label {
colorScheme: root.colorScheme colorScheme: root.colorScheme
text: qsTr("Settings") text: qsTr("Settings")

View File

@ -24,6 +24,8 @@ import Proton 4.0
SettingsView { SettingsView {
id: root id: root
fillHeight: true
Label { Label {
colorScheme: root.colorScheme colorScheme: root.colorScheme
text: qsTr("Help") text: qsTr("Help")
@ -88,6 +90,12 @@ SettingsView {
Layout.fillWidth: true Layout.fillWidth: true
} }
// fill height so the footer label will be allways attached to the bottom
Item {
Layout.fillHeight: true
Layout.fillWidth: true
}
Label { Label {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
colorScheme: root.colorScheme colorScheme: root.colorScheme

View File

@ -26,6 +26,8 @@ import Proton 4.0
SettingsView { SettingsView {
id: root id: root
fillHeight: false
property var notifications property var notifications
property bool _diskCacheEnabled: true property bool _diskCacheEnabled: true
property string _diskCachePath: "/home" property string _diskCachePath: "/home"

View File

@ -25,6 +25,8 @@ import Proton 4.0
SettingsView { SettingsView {
id: root id: root
fillHeight: false
property bool _valuesChanged: ( property bool _valuesChanged: (
imapField.text*1 !== root.backend.portIMAP || imapField.text*1 !== root.backend.portIMAP ||
smtpField.text*1 !== root.backend.portSMTP smtpField.text*1 !== root.backend.portSMTP

View File

@ -124,11 +124,27 @@ FocusScope {
function selectWord() { return control.selectWord() } function selectWord() { return control.selectWord() }
function undo() { return control.undo() } function undo() { return control.undo() }
// Calculates the height of the component to make exactly lineNum visible in edit area
function heightForLinesVisible(lineNum) {
var totalHeight = 0
totalHeight += headerLayout.height
totalHeight += footerLayout.height
totalHeight += control.topPadding + control.bottomPadding
totalHeight += lineNum * fontMetrics.height
return totalHeight
}
FontMetrics {
id: fontMetrics
font: control.font
}
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
spacing: 0 spacing: 0
RowLayout { RowLayout {
id: headerLayout
Layout.fillWidth: true Layout.fillWidth: true
spacing: 0 spacing: 0
@ -282,6 +298,7 @@ FocusScope {
} }
RowLayout { RowLayout {
id: footerLayout
Layout.fillWidth: true Layout.fillWidth: true
spacing: 0 spacing: 0

View File

@ -25,6 +25,8 @@ import Proton 4.0
SettingsView { SettingsView {
id: root id: root
fillHeight: false
Label { Label {
colorScheme: root.colorScheme colorScheme: root.colorScheme
text: qsTr("SMTP connection mode") text: qsTr("SMTP connection mode")

View File

@ -37,28 +37,47 @@ Item {
property int _bottomMargin: 32 property int _bottomMargin: 32
property int _spacing: 20 property int _spacing: 20
// fillHeight indicates whether the SettingsView should fill all available explicit height set
property bool fillHeight: false
ScrollView { ScrollView {
id: scrollView
clip: true clip: true
width:root.width anchors.fill: parent
height:root.height
contentWidth: content.width + content.anchors.leftMargin + content.anchors.rightMargin Item {
contentHeight: content.height + content.anchors.topMargin + content.anchors.bottomMargin // can't use parent here because parent is not ScrollView (Flickable inside contentItem inside ScrollView)
width: scrollView.availableWidth
height: scrollView.availableHeight
ColumnLayout { implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
id: content // do not set implicitWidth because implicit width of ColumnLayout will be equal to maximum implicit width of
spacing: root._spacing // internal items. And if one of internal items would be a Text or Label - implicit width of those is always
width: root.width - (root._leftMargin + root._rightMargin) // equal to non-wrapped text (i.e. one line only). That will lead to enabling horizontal scroll when not needed
implicitWidth: width
anchors{ ColumnLayout {
top: parent.top anchors.fill: parent
left: parent.left spacing: 0
topMargin: root._topMargin
bottomMargin: root._bottomMargin ColumnLayout {
leftMargin: root._leftMargin id: content
rightMargin: root._rightMargin spacing: root._spacing
Layout.fillWidth: true
Layout.topMargin: root._topMargin
Layout.bottomMargin: root._bottomMargin
Layout.leftMargin: root._leftMargin
Layout.rightMargin: root._rightMargin
}
Item {
id: filler
Layout.fillHeight: true
visible: !root.fillHeight
}
} }
} }
} }