forked from Silverfish/proton-bridge
GODT-22: Facelift
- GODT-1199: Add menu to status window - GODT-22: use ColorImage instead of IconLabel - GODT-22: remove banners from MainWindow - GODT-1199: Fix separator width - GODT-1199: Fix StatusWindow button position - GODT-1198: Open main window on startup if no users - GODT-1199: Fix avatar text color - GODT-1198: refactor main window layout - GODT-22: add missing components to qmldir - GODT-22: refactor components having Layout as root item - GODT-22: add more user controls - GODT-1199: Add status window resize and maximum height - GODT-22: WIP: notification arch - GODT-22: Notifications WIP - GODT-22: Fix notification filter, topmost notification - GODT-1199: Add notifications to status window - GODT-22: Add strict typization to colorScheme variable - GODT-1198: WIP Notifications, dialogs and banners - GODT-22: Add backend notifications (Banners & Dialogs) D
This commit is contained in:
136
internal/frontend/qml/Proton/ApplicationWindow.qml
Normal file
136
internal/frontend/qml/Proton/ApplicationWindow.qml
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
|
||||
import "."
|
||||
|
||||
T.ApplicationWindow {
|
||||
id: root
|
||||
|
||||
property ColorScheme colorScheme
|
||||
|
||||
// popup priority based on types
|
||||
enum PopupType {
|
||||
Banner = 0,
|
||||
Dialog = 1
|
||||
}
|
||||
|
||||
// contains currently visible popup
|
||||
property var popupVisible: null
|
||||
|
||||
// list of all popups within ApplicationWindow
|
||||
property ListModel popups: ListModel {
|
||||
// overriding get method to ignore any role and return directly object itself
|
||||
function get(row) {
|
||||
if (row < 0 || row >= count) {
|
||||
return undefined
|
||||
}
|
||||
return data(index(row, 0), Qt.DisplayRole)
|
||||
}
|
||||
|
||||
onRowsInserted: {
|
||||
for (var i = first; i <= last; i++) {
|
||||
var obj = popups.get(i)
|
||||
obj.onShouldShowChanged.connect( root.processPopups )
|
||||
}
|
||||
|
||||
processPopups()
|
||||
}
|
||||
|
||||
onRowsAboutToBeRemoved: {
|
||||
for (var i = first; i <= last; i++ ) {
|
||||
var obj = popups.get(i)
|
||||
obj.onShouldShowChanged.disconnect( root.processPopups )
|
||||
|
||||
// if currently visible popup was removed
|
||||
if (root.popupVisible === obj) {
|
||||
root.popupVisible.visible = false
|
||||
root.popupVisible = null
|
||||
}
|
||||
}
|
||||
|
||||
processPopups()
|
||||
}
|
||||
}
|
||||
|
||||
function processPopups() {
|
||||
if ((root.popupVisible) && (!root.popupVisible.shouldShow)) {
|
||||
root.popupVisible.visible = false
|
||||
}
|
||||
|
||||
// do nothing if there is already visible popup
|
||||
if (root.popupVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
var topmost = null
|
||||
for (var i = 0; i < popups.count; i++) {
|
||||
var obj = popups.get(i)
|
||||
|
||||
if (obj.shouldShow === false) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (topmost && (topmost.popupType > obj.popupType)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (topmost && (topmost.popupType === obj.popupType) && (topmost.occurred > obj.occurred)) {
|
||||
continue
|
||||
}
|
||||
|
||||
topmost = obj
|
||||
}
|
||||
|
||||
root.popupVisible = topmost
|
||||
|
||||
if (!topmost) {
|
||||
return
|
||||
}
|
||||
|
||||
topmost.visible = true
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.popupVisible
|
||||
|
||||
onVisibleChanged: {
|
||||
if (root.popupVisible.visible) {
|
||||
return
|
||||
}
|
||||
|
||||
root.popupVisible = null
|
||||
root.processPopups()
|
||||
}
|
||||
}
|
||||
|
||||
color: root.colorScheme.background_norm
|
||||
|
||||
overlay.modal: Rectangle {
|
||||
color: root.colorScheme.backdrop_norm
|
||||
}
|
||||
|
||||
overlay.modeless: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
width: layout.width
|
||||
height: layout.height
|
||||
|
||||
radius: 10
|
||||
|
||||
signal accepted()
|
||||
|
||||
|
||||
property alias text: description.text
|
||||
property var actionText: ""
|
||||
|
||||
property var colorText: Style.currentStyle.text_invert
|
||||
property var colorMain: "#000"
|
||||
property var colorHover: "#000"
|
||||
property var colorActive: "#000"
|
||||
property var iconSource: "../icons/ic-exclamation-circle-filled.svg"
|
||||
|
||||
color: root.colorMain
|
||||
border.color: root.colorActive
|
||||
border.width: 1
|
||||
|
||||
property var maxWidth: 600
|
||||
property var minWidth: 400
|
||||
property var usedWidth: button.width + icon.width
|
||||
|
||||
RowLayout {
|
||||
id: layout
|
||||
|
||||
IconLabel {
|
||||
id:icon
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.leftMargin: 17.5
|
||||
Layout.topMargin: 15.5
|
||||
Layout.bottomMargin: 15.5
|
||||
color: root.colorText
|
||||
icon.source: root.iconSource
|
||||
icon.color: root.colorText
|
||||
icon.height: Style.title_line_height
|
||||
}
|
||||
|
||||
ProtonLabel {
|
||||
id: description
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.leftMargin: 9.5
|
||||
Layout.minimumWidth: root.minWidth - root.usedWidth
|
||||
Layout.maximumWidth: root.maxWidth - root.usedWidth
|
||||
|
||||
color: root.colorText
|
||||
state: "body"
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Button {
|
||||
id:button
|
||||
Layout.fillHeight: true
|
||||
|
||||
hoverEnabled: true
|
||||
|
||||
text: root.actionText.toUpperCase()
|
||||
|
||||
onClicked: root.accepted()
|
||||
|
||||
background: RoundedRectangle {
|
||||
width:parent.width
|
||||
height:parent.height
|
||||
strokeColor: root.colorActive
|
||||
strokeWidth: root.border.width
|
||||
|
||||
radiusTopRight : root.radius
|
||||
radiusBottomRight : root.radius
|
||||
radiusTopLeft : 0
|
||||
radiusBottomLeft : 0
|
||||
|
||||
fillColor: button.down ? root.colorActive : (
|
||||
button.hovered ? root.colorHover :
|
||||
root.colorMain
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state: "info"
|
||||
states: [
|
||||
State{ name : "danger" ; PropertyChanges{ target : root ; colorMain : Style.currentStyle.signal_danger ; colorHover : Style.currentStyle.signal_danger_hover ; colorActive : Style.currentStyle.signal_danger_active ; iconSource: "../icons/ic-exclamation-circle-filled.svg"}} ,
|
||||
State{ name : "warning" ; PropertyChanges{ target : root ; colorMain : Style.currentStyle.signal_warning ; colorHover : Style.currentStyle.signal_warning_hover ; colorActive : Style.currentStyle.signal_warning_active ; iconSource: "../icons/ic-exclamation-circle-filled.svg"}} ,
|
||||
State{ name : "success" ; PropertyChanges{ target : root ; colorMain : Style.currentStyle.signal_success ; colorHover : Style.currentStyle.signal_success_hover ; colorActive : Style.currentStyle.signal_success_active ; iconSource: "../icons/ic-info-circle-filled.svg"}} ,
|
||||
State{ name : "info" ; PropertyChanges{ target : root ; colorMain : Style.currentStyle.signal_info ; colorHover : Style.currentStyle.signal_info_hover ; colorActive : Style.currentStyle.signal_info_active ; iconSource: "../icons/ic-info-circle-filled.svg"}}
|
||||
]
|
||||
}
|
||||
@ -22,7 +22,7 @@ import QtQuick.Templates 2.12 as T
|
||||
import "."
|
||||
|
||||
T.Button {
|
||||
property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
|
||||
property ColorScheme colorScheme
|
||||
|
||||
property alias secondary: control.flat
|
||||
readonly property bool primary: !secondary
|
||||
@ -30,6 +30,10 @@ T.Button {
|
||||
|
||||
property bool loading: false
|
||||
|
||||
property bool borderless: false
|
||||
|
||||
property int labelType: Label.LabelType.Body
|
||||
|
||||
// TODO: store previous enabled state and restore it?
|
||||
// For now assuming that only enabled buttons could have loading state
|
||||
onLoadingChanged: {
|
||||
@ -55,9 +59,7 @@ T.Button {
|
||||
horizontalPadding: 16
|
||||
spacing: 10
|
||||
|
||||
font.family: Style.font_family
|
||||
font.pixelSize: Style.body_font_size
|
||||
font.letterSpacing: Style.body_letter_spacing
|
||||
font: label.font
|
||||
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
@ -65,7 +67,7 @@ T.Button {
|
||||
if (primary && !isIcon) {
|
||||
return "#FFFFFF"
|
||||
} else {
|
||||
return colorScheme.text_norm
|
||||
return control.colorScheme.text_norm
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,6 +105,7 @@ T.Button {
|
||||
}
|
||||
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: label
|
||||
anchors.left: labelIcon.left
|
||||
anchors.top: labelIcon.top
|
||||
@ -115,15 +118,16 @@ T.Button {
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
|
||||
text: control.text
|
||||
font: control.font
|
||||
color: {
|
||||
if (primary && !isIcon) {
|
||||
return "#FFFFFF"
|
||||
} else {
|
||||
return colorScheme.text_norm
|
||||
return control.colorScheme.text_norm
|
||||
}
|
||||
}
|
||||
opacity: control.enabled || control.loading ? 1.0 : 0.5
|
||||
|
||||
type: labelType
|
||||
}
|
||||
|
||||
ColorImage {
|
||||
@ -176,74 +180,74 @@ T.Button {
|
||||
// Primary colors
|
||||
|
||||
if (control.down) {
|
||||
return colorScheme.interaction_norm_active
|
||||
return control.colorScheme.interaction_norm_active
|
||||
}
|
||||
|
||||
if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
if (control.loading) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_norm
|
||||
return control.colorScheme.interaction_norm
|
||||
} else {
|
||||
// Secondary colors
|
||||
|
||||
if (control.down) {
|
||||
return colorScheme.interaction_default_active
|
||||
return control.colorScheme.interaction_default_active
|
||||
}
|
||||
|
||||
if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
|
||||
return colorScheme.interaction_default_hover
|
||||
return control.colorScheme.interaction_default_hover
|
||||
}
|
||||
|
||||
if (control.loading) {
|
||||
return colorScheme.interaction_default_hover
|
||||
return control.colorScheme.interaction_default_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_default
|
||||
return control.colorScheme.interaction_default
|
||||
}
|
||||
} else {
|
||||
if (primary) {
|
||||
// Primary icon colors
|
||||
|
||||
if (control.down) {
|
||||
return colorScheme.interaction_default_active
|
||||
return control.colorScheme.interaction_default_active
|
||||
}
|
||||
|
||||
if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
|
||||
return colorScheme.interaction_default_hover
|
||||
return control.colorScheme.interaction_default_hover
|
||||
}
|
||||
|
||||
if (control.loading) {
|
||||
return colorScheme.interaction_default_hover
|
||||
return control.colorScheme.interaction_default_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_default
|
||||
return control.colorScheme.interaction_default
|
||||
} else {
|
||||
// Secondary icon colors
|
||||
|
||||
if (control.down) {
|
||||
return colorScheme.interaction_default_active
|
||||
return control.colorScheme.interaction_default_active
|
||||
}
|
||||
|
||||
if (control.enabled && (control.highlighted || control.hovered || control.checked)) {
|
||||
return colorScheme.interaction_default_hover
|
||||
return control.colorScheme.interaction_default_hover
|
||||
}
|
||||
|
||||
if (control.loading) {
|
||||
return colorScheme.interaction_default_hover
|
||||
return control.colorScheme.interaction_default_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_default
|
||||
return control.colorScheme.interaction_default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
border.color: colorScheme.border_norm
|
||||
border.width: secondary ? 1 : 0
|
||||
border.color: control.colorScheme.border_norm
|
||||
border.width: secondary && !borderless ? 1 : 0
|
||||
|
||||
opacity: control.enabled || control.loading ? 1.0 : 0.5
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
|
||||
T.CheckBox {
|
||||
property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
|
||||
property ColorScheme colorScheme
|
||||
|
||||
property bool error: false
|
||||
|
||||
@ -46,39 +46,39 @@ T.CheckBox {
|
||||
|
||||
color: {
|
||||
if (!checked) {
|
||||
return colorScheme.background_norm
|
||||
return control.colorScheme.background_norm
|
||||
}
|
||||
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return control.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.error) {
|
||||
return colorScheme.signal_danger
|
||||
return control.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_norm
|
||||
return control.colorScheme.interaction_norm
|
||||
}
|
||||
|
||||
border.width: control.checked ? 0 : 1
|
||||
border.color: {
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return control.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.error) {
|
||||
return colorScheme.signal_danger
|
||||
return control.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
return colorScheme.field_norm
|
||||
return control.colorScheme.field_norm
|
||||
}
|
||||
|
||||
ColorImage {
|
||||
@ -112,21 +112,21 @@ T.CheckBox {
|
||||
|
||||
color: {
|
||||
if (!enabled) {
|
||||
return colorScheme.text_disabled
|
||||
return control.colorScheme.text_disabled
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return colorScheme.signal_danger
|
||||
return control.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
return colorScheme.text_norm
|
||||
return control.colorScheme.text_norm
|
||||
}
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: Style.fontWidth_400
|
||||
font.pixelSize: 14
|
||||
lineHeight: 20
|
||||
font.weight: Style.fontWeight_400
|
||||
font.pixelSize: Style.body_font_size
|
||||
lineHeight: Style.body_line_height
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: 0.2
|
||||
font.letterSpacing: Style.body_letter_spacing
|
||||
}
|
||||
}
|
||||
|
||||
82
internal/frontend/qml/Proton/Dialog.qml
Normal file
82
internal/frontend/qml/Proton/Dialog.qml
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
|
||||
import "."
|
||||
|
||||
T.Dialog {
|
||||
id: root
|
||||
property ColorScheme colorScheme
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!ApplicationWindow.window) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ApplicationWindow.window.popups === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
var obj = this
|
||||
ApplicationWindow.window.popups.append( { obj } )
|
||||
}
|
||||
|
||||
readonly property int popupType: ApplicationWindow.PopupType.Dialog
|
||||
|
||||
property bool shouldShow: false
|
||||
readonly property var occurred: shouldShow ? new Date() : undefined
|
||||
function open() {
|
||||
root.shouldShow = true
|
||||
}
|
||||
|
||||
function close() {
|
||||
root.shouldShow = false
|
||||
}
|
||||
|
||||
anchors.centerIn: Overlay.overlay
|
||||
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
contentWidth + leftPadding + rightPadding,
|
||||
implicitHeaderWidth,
|
||||
implicitFooterWidth)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
contentHeight + topPadding + bottomPadding
|
||||
+ (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0)
|
||||
+ (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0))
|
||||
|
||||
padding: 24
|
||||
|
||||
background: Rectangle {
|
||||
color: root.colorScheme.background_norm
|
||||
radius: 10
|
||||
}
|
||||
|
||||
// TODO: Add DropShadow here
|
||||
|
||||
T.Overlay.modal: Rectangle {
|
||||
color: root.colorScheme.backdrop_norm
|
||||
}
|
||||
|
||||
T.Overlay.modeless: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
138
internal/frontend/qml/Proton/Label.qml
Normal file
138
internal/frontend/qml/Proton/Label.qml
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
import "."
|
||||
|
||||
T.Label {
|
||||
id: root
|
||||
|
||||
property ColorScheme colorScheme
|
||||
|
||||
enum LabelType {
|
||||
// weight 700, size 28, height 36
|
||||
Heading,
|
||||
// weight 700, size 20, height 24
|
||||
Title,
|
||||
// weight 400, size 18, height 26
|
||||
Lead,
|
||||
// weight 400, size 14, height 20, spacing 0.2
|
||||
Body,
|
||||
// weight 600, size 14, height 20, spacing 0.2
|
||||
Body_semibold,
|
||||
// weight 700, size 14, height 20, spacing 0.2
|
||||
Body_bold,
|
||||
// weight 400, size 12, height 16, spacing 0.4
|
||||
Caption,
|
||||
// weight 600, size 12, height 16, spacing 0.4
|
||||
Caption_semibold,
|
||||
// weight 700, size 12, height 16, spacing 0.4
|
||||
Caption_bold
|
||||
}
|
||||
property int type: Label.LabelType.Body
|
||||
|
||||
color: root.enabled ? root.colorScheme.text_norm : root.colorScheme.text_disabled
|
||||
palette.link: root.colorScheme.interaction_norm
|
||||
|
||||
font.family: Style.font_family
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
font.weight: {
|
||||
switch (root.type) {
|
||||
case Label.LabelType.Heading:
|
||||
return Style.fontWeight_700
|
||||
case Label.LabelType.Title:
|
||||
return Style.fontWeight_700
|
||||
case Label.LabelType.Lead:
|
||||
return Style.fontWeight_400
|
||||
case Label.LabelType.Body:
|
||||
return Style.fontWeight_400
|
||||
case Label.LabelType.Body_semibold:
|
||||
return Style.fontWeight_600
|
||||
case Label.LabelType.Body_bold:
|
||||
return Style.fontWeight_700
|
||||
case Label.LabelType.Caption:
|
||||
return Style.fontWeight_400
|
||||
case Label.LabelType.Caption_semibold:
|
||||
return Style.fontWeight_600
|
||||
case Label.LabelType.Caption_bold:
|
||||
return Style.fontWeight_700
|
||||
}
|
||||
}
|
||||
|
||||
font.pixelSize: {
|
||||
switch (root.type) {
|
||||
case Label.LabelType.Heading:
|
||||
return Style.heading_font_size
|
||||
case Label.LabelType.Title:
|
||||
return Style.title_font_size
|
||||
case Label.LabelType.Lead:
|
||||
return Style.lead_font_size
|
||||
case Label.LabelType.Body:
|
||||
case Label.LabelType.Body_semibold:
|
||||
case Label.LabelType.Body_bold:
|
||||
return Style.body_font_size
|
||||
case Label.LabelType.Caption:
|
||||
case Label.LabelType.Caption_semibold:
|
||||
case Label.LabelType.Caption_bold:
|
||||
return Style.caption_font_size
|
||||
}
|
||||
}
|
||||
|
||||
lineHeight: {
|
||||
switch (root.type) {
|
||||
case Label.LabelType.Heading:
|
||||
return Style.heading_line_height
|
||||
case Label.LabelType.Title:
|
||||
return Style.title_line_height
|
||||
case Label.LabelType.Lead:
|
||||
return Style.lead_line_height
|
||||
case Label.LabelType.Body:
|
||||
case Label.LabelType.Body_semibold:
|
||||
case Label.LabelType.Body_bold:
|
||||
return Style.body_line_height
|
||||
case Label.LabelType.Caption:
|
||||
case Label.LabelType.Caption_semibold:
|
||||
case Label.LabelType.Caption_bold:
|
||||
return Style.caption_line_height
|
||||
}
|
||||
}
|
||||
|
||||
font.letterSpacing: {
|
||||
switch (root.type) {
|
||||
case Label.LabelType.Heading:
|
||||
case Label.LabelType.Title:
|
||||
case Label.LabelType.Lead:
|
||||
return 0
|
||||
case Label.LabelType.Body:
|
||||
case Label.LabelType.Body_semibold:
|
||||
case Label.LabelType.Body_bold:
|
||||
return Style.body_letter_spacing
|
||||
case Label.LabelType.Caption:
|
||||
case Label.LabelType.Caption_semibold:
|
||||
case Label.LabelType.Caption_bold:
|
||||
return Style.caption_letter_spacing
|
||||
}
|
||||
}
|
||||
|
||||
function link(url, text) {
|
||||
return `<a href="${url}">${text}</a>`
|
||||
}
|
||||
}
|
||||
68
internal/frontend/qml/Proton/Menu.qml
Normal file
68
internal/frontend/qml/Proton/Menu.qml
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
import QtQuick.Window 2.12
|
||||
import "."
|
||||
|
||||
T.Menu {
|
||||
id: control
|
||||
|
||||
property ColorScheme colorScheme
|
||||
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
contentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
contentHeight + topPadding + bottomPadding)
|
||||
|
||||
margins: 0
|
||||
overlap: 1
|
||||
|
||||
delegate: MenuItem {
|
||||
colorScheme: control.colorScheme
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitHeight: children[0].implicitHeight + children[0].anchors.topMargin + children[0].anchors.bottomMargin
|
||||
implicitWidth: children[0].implicitWidth + children[0].anchors.leftMargin + children[0].anchors.rightMargin
|
||||
|
||||
ListView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
|
||||
implicitHeight: contentHeight
|
||||
model: control.contentModel
|
||||
interactive: Window.window ? contentHeight > Window.window.height : false
|
||||
clip: true
|
||||
currentIndex: control.currentIndex
|
||||
|
||||
ScrollIndicator.vertical: ScrollIndicator {}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
implicitWidth: 200
|
||||
implicitHeight: 40
|
||||
color: colorScheme.background_norm
|
||||
border.width: 1
|
||||
border.color: colorScheme.border_weak
|
||||
radius: 10
|
||||
}
|
||||
}
|
||||
72
internal/frontend/qml/Proton/MenuItem.qml
Normal file
72
internal/frontend/qml/Proton/MenuItem.qml
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
import "."
|
||||
|
||||
T.MenuItem {
|
||||
id: control
|
||||
|
||||
property ColorScheme colorScheme
|
||||
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
implicitContentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
implicitContentHeight + topPadding + bottomPadding,
|
||||
implicitIndicatorHeight + topPadding + bottomPadding)
|
||||
|
||||
padding: 6
|
||||
spacing: 6
|
||||
|
||||
icon.width: 24
|
||||
icon.height: 24
|
||||
icon.color: control.enabled ? control.colorScheme.text_norm : control.colorScheme.text_disabled
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: Style.fontWeight_400
|
||||
font.pixelSize: Style.body_font_size
|
||||
font.letterSpacing: Style.body_letter_spacing
|
||||
|
||||
contentItem: IconLabel {
|
||||
id: iconLabel
|
||||
readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0
|
||||
readonly property real indicatorPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0
|
||||
leftPadding: !control.mirrored ? indicatorPadding : arrowPadding
|
||||
rightPadding: control.mirrored ? indicatorPadding : arrowPadding
|
||||
|
||||
spacing: control.spacing
|
||||
mirrored: control.mirrored
|
||||
display: control.display
|
||||
alignment: Qt.AlignLeft
|
||||
|
||||
icon: control.icon
|
||||
text: control.text
|
||||
font: control.font
|
||||
|
||||
color: control.enabled ? control.colorScheme.text_norm : control.colorScheme.text_disabled
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
implicitWidth: 164
|
||||
implicitHeight: 36
|
||||
radius: 4
|
||||
color: control.down ? control.colorScheme.interaction_default_active : control.highlighted ? control.colorScheme.interaction_default_hover : control.colorScheme.interaction_default
|
||||
}
|
||||
}
|
||||
67
internal/frontend/qml/Proton/Popup.qml
Normal file
67
internal/frontend/qml/Proton/Popup.qml
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
|
||||
T.Popup {
|
||||
id: root
|
||||
property ColorScheme colorScheme
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!ApplicationWindow.window) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ApplicationWindow.window.popups === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
var obj = this
|
||||
ApplicationWindow.window.popups.append( { obj } )
|
||||
}
|
||||
|
||||
property int popupType: ApplicationWindow.PopupType.Banner
|
||||
|
||||
property bool shouldShow: false
|
||||
readonly property var occurred: shouldShow ? new Date() : undefined
|
||||
function open() {
|
||||
root.shouldShow = true
|
||||
}
|
||||
|
||||
function close() {
|
||||
root.shouldShow = false
|
||||
}
|
||||
|
||||
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
|
||||
contentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
contentHeight + topPadding + bottomPadding)
|
||||
|
||||
// TODO: Add DropShadow here
|
||||
|
||||
T.Overlay.modal: Rectangle {
|
||||
color: root.colorScheme.backdrop_norm
|
||||
}
|
||||
|
||||
T.Overlay.modeless: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
// Copyright (c) 2021 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Label {
|
||||
id: root
|
||||
|
||||
color: Style.currentStyle.text_norm
|
||||
palette.link: Style.currentStyle.interaction_norm
|
||||
|
||||
font.family: ProtonStyle.font_family
|
||||
font.weight: ProtonStyle.fontWidth_400
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
function putLink(linkURL,linkText) {
|
||||
return `<a href="${linkURL}">${linkText}</a>`
|
||||
}
|
||||
|
||||
state: "title"
|
||||
states: [
|
||||
State { name : "heading" ; PropertyChanges { target : root ; font.pixelSize : Style.heading_font_size ; lineHeight : Style.heading_line_height } },
|
||||
State { name : "title" ; PropertyChanges { target : root ; font.pixelSize : Style.title_font_size ; lineHeight : Style.title_line_height } },
|
||||
State { name : "lead" ; PropertyChanges { target : root ; font.pixelSize : Style.lead_font_size ; lineHeight : Style.lead_line_height } },
|
||||
State { name : "body" ; PropertyChanges { target : root ; font.pixelSize : Style.body_font_size ; lineHeight : Style.body_line_height ; font.letterSpacing : Style.body_letter_spacing } },
|
||||
State { name : "caption" ; PropertyChanges { target : root ; font.pixelSize : Style.caption_font_size ; lineHeight : Style.caption_line_height ; font.letterSpacing : Style.caption_letter_spacing } }
|
||||
]
|
||||
}
|
||||
@ -21,7 +21,7 @@ import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
|
||||
T.RadioButton {
|
||||
property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
|
||||
property ColorScheme colorScheme
|
||||
|
||||
property bool error: false
|
||||
|
||||
@ -44,22 +44,22 @@ T.RadioButton {
|
||||
x: text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
|
||||
y: control.topPadding + (control.availableHeight - height) / 2
|
||||
|
||||
color: colorScheme.background_norm
|
||||
color: control.colorScheme.background_norm
|
||||
border.width: 1
|
||||
border.color: {
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return control.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.error) {
|
||||
return colorScheme.signal_danger
|
||||
return control.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
return colorScheme.field_norm
|
||||
return control.colorScheme.field_norm
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -70,18 +70,18 @@ T.RadioButton {
|
||||
radius: width / 2
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return control.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.error) {
|
||||
return colorScheme.signal_danger
|
||||
return control.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_norm
|
||||
return control.colorScheme.interaction_norm
|
||||
}
|
||||
visible: control.checked
|
||||
}
|
||||
@ -95,21 +95,21 @@ T.RadioButton {
|
||||
|
||||
color: {
|
||||
if (!enabled) {
|
||||
return colorScheme.text_disabled
|
||||
return control.colorScheme.text_disabled
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return colorScheme.signal_danger
|
||||
return control.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
return colorScheme.text_norm
|
||||
return control.colorScheme.text_norm
|
||||
}
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: Style.fontWidth_400
|
||||
font.pixelSize: 14
|
||||
lineHeight: 20
|
||||
font.weight: Style.fontWeight_400
|
||||
font.pixelSize: Style.body_font_size
|
||||
lineHeight: Style.body_line_height
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: 0.2
|
||||
font.letterSpacing: Style.body_letter_spacing
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,9 +32,8 @@ QtObject {
|
||||
// property color primay_norm
|
||||
// ...
|
||||
// }
|
||||
// and instead of "var" later on "ColorScheme" should be used (also in each component)
|
||||
|
||||
property var lightStyle: ColorScheme {
|
||||
property ColorScheme lightStyle: ColorScheme {
|
||||
id: _lightStyle
|
||||
|
||||
prominent: prominentStyle
|
||||
@ -105,7 +104,7 @@ QtObject {
|
||||
backdrop_norm: "#7A262A33"
|
||||
}
|
||||
|
||||
property var prominentStyle: ColorScheme {
|
||||
property ColorScheme prominentStyle: ColorScheme {
|
||||
id: _prominentStyle
|
||||
|
||||
prominent: this
|
||||
@ -176,7 +175,7 @@ QtObject {
|
||||
backdrop_norm: "#52000000"
|
||||
}
|
||||
|
||||
property var darkStyle: ColorScheme {
|
||||
property ColorScheme darkStyle: ColorScheme {
|
||||
id: _darkStyle
|
||||
|
||||
prominent: prominentStyle
|
||||
@ -249,7 +248,7 @@ QtObject {
|
||||
|
||||
// TODO: if default style should be loaded from somewhere
|
||||
// (i.e. from preferencies file) - it should be loaded here
|
||||
property var currentStyle: lightStyle
|
||||
property ColorScheme currentStyle: lightStyle
|
||||
|
||||
property string font_family: {
|
||||
switch (Qt.platform.os) {
|
||||
@ -281,15 +280,13 @@ QtObject {
|
||||
property int caption_line_height: 16
|
||||
property real caption_letter_spacing: 0.4
|
||||
|
||||
property int fontWidth_100: Font.Thin
|
||||
property int fontWidth_200: Font.Light
|
||||
property int fontWidth_300: Font.ExtraLight
|
||||
property int fontWidth_400: Font.Normal
|
||||
property int fontWidth_500: Font.Medium
|
||||
property int fontWidth_600: Font.DemiBold
|
||||
property int fontWidth_700: Font.Bold
|
||||
property int fontWidth_800: Font.ExtraBold
|
||||
property int fontWidth_900: Font.Black
|
||||
|
||||
property var transparent: "#00000000"
|
||||
property int fontWeight_100: Font.Thin
|
||||
property int fontWeight_200: Font.Light
|
||||
property int fontWeight_300: Font.ExtraLight
|
||||
property int fontWeight_400: Font.Normal
|
||||
property int fontWeight_500: Font.Medium
|
||||
property int fontWeight_600: Font.DemiBold
|
||||
property int fontWeight_700: Font.Bold
|
||||
property int fontWeight_800: Font.ExtraBold
|
||||
property int fontWeight_900: Font.Black
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
|
||||
T.Switch {
|
||||
property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
|
||||
property ColorScheme colorScheme
|
||||
|
||||
property bool loading: false
|
||||
|
||||
@ -57,9 +57,9 @@ T.Switch {
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
padding: 0
|
||||
color: control.enabled || control.loading ? colorScheme.background_norm : colorScheme.background_strong
|
||||
color: control.enabled || control.loading ? control.colorScheme.background_norm : control.colorScheme.background_strong
|
||||
border.width: control.enabled && !loading ? 1 : 0
|
||||
border.color: control.hovered ? colorScheme.field_hover : colorScheme.field_norm
|
||||
border.color: control.hovered ? control.colorScheme.field_hover : control.colorScheme.field_norm
|
||||
|
||||
Rectangle {
|
||||
x: Math.max(0, Math.min(parent.width - width, control.visualPosition * parent.width - (width / 2)))
|
||||
@ -72,22 +72,22 @@ T.Switch {
|
||||
|
||||
color: {
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return control.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.checked) {
|
||||
if (control.hovered) {
|
||||
return colorScheme.interaction_norm_hover
|
||||
return control.colorScheme.interaction_norm_hover
|
||||
}
|
||||
|
||||
return colorScheme.interaction_norm
|
||||
return control.colorScheme.interaction_norm
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.field_hover
|
||||
return control.colorScheme.field_hover
|
||||
}
|
||||
|
||||
return colorScheme.field_norm
|
||||
return control.colorScheme.field_norm
|
||||
}
|
||||
|
||||
ColorImage {
|
||||
@ -114,7 +114,7 @@ T.Switch {
|
||||
|
||||
width: 18
|
||||
height: 18
|
||||
color: colorScheme.interaction_norm_hover
|
||||
color: control.colorScheme.interaction_norm_hover
|
||||
source: "../icons/Loader_16.svg"
|
||||
visible: control.loading
|
||||
|
||||
@ -137,13 +137,13 @@ T.Switch {
|
||||
|
||||
text: control.text
|
||||
|
||||
color: control.enabled || control.loading ? colorScheme.text_norm : colorScheme.text_disabled
|
||||
color: control.enabled || control.loading ? control.colorScheme.text_norm : control.colorScheme.text_disabled
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: Style.fontWidth_400
|
||||
font.pixelSize: 14
|
||||
lineHeight: 20
|
||||
font.weight: Style.fontWeight_400
|
||||
font.pixelSize: Style.body_font_size
|
||||
lineHeight: Style.body_line_height
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: 0.2
|
||||
font.letterSpacing: Style.body_letter_spacing
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ import QtQuick.Templates 2.12 as T
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
|
||||
property ColorScheme colorScheme
|
||||
|
||||
property alias background: control.background
|
||||
property alias bottomInset: control.bottomInset
|
||||
@ -104,61 +104,53 @@ Item {
|
||||
|
||||
radius: 4
|
||||
visible: true
|
||||
color: colorScheme.background_norm
|
||||
color: root.colorScheme.background_norm
|
||||
border.color: {
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return root.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.activeFocus) {
|
||||
return colorScheme.interaction_norm
|
||||
return root.colorScheme.interaction_norm
|
||||
}
|
||||
|
||||
if (root.error) {
|
||||
return colorScheme.signal_danger
|
||||
return root.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.field_hover
|
||||
return root.colorScheme.field_hover
|
||||
}
|
||||
|
||||
return colorScheme.field_norm
|
||||
return root.colorScheme.field_norm
|
||||
}
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: label
|
||||
|
||||
anchors.top: root.top
|
||||
anchors.left: root.left
|
||||
anchors.bottomMargin: 4
|
||||
|
||||
color: root.enabled ? colorScheme.text_norm : colorScheme.text_disabled
|
||||
color: root.enabled ? root.colorScheme.text_norm : root.colorScheme.text_disabled
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: Style.fontWidth_600
|
||||
font.pixelSize: 14
|
||||
lineHeight: 20
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: 0.2
|
||||
type: Label.LabelType.Body_semibold
|
||||
}
|
||||
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: hint
|
||||
|
||||
anchors.right: root.right
|
||||
anchors.bottom: controlView.top
|
||||
anchors.bottomMargin: 5
|
||||
|
||||
color: root.enabled ? colorScheme.text_weak : colorScheme.text_disabled
|
||||
color: root.enabled ? root.colorScheme.text_weak : root.colorScheme.text_disabled
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: Style.fontWidth_400
|
||||
font.pixelSize: 12
|
||||
lineHeight: 16
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: 0.4
|
||||
type: Label.LabelType.Caption
|
||||
}
|
||||
|
||||
ColorImage {
|
||||
@ -168,10 +160,11 @@ Item {
|
||||
anchors.top: assistiveText.top
|
||||
anchors.bottom: assistiveText.bottom
|
||||
source: "../icons/ic-exclamation-circle-filled.svg"
|
||||
color: colorScheme.signal_danger
|
||||
color: root.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: assistiveText
|
||||
|
||||
anchors.left: root.error ? errorIcon.right : parent.left
|
||||
@ -181,22 +174,17 @@ Item {
|
||||
|
||||
color: {
|
||||
if (!root.enabled) {
|
||||
return colorScheme.text_disabled
|
||||
return root.colorScheme.text_disabled
|
||||
}
|
||||
|
||||
if (root.error) {
|
||||
return colorScheme.signal_danger
|
||||
return root.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
return colorScheme.text_weak
|
||||
return root.colorScheme.text_weak
|
||||
}
|
||||
|
||||
font.family: Style.font_family
|
||||
font.weight: root.error ? Style.fontWidth_600 : Style.fontWidth_400
|
||||
font.pixelSize: 12
|
||||
lineHeight: 16
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: 0.4
|
||||
type: root.error ? Label.LabelType.Caption_semibold : Label.LabelType.Caption
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
@ -222,8 +210,8 @@ Item {
|
||||
padding: 8
|
||||
leftPadding: 12
|
||||
|
||||
color: control.enabled ? colorScheme.text_norm : colorScheme.text_disabled
|
||||
placeholderTextColor: control.enabled ? colorScheme.text_hint : colorScheme.text_disabled
|
||||
color: control.enabled ? root.colorScheme.text_norm : root.colorScheme.text_disabled
|
||||
placeholderTextColor: control.enabled ? root.colorScheme.text_hint : root.colorScheme.text_disabled
|
||||
|
||||
selectionColor: control.palette.highlight
|
||||
selectedTextColor: control.palette.highlightedText
|
||||
@ -231,7 +219,7 @@ Item {
|
||||
cursorDelegate: Rectangle {
|
||||
id: cursor
|
||||
width: 1
|
||||
color: colorScheme.interaction_norm
|
||||
color: root.colorScheme.interaction_norm
|
||||
visible: control.activeFocus && !control.readOnly && control.selectionStart === control.selectionEnd
|
||||
|
||||
Connections {
|
||||
|
||||
@ -21,10 +21,11 @@ import QtQuick.Controls 2.12
|
||||
import QtQuick.Controls.impl 2.12
|
||||
import QtQuick.Templates 2.12 as T
|
||||
import QtQuick.Layouts 1.12
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle
|
||||
property ColorScheme colorScheme
|
||||
|
||||
property alias background: control.background
|
||||
property alias bottomInset: control.bottomInset
|
||||
@ -91,7 +92,7 @@ Item {
|
||||
property alias hint: hint.text
|
||||
property alias assistiveText: assistiveText.text
|
||||
|
||||
property var echoMode: TextInput.Normal
|
||||
property int echoMode: TextInput.Normal
|
||||
|
||||
property bool error: false
|
||||
|
||||
@ -117,7 +118,7 @@ Item {
|
||||
function selectAll() { control.selectAll() }
|
||||
function selectWord() { control.selectWord() }
|
||||
function undo() { control.undo() }
|
||||
function forceActiveFocus() {control.forceActiveFocus()}
|
||||
function forceActiveFocus() { control.forceActiveFocus() }
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
@ -127,22 +128,22 @@ Item {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
|
||||
ProtonLabel {
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: label
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
color: root.enabled ? colorScheme.text_norm : colorScheme.text_disabled
|
||||
font.weight: Style.fontWidth_600
|
||||
state: "body"
|
||||
type: Label.LabelType.Body_semibold
|
||||
}
|
||||
|
||||
ProtonLabel {
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: hint
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
color: root.enabled ? colorScheme.text_weak : colorScheme.text_disabled
|
||||
color: root.enabled ? root.colorScheme.text_weak : root.colorScheme.text_disabled
|
||||
horizontalAlignment: Text.AlignRight
|
||||
state: "caption"
|
||||
type: Label.LabelType.Caption
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,25 +158,25 @@ Item {
|
||||
|
||||
radius: 4
|
||||
visible: true
|
||||
color: colorScheme.background_norm
|
||||
color: root.colorScheme.background_norm
|
||||
border.color: {
|
||||
if (!control.enabled) {
|
||||
return colorScheme.field_disabled
|
||||
return root.colorScheme.field_disabled
|
||||
}
|
||||
|
||||
if (control.activeFocus) {
|
||||
return colorScheme.interaction_norm
|
||||
return root.colorScheme.interaction_norm
|
||||
}
|
||||
|
||||
if (root.error) {
|
||||
return colorScheme.signal_danger
|
||||
return root.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
if (control.hovered) {
|
||||
return colorScheme.field_hover
|
||||
return root.colorScheme.field_hover
|
||||
}
|
||||
|
||||
return colorScheme.field_norm
|
||||
return root.colorScheme.field_norm
|
||||
}
|
||||
border.width: 1
|
||||
|
||||
@ -193,25 +194,27 @@ Item {
|
||||
Layout.fillWidth: true
|
||||
|
||||
implicitWidth: implicitBackgroundWidth + leftInset + rightInset
|
||||
|| Math.max(contentWidth, placeholder.implicitWidth) + leftPadding + rightPadding
|
||||
|| Math.max(contentWidth, placeholder.implicitWidth) + leftPadding + rightPadding
|
||||
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
|
||||
contentHeight + topPadding + bottomPadding,
|
||||
placeholder.implicitHeight + topPadding + bottomPadding)
|
||||
contentHeight + topPadding + bottomPadding,
|
||||
placeholder.implicitHeight + topPadding + bottomPadding)
|
||||
|
||||
padding: 8
|
||||
leftPadding: 12
|
||||
|
||||
color: control.enabled ? colorScheme.text_norm : colorScheme.text_disabled
|
||||
color: control.enabled ? root.colorScheme.text_norm : root.colorScheme.text_disabled
|
||||
|
||||
selectionColor: control.palette.highlight
|
||||
selectedTextColor: control.palette.highlightedText
|
||||
placeholderTextColor: control.enabled ? colorScheme.text_hint : colorScheme.text_disabled
|
||||
placeholderTextColor: control.enabled ? root.colorScheme.text_hint : root.colorScheme.text_disabled
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
|
||||
echoMode: eyeButton.checked ? TextInput.Normal : root.echoMode
|
||||
|
||||
cursorDelegate: Rectangle {
|
||||
id: cursor
|
||||
width: 1
|
||||
color: colorScheme.interaction_norm
|
||||
color: root.colorScheme.interaction_norm
|
||||
visible: control.activeFocus && !control.readOnly && control.selectionStart === control.selectionEnd
|
||||
|
||||
Connections {
|
||||
@ -268,22 +271,16 @@ Item {
|
||||
}
|
||||
|
||||
Button {
|
||||
colorScheme: root.colorScheme
|
||||
id: eyeButton
|
||||
|
||||
Layout.fillHeight: true
|
||||
|
||||
visible: root.echoMode === TextInput.Password
|
||||
icon.source: control.echoMode == TextInput.Password ? "../icons/ic-eye.svg" : "../icons/ic-eye-slash.svg"
|
||||
icon.color: control.color
|
||||
background: Rectangle{color: "#00000000"}
|
||||
onClicked: {
|
||||
if (control.echoMode == TextInput.Password) {
|
||||
control.echoMode = TextInput.Normal
|
||||
} else {
|
||||
control.echoMode = TextInput.Password
|
||||
}
|
||||
}
|
||||
Component.onCompleted: control.echoMode = root.echoMode
|
||||
background: Item { }
|
||||
checkable: true
|
||||
icon.source: checked ? "../icons/ic-eye-slash.svg" : "../icons/ic-eye.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -292,17 +289,16 @@ Item {
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
|
||||
// FIXME: maybe somewhere in the future there will be an Icon component capable of setting color to the icon
|
||||
// but before that moment we need to use IconLabel
|
||||
IconLabel {
|
||||
ColorImage {
|
||||
id: errorIcon
|
||||
|
||||
visible: root.error && (assistiveText.text.length > 0)
|
||||
icon.source: "../icons/ic-exclamation-circle-filled.svg"
|
||||
icon.color: colorScheme.signal_danger
|
||||
source: "../icons/ic-exclamation-circle-filled.svg"
|
||||
color: root.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
ProtonLabel {
|
||||
Label {
|
||||
colorScheme: root.colorScheme
|
||||
id: assistiveText
|
||||
|
||||
Layout.fillHeight: true
|
||||
@ -311,18 +307,17 @@ Item {
|
||||
|
||||
color: {
|
||||
if (!root.enabled) {
|
||||
return colorScheme.text_disabled
|
||||
return root.colorScheme.text_disabled
|
||||
}
|
||||
|
||||
if (root.error) {
|
||||
return colorScheme.signal_danger
|
||||
return root.colorScheme.signal_danger
|
||||
}
|
||||
|
||||
return colorScheme.text_weak
|
||||
return root.colorScheme.text_weak
|
||||
}
|
||||
|
||||
font.weight: root.error ? Style.fontWidth_600 : Style.fontWidth_400
|
||||
state: "caption"
|
||||
type: root.error ? Label.LabelType.Caption_semibold : Label.LabelType.Caption
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,36 @@
|
||||
# Copyright (c) 2021 Proton Technologies AG
|
||||
#
|
||||
# This file is part of ProtonMail Bridge.
|
||||
#
|
||||
# ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
module QQtQuick.Controls.Proton
|
||||
depends QtQuick.Controls 2.12
|
||||
|
||||
singleton ProtonStyle 4.0 Style.qml
|
||||
Banner 4.0 Banner.qml
|
||||
ColorScheme 4.0 ColorScheme.qml
|
||||
|
||||
ApplicationWindow 4.0 ApplicationWindow.qml
|
||||
Button 4.0 Button.qml
|
||||
CheckBox 4.0 CheckBox.qml
|
||||
ProtonLabel 4.0 ProtonLabel.qml
|
||||
RoundedRectangle 4.0 RoundedRectangle.qml
|
||||
Dialog 4.0 Dialog.qml
|
||||
Label 4.0 Label.qml
|
||||
Menu 4.0 Menu.qml
|
||||
MenuItem 4.0 MenuItem.qml
|
||||
Popup 4.0 Popup.qml
|
||||
RadioButton 4.0 RadioButton.qml
|
||||
RoundedRectangle 4.0 RoundedRectangle.qml
|
||||
Switch 4.0 Switch.qml
|
||||
TextArea 4.0 TextArea.qml
|
||||
TextField 4.0 TextField.qml
|
||||
|
||||
Reference in New Issue
Block a user