mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-15 14:56:42 +00:00
We build too many walls and not enough bridges
This commit is contained in:
34
internal/frontend/qml/ProtonUI/AccessibleButton.qml
Normal file
34
internal/frontend/qml/ProtonUI/AccessibleButton.qml
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// default options to make button accessible
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
Button {
|
||||
function clearText(value) {
|
||||
// remove font-awesome chars
|
||||
return value.replace(/[\uf000-\uf2e0]/g,'')
|
||||
}
|
||||
Accessible.onPressAction: clicked()
|
||||
Accessible.ignored: !enabled || !visible
|
||||
Accessible.name: clearText(text)
|
||||
Accessible.description: clearText(text)
|
||||
}
|
||||
|
||||
40
internal/frontend/qml/ProtonUI/AccessibleSelectableText.qml
Normal file
40
internal/frontend/qml/ProtonUI/AccessibleSelectableText.qml
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// default options to make text accessible and selectable
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
TextEdit {
|
||||
function clearText(value) {
|
||||
// substitue the copyright symbol by the text and remove the font-awesome chars and HTML tags
|
||||
return value.replace(/\uf1f9/g,'Copyright').replace(/[\uf000-\uf2e0]/g,'').replace(/<[^>]+>/g,'')
|
||||
}
|
||||
|
||||
readOnly: true
|
||||
selectByKeyboard: true
|
||||
selectByMouse: true
|
||||
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: clearText(text)
|
||||
Accessible.description: clearText(text)
|
||||
Accessible.focusable: true
|
||||
Accessible.ignored: !enabled || !visible || text == ""
|
||||
}
|
||||
|
||||
|
||||
40
internal/frontend/qml/ProtonUI/AccessibleText.qml
Normal file
40
internal/frontend/qml/ProtonUI/AccessibleText.qml
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// default options to make text accessible
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
Text {
|
||||
function clearText(value) {
|
||||
// substitue the copyright symbol by the text and remove the font-awesome chars and HTML tags
|
||||
return value.replace(/\uf1f9/g,'Copyright').replace(/[\uf000-\uf2e0]/g,'').replace(/<[^>]+>/g,'')
|
||||
}
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: clearText(text)
|
||||
Accessible.description: clearText(text)
|
||||
Accessible.focusable: true
|
||||
Accessible.ignored: !enabled || !visible || text == ""
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
140
internal/frontend/qml/ProtonUI/AccountView.qml
Normal file
140
internal/frontend/qml/ProtonUI/AccountView.qml
Normal file
@ -0,0 +1,140 @@
|
||||
// Copyright (c) 2020 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.8
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
signal addAccount()
|
||||
|
||||
property alias numAccounts : listAccounts.count
|
||||
property alias model : listAccounts.model
|
||||
property alias delegate : listAccounts.delegate
|
||||
property int separatorNoAccount : viewContent.height-Style.accounts.heightFooter
|
||||
property bool hasFooter : true
|
||||
|
||||
// must have wrapper
|
||||
Rectangle {
|
||||
id: wrapper
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: Style.main.background
|
||||
|
||||
// content
|
||||
ListView {
|
||||
id: listAccounts
|
||||
anchors {
|
||||
top : parent.top
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
bottom : hasFooter ? addAccFooter.top : parent.bottom
|
||||
}
|
||||
orientation: ListView.Vertical
|
||||
clip: true
|
||||
cacheBuffer: 2500
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: Style.main.rightMargin/4
|
||||
}
|
||||
width: Style.main.rightMargin/3
|
||||
Accessible.ignored: true
|
||||
}
|
||||
header: Rectangle {
|
||||
width : wrapper.width
|
||||
height : root.numAccounts!=0 ? Style.accounts.heightHeader : root.separatorNoAccount
|
||||
color : "transparent"
|
||||
AccessibleText { // Placeholder on empty
|
||||
anchors {
|
||||
centerIn: parent
|
||||
}
|
||||
visible: root.numAccounts==0
|
||||
text : qsTr("No accounts added", "displayed when there are no accounts added")
|
||||
font.pointSize : Style.main.fontSize * Style.pt
|
||||
color : Style.main.textDisabled
|
||||
}
|
||||
Text { // Account
|
||||
anchors {
|
||||
left : parent.left
|
||||
leftMargin : Style.main.leftMargin
|
||||
verticalCenter : parent.verticalCenter
|
||||
}
|
||||
visible: root.numAccounts!=0
|
||||
font.bold : true
|
||||
font.pointSize : Style.main.fontSize * Style.pt
|
||||
text : qsTr("ACCOUNT", "title of column that displays account name")
|
||||
color : Style.main.textDisabled
|
||||
}
|
||||
Text { // Status
|
||||
anchors {
|
||||
left : parent.left
|
||||
leftMargin : Style.accounts.leftMargin2
|
||||
verticalCenter : parent.verticalCenter
|
||||
}
|
||||
visible: root.numAccounts!=0
|
||||
font.bold : true
|
||||
font.pointSize : Style.main.fontSize * Style.pt
|
||||
text : qsTr("STATUS", "title of column that displays connected or disconnected status")
|
||||
color : Style.main.textDisabled
|
||||
}
|
||||
Text { // Actions
|
||||
anchors {
|
||||
left : parent.left
|
||||
leftMargin : Style.accounts.leftMargin3
|
||||
verticalCenter : parent.verticalCenter
|
||||
}
|
||||
visible: root.numAccounts!=0
|
||||
font.bold : true
|
||||
font.pointSize : Style.main.fontSize * Style.pt
|
||||
text : qsTr("ACTIONS", "title of column that displays log out and log in actions for each account")
|
||||
color : Style.main.textDisabled
|
||||
}
|
||||
// line
|
||||
Rectangle {
|
||||
anchors {
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
bottom : parent.bottom
|
||||
}
|
||||
visible: root.numAccounts!=0
|
||||
color: Style.accounts.line
|
||||
height: Style.accounts.heightLine
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AddAccountBar {
|
||||
id: addAccFooter
|
||||
visible: hasFooter
|
||||
anchors {
|
||||
left : parent.left
|
||||
bottom : parent.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: StandardKey.SelectAll
|
||||
onActivated: root.addAccount()
|
||||
}
|
||||
}
|
||||
69
internal/frontend/qml/ProtonUI/AddAccountBar.qml
Normal file
69
internal/frontend/qml/ProtonUI/AddAccountBar.qml
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Bar with add account button and help
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
|
||||
Rectangle {
|
||||
width : parent.width
|
||||
height : Style.accounts.heightFooter
|
||||
color: "transparent"
|
||||
Rectangle {
|
||||
anchors {
|
||||
top : parent.top
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
}
|
||||
height: Style.accounts.heightLine
|
||||
color: Style.accounts.line
|
||||
}
|
||||
ClickIconText {
|
||||
id: buttonAddAccount
|
||||
anchors {
|
||||
left : parent.left
|
||||
leftMargin : Style.main.leftMargin
|
||||
verticalCenter : parent.verticalCenter
|
||||
}
|
||||
textColor : Style.main.textBlue
|
||||
iconText : Style.fa.plus_circle
|
||||
text : qsTr("Add Account", "begins the flow to log in to an account that is not yet listed")
|
||||
textBold : true
|
||||
onClicked : root.addAccount()
|
||||
Accessible.description: {
|
||||
if (gui.winMain!=null) {
|
||||
return text + (gui.winMain.addAccountTip.visible? ", "+gui.winMain.addAccountTip.text : "")
|
||||
}
|
||||
return buttonAddAccount.text
|
||||
}
|
||||
}
|
||||
ClickIconText {
|
||||
id: buttonHelp
|
||||
anchors {
|
||||
right : parent.right
|
||||
rightMargin : Style.main.rightMargin
|
||||
verticalCenter : parent.verticalCenter
|
||||
}
|
||||
textColor : Style.main.textDisabled
|
||||
iconText : Style.fa.question_circle
|
||||
text : qsTr("Help", "directs the user to the online user guide")
|
||||
textBold : true
|
||||
onClicked : go.openManual()
|
||||
}
|
||||
}
|
||||
170
internal/frontend/qml/ProtonUI/BubbleNote.qml
Normal file
170
internal/frontend/qml/ProtonUI/BubbleNote.qml
Normal file
@ -0,0 +1,170 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Notify user
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
property int posx // x-coordinate of triangle
|
||||
property bool isTriangleBelow
|
||||
property string text
|
||||
property alias bubbleColor: bubble.color
|
||||
anchors {
|
||||
top : tabbar.bottom
|
||||
left : tabbar.left
|
||||
leftMargin : {
|
||||
// position of bubble calculated from posx
|
||||
return Math.max(
|
||||
Style.main.leftMargin, // keep minimal left margin
|
||||
Math.min(
|
||||
root.posx - root.width/2, // fit triangle in the middle if possible
|
||||
tabbar.width - root.width - Style.main.rightMargin // keep minimal right margin
|
||||
)
|
||||
)
|
||||
}
|
||||
topMargin: 0
|
||||
}
|
||||
height : triangle.height + bubble.height
|
||||
width : bubble.width
|
||||
color : "transparent"
|
||||
visible : false
|
||||
|
||||
|
||||
Rectangle {
|
||||
id : triangle
|
||||
anchors {
|
||||
top : root.isTriangleBelow ? undefined : root.top
|
||||
bottom : root.isTriangleBelow ? root.bottom : undefined
|
||||
bottomMargin : 1*Style.px
|
||||
left : root.left
|
||||
leftMargin : root.posx - triangle.width/2 - root.anchors.leftMargin
|
||||
}
|
||||
width: 2*Style.tabbar.heightTriangle+2
|
||||
height: Style.tabbar.heightTriangle
|
||||
color: "transparent"
|
||||
Canvas {
|
||||
anchors.fill: parent
|
||||
rotation: root.isTriangleBelow ? 180 : 0
|
||||
onPaint: {
|
||||
var ctx = getContext("2d")
|
||||
ctx.fillStyle = bubble.color
|
||||
ctx.moveTo(0 , height)
|
||||
ctx.lineTo(width/2, 0)
|
||||
ctx.lineTo(width , height)
|
||||
ctx.closePath()
|
||||
ctx.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: bubble
|
||||
anchors {
|
||||
top: root.top
|
||||
left: root.left
|
||||
topMargin: (root.isTriangleBelow ? 0 : triangle.height)
|
||||
}
|
||||
width : mainText.contentWidth + Style.main.leftMargin + Style.main.rightMargin
|
||||
height : 2*Style.main.fontSize
|
||||
radius : Style.bubble.radius
|
||||
color : Style.bubble.background
|
||||
|
||||
AccessibleText {
|
||||
id: mainText
|
||||
anchors {
|
||||
horizontalCenter : parent.horizontalCenter
|
||||
top: parent.top
|
||||
topMargin : Style.main.fontSize
|
||||
}
|
||||
|
||||
text: "<html><style>a { color: "+Style.main.textBlue+";}</style>"+root.text+"<html>"
|
||||
width : Style.bubble.width - ( Style.main.leftMargin + Style.main.rightMargin )
|
||||
font.pointSize: Style.main.fontSize * Style.pt
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WordWrap
|
||||
color: Style.bubble.text
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: mainText
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
|
||||
Accessible.name: qsTr("Message")
|
||||
Accessible.description: root.text
|
||||
}
|
||||
|
||||
ButtonRounded {
|
||||
id: okButton
|
||||
visible: !root.isTriangleBelow
|
||||
anchors {
|
||||
bottom : parent.bottom
|
||||
horizontalCenter : parent.horizontalCenter
|
||||
bottomMargin : Style.main.fontSize
|
||||
}
|
||||
text: qsTr("Okay", "confirms and dismisses a notification")
|
||||
height: Style.main.fontSize*2
|
||||
color_main: Style.main.text
|
||||
color_minor: Style.main.textBlue
|
||||
isOpaque: true
|
||||
onClicked: hide()
|
||||
}
|
||||
}
|
||||
|
||||
function place(index) {
|
||||
if (index < 0) {
|
||||
// add accounts
|
||||
root.isTriangleBelow = true
|
||||
bubble.height = 3.25*Style.main.fontSize
|
||||
root.posx = 2*Style.main.leftMargin
|
||||
bubble.width = mainText.contentWidth - Style.main.leftMargin
|
||||
} else {
|
||||
root.isTriangleBelow = false
|
||||
bubble.height = (
|
||||
bubble.anchors.topMargin + // from top
|
||||
mainText.contentHeight + // the text content
|
||||
Style.main.fontSize + // gap between button
|
||||
okButton.height + okButton.anchors.bottomMargin // from bottom and button
|
||||
)
|
||||
if (index < 3) {
|
||||
// possition accordig to top tab
|
||||
var margin = Style.main.leftMargin + Style.tabbar.widthButton/2
|
||||
root.posx = margin + index*tabbar.spacing
|
||||
} else {
|
||||
// quit button
|
||||
root.posx = tabbar.width - 2*Style.main.rightMargin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function show() {
|
||||
root.visible=true
|
||||
gui.winMain.activeContent = false
|
||||
}
|
||||
|
||||
function hide() {
|
||||
root.visible=false
|
||||
go.bubbleClosed()
|
||||
gui.winMain.activeContent = true
|
||||
gui.winMain.tabbar.focusButton()
|
||||
}
|
||||
}
|
||||
337
internal/frontend/qml/ProtonUI/BugReportWindow.qml
Normal file
337
internal/frontend/qml/ProtonUI/BugReportWindow.qml
Normal file
@ -0,0 +1,337 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Window for sending a bug report
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Window {
|
||||
id:root
|
||||
property alias userAddress : userAddress
|
||||
property alias clientVersion : clientVersion
|
||||
|
||||
width : Style.bugreport.width
|
||||
height : Style.bugreport.height
|
||||
minimumWidth : Style.bugreport.width
|
||||
maximumWidth : Style.bugreport.width
|
||||
minimumHeight : Style.bugreport.height
|
||||
maximumHeight : Style.bugreport.height
|
||||
|
||||
property color inputBorderColor : Style.main.text
|
||||
|
||||
color : "transparent"
|
||||
flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint
|
||||
title : "ProtonMail Bridge - Bug report"
|
||||
visible : false
|
||||
|
||||
WindowTitleBar {
|
||||
id: titleBar
|
||||
window: root
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id:background
|
||||
color: Style.main.background
|
||||
anchors {
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
top : titleBar.bottom
|
||||
bottom : parent.bottom
|
||||
}
|
||||
border {
|
||||
width: Style.main.border
|
||||
color: Style.tabbar.background
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id:content
|
||||
anchors {
|
||||
fill : parent
|
||||
leftMargin : Style.main.leftMargin
|
||||
rightMargin : Style.main.rightMargin
|
||||
bottomMargin : Style.main.rightMargin
|
||||
topMargin : Style.main.rightMargin + titleBar.height
|
||||
}
|
||||
color: "transparent"
|
||||
|
||||
// Description in flickable
|
||||
Flickable {
|
||||
id: descripWrapper
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
height: content.height - (
|
||||
(clientVersion.visible ? clientVersion.height + Style.dialog.fontSize : 0) +
|
||||
userAddress.height + Style.dialog.fontSize +
|
||||
securityNote.contentHeight + Style.dialog.fontSize +
|
||||
cancelButton.height + Style.dialog.fontSize
|
||||
)
|
||||
clip: true
|
||||
contentWidth : width
|
||||
contentHeight : height
|
||||
|
||||
TextArea.flickable: TextArea {
|
||||
id: description
|
||||
focus: true
|
||||
wrapMode: TextEdit.Wrap
|
||||
placeholderText: qsTr ("Please briefly describe the bug(s) you have encountered...", "bug report instructions")
|
||||
background : Rectangle {
|
||||
color : Style.dialog.background
|
||||
radius: Style.dialog.radiusButton
|
||||
border {
|
||||
color : root.inputBorderColor
|
||||
width : Style.dialog.borderInput
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
anchors.fill: parent
|
||||
radius: 8 * Style.px
|
||||
}
|
||||
}
|
||||
color: Style.main.text
|
||||
font.pointSize: Style.dialog.fontSize * Style.pt
|
||||
selectionColor: Style.main.textBlue
|
||||
selectByKeyboard: true
|
||||
selectByMouse: true
|
||||
KeyNavigation.tab: clientVersion
|
||||
KeyNavigation.priority: KeyNavigation.BeforeItem
|
||||
}
|
||||
|
||||
ScrollBar.vertical : ScrollBar{}
|
||||
}
|
||||
|
||||
// Client
|
||||
TextLabel {
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: descripWrapper.bottom
|
||||
topMargin: Style.dialog.fontSize
|
||||
}
|
||||
visible: clientVersion.visible
|
||||
width: parent.width/2.618
|
||||
text: qsTr ("Email client:", "in the bug report form, which third-party email client is being used")
|
||||
font.pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: clientVersion
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: descripWrapper.bottom
|
||||
topMargin: Style.dialog.fontSize
|
||||
}
|
||||
placeholderText: qsTr("e.g. Thunderbird", "in the bug report form, placeholder text for email client")
|
||||
width: parent.width/1.618
|
||||
|
||||
color : Style.dialog.text
|
||||
selectionColor : Style.main.textBlue
|
||||
selectByMouse : true
|
||||
font.pointSize : Style.dialog.fontSize * Style.pt
|
||||
padding : Style.dialog.radiusButton
|
||||
|
||||
background: Rectangle {
|
||||
color : Style.dialog.background
|
||||
radius: Style.dialog.radiusButton
|
||||
border {
|
||||
color : root.inputBorderColor
|
||||
width : Style.dialog.borderInput
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
anchors.fill: parent
|
||||
radius: 8 * Style.px
|
||||
}
|
||||
}
|
||||
onAccepted: userAddress.focus = true
|
||||
}
|
||||
|
||||
// Address
|
||||
TextLabel {
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: clientVersion.visible ? clientVersion.bottom : descripWrapper.bottom
|
||||
topMargin: Style.dialog.fontSize
|
||||
}
|
||||
color: Style.dialog.text
|
||||
width: parent.width/2.618
|
||||
text: qsTr ("Contact email:", "in the bug report form, an email to contact the user at")
|
||||
font.pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: userAddress
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: clientVersion.visible ? clientVersion.bottom : descripWrapper.bottom
|
||||
topMargin: Style.dialog.fontSize
|
||||
}
|
||||
placeholderText: "benjerry@protonmail.com"
|
||||
width: parent.width/1.618
|
||||
|
||||
color : Style.dialog.text
|
||||
selectionColor : Style.main.textBlue
|
||||
selectByMouse : true
|
||||
font.pointSize : Style.dialog.fontSize * Style.pt
|
||||
padding : Style.dialog.radiusButton
|
||||
|
||||
background: Rectangle {
|
||||
color : Style.dialog.background
|
||||
radius: Style.dialog.radiusButton
|
||||
border {
|
||||
color : root.inputBorderColor
|
||||
width : Style.dialog.borderInput
|
||||
}
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
anchors.fill: parent
|
||||
radius: 8 * Style.px
|
||||
}
|
||||
}
|
||||
onAccepted: root.submit()
|
||||
}
|
||||
|
||||
// Note
|
||||
AccessibleText {
|
||||
id: securityNote
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: userAddress.bottom
|
||||
topMargin: Style.dialog.fontSize
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
color: Style.dialog.text
|
||||
font.pointSize : Style.dialog.fontSize * Style.pt
|
||||
text:
|
||||
"<span style='font-family: " + Style.fontawesome.name + "'>" + Style.fa.exclamation_triangle + "</span> " +
|
||||
qsTr("Bug reports are not end-to-end encrypted!", "The first part of warning in bug report form") + " " +
|
||||
qsTr("Please do not send any sensitive information.", "The second part of warning in bug report form") + " " +
|
||||
qsTr("Contact us at security@protonmail.com for critical security issues.", "The third part of warning in bug report form")
|
||||
}
|
||||
|
||||
// buttons
|
||||
ButtonRounded {
|
||||
id: cancelButton
|
||||
anchors {
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
fa_icon: Style.fa.times
|
||||
text: qsTr ("Cancel", "dismisses current action")
|
||||
onClicked : root.hide()
|
||||
}
|
||||
ButtonRounded {
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
isOpaque: true
|
||||
color_main: "white"
|
||||
color_minor: Style.main.textBlue
|
||||
fa_icon: Style.fa.send
|
||||
text: qsTr ("Send", "button sends bug report")
|
||||
onClicked : root.submit()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: notification
|
||||
property bool isOK: true
|
||||
visible: false
|
||||
color: background.color
|
||||
anchors.fill: background
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
color: Style.dialog.text
|
||||
width: background.width*0.6180
|
||||
text: notification.isOK ?
|
||||
qsTr ( "Bug report successfully sent." , "notification message about bug sending" ) :
|
||||
qsTr ( "Unable to submit bug report." , "notification message about bug sending" )
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pointSize: Style.dialog.titleSize * Style.pt
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: notificationTimer
|
||||
interval: 3000
|
||||
repeat: false
|
||||
onTriggered : {
|
||||
notification.visible=false
|
||||
if (notification.isOK) root.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function submit(){
|
||||
if(root.areInputsOK()){
|
||||
root.notify(go.sendBug(description.text, clientVersion.text, userAddress.text ))
|
||||
}
|
||||
}
|
||||
|
||||
function isEmpty(input){
|
||||
if (input.text=="") {
|
||||
input.focus=true
|
||||
input.placeholderText = qsTr("Field required", "a field that must be filled in to submit form")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function areInputsOK() {
|
||||
var isOK = true
|
||||
if (isEmpty(userAddress)) { isOK=false }
|
||||
if (clientVersion.visible && isEmpty(clientVersion)) { isOK=false }
|
||||
if (isEmpty(description)) { isOK=false }
|
||||
return isOK
|
||||
}
|
||||
|
||||
function clear() {
|
||||
description.text = ""
|
||||
clientVersion.text = ""
|
||||
notification.visible = false
|
||||
}
|
||||
|
||||
signal prefill()
|
||||
|
||||
function notify(isOK){
|
||||
notification.isOK = isOK
|
||||
notification.visible = true
|
||||
notificationTimer.start()
|
||||
}
|
||||
|
||||
|
||||
function show() {
|
||||
prefill()
|
||||
root.visible=true
|
||||
}
|
||||
|
||||
function hide() {
|
||||
clear()
|
||||
root.visible=false
|
||||
}
|
||||
}
|
||||
100
internal/frontend/qml/ProtonUI/ButtonIconText.qml
Normal file
100
internal/frontend/qml/ProtonUI/ButtonIconText.qml
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Button with full window width containing two icons (left and right) and text
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
AccessibleButton {
|
||||
id: root
|
||||
property alias leftIcon : leftIcon
|
||||
property alias rightIcon : rightIcon
|
||||
property alias main : mainText
|
||||
|
||||
// dimensions
|
||||
width : viewContent.width
|
||||
height : Style.main.heightRow
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
leftPadding: Style.main.leftMargin
|
||||
rightPadding: Style.main.rightMargin
|
||||
|
||||
background : Rectangle{
|
||||
color: Qt.lighter(Style.main.background, root.hovered || root.activeFocus ? ( root.pressed ? 1.2: 1.1) :1.0)
|
||||
// line
|
||||
Rectangle {
|
||||
anchors.bottom : parent.bottom
|
||||
width : parent.width
|
||||
height : Style.main.heightLine
|
||||
color : Style.main.line
|
||||
}
|
||||
// pointing cursor
|
||||
MouseArea {
|
||||
anchors.fill : parent
|
||||
cursorShape : Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
contentItem : Rectangle {
|
||||
color: "transparent"
|
||||
// Icon left
|
||||
Text {
|
||||
id: leftIcon
|
||||
anchors {
|
||||
verticalCenter : parent.verticalCenter
|
||||
left : parent.left
|
||||
}
|
||||
font {
|
||||
family : Style.fontawesome.name
|
||||
pointSize : Style.settings.iconSize * Style.pt
|
||||
}
|
||||
color : Style.main.textBlue
|
||||
text : Style.fa.hashtag
|
||||
}
|
||||
|
||||
// Icon/Text right
|
||||
Text {
|
||||
id: rightIcon
|
||||
anchors {
|
||||
verticalCenter : parent.verticalCenter
|
||||
right : parent.right
|
||||
}
|
||||
font {
|
||||
family : Style.fontawesome.name
|
||||
pointSize : Style.settings.iconSize * Style.pt
|
||||
}
|
||||
color : Style.main.textBlue
|
||||
text : Style.fa.hashtag
|
||||
}
|
||||
|
||||
// Label
|
||||
Text {
|
||||
id: mainText
|
||||
anchors {
|
||||
verticalCenter : parent.verticalCenter
|
||||
left : leftIcon.right
|
||||
leftMargin : leftIcon.text!="" ? Style.main.leftMargin : 0
|
||||
}
|
||||
font.pointSize : Style.settings.fontSize * Style.pt
|
||||
color : Style.main.text
|
||||
text : root.text
|
||||
}
|
||||
}
|
||||
}
|
||||
92
internal/frontend/qml/ProtonUI/ButtonRounded.qml
Normal file
92
internal/frontend/qml/ProtonUI/ButtonRounded.qml
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Classic button with icon and text
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.1
|
||||
import QtGraphicalEffects 1.0
|
||||
import ProtonUI 1.0
|
||||
|
||||
AccessibleButton {
|
||||
id: root
|
||||
property string fa_icon : ""
|
||||
property color color_main : Style.dialog.text
|
||||
property color color_minor : "transparent"
|
||||
property bool isOpaque : false
|
||||
|
||||
text : "undef"
|
||||
state : root.hovered || root.activeFocus ? "hover" : "normal"
|
||||
width : Style.dialog.widthButton
|
||||
height : Style.dialog.heightButton
|
||||
scale : root.pressed ? 0.96 : 1.00
|
||||
|
||||
background: Rectangle {
|
||||
border {
|
||||
color : root.color_main
|
||||
width : root.isOpaque ? 0 : Style.dialog.borderButton
|
||||
}
|
||||
radius : Style.dialog.radiusButton
|
||||
color : root.isOpaque ? root.color_minor : "transparent"
|
||||
|
||||
MouseArea {
|
||||
anchors.fill : parent
|
||||
cursorShape : Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Rectangle {
|
||||
color: "transparent"
|
||||
|
||||
Row {
|
||||
id: mainText
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
Text {
|
||||
font {
|
||||
pointSize : Style.dialog.fontSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
color : color_main
|
||||
text : root.fa_icon=="" ? "" : root.fa_icon + " "
|
||||
}
|
||||
|
||||
Text {
|
||||
font {
|
||||
pointSize : Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
color : color_main
|
||||
text : root.text
|
||||
}
|
||||
}
|
||||
|
||||
Glow {
|
||||
id: mainTextEffect
|
||||
anchors.fill : mainText
|
||||
source: mainText
|
||||
color: color_main
|
||||
opacity: 0.33
|
||||
}
|
||||
}
|
||||
|
||||
states :[
|
||||
State {name: "normal"; PropertyChanges{ target: mainTextEffect; radius: 0 ; visible: false } },
|
||||
State {name: "hover" ; PropertyChanges{ target: mainTextEffect; radius: 3*Style.px ; visible: true } }
|
||||
]
|
||||
}
|
||||
55
internal/frontend/qml/ProtonUI/CheckBoxLabel.qml
Normal file
55
internal/frontend/qml/ProtonUI/CheckBoxLabel.qml
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// input for date range
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import ProtonUI 1.0
|
||||
|
||||
CheckBox {
|
||||
id: root
|
||||
spacing: Style.dialog.spacing
|
||||
padding: 0
|
||||
property color textColor : Style.main.text
|
||||
property color checkedColor : Style.main.textBlue
|
||||
property color uncheckedColor : Style.main.textInactive
|
||||
property string checkedSymbol : Style.fa.check_square_o
|
||||
property string uncheckedSymbol : Style.fa.square_o
|
||||
background: Rectangle {
|
||||
color: Style.transparent
|
||||
}
|
||||
indicator: Text {
|
||||
text : root.checked ? root.checkedSymbol : root.uncheckedSymbol
|
||||
color : root.checked ? root.checkedColor : root.uncheckedColor
|
||||
font {
|
||||
pointSize : Style.dialog.iconSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
}
|
||||
contentItem: Text {
|
||||
id: label
|
||||
text : root.text
|
||||
color : root.textColor
|
||||
font {
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: Style.dialog.iconSize + root.spacing
|
||||
}
|
||||
}
|
||||
98
internal/frontend/qml/ProtonUI/ClickIconText.qml
Normal file
98
internal/frontend/qml/ProtonUI/ClickIconText.qml
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// No border button with icon
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
AccessibleButton {
|
||||
id: root
|
||||
|
||||
property string iconText : Style.fa.hashtag
|
||||
property color textColor : Style.main.text
|
||||
property int fontSize : Style.main.fontSize
|
||||
property int iconSize : Style.main.iconSize
|
||||
property int margin : iconText!="" ? Style.main.leftMarginButton : 0.0
|
||||
property bool iconOnRight : false
|
||||
property bool textBold : false
|
||||
property bool textUnderline : false
|
||||
|
||||
|
||||
TextMetrics {
|
||||
id: metrics
|
||||
text: root.text
|
||||
font: showText.font
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: metricsIcon
|
||||
text : root.iconText
|
||||
font : showIcon.font
|
||||
}
|
||||
|
||||
scale : root.pressed ? 0.96 : root.activeFocus ? 1.05 : 1.0
|
||||
height : Math.max(metrics.height, metricsIcon.height)
|
||||
width : metricsIcon.width*1.5 + margin + metrics.width + 4.0
|
||||
padding : 0.0
|
||||
|
||||
background : Rectangle {
|
||||
color: Style.transparent
|
||||
MouseArea {
|
||||
anchors.fill : parent
|
||||
cursorShape : Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
contentItem : Rectangle {
|
||||
color: Style.transparent
|
||||
Text {
|
||||
id: showIcon
|
||||
anchors {
|
||||
left : iconOnRight ? showText.right : parent.left
|
||||
leftMargin : iconOnRight ? margin : 0
|
||||
verticalCenter : parent.verticalCenter
|
||||
}
|
||||
font {
|
||||
pointSize : iconSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
color : textColor
|
||||
text : root.iconText
|
||||
}
|
||||
|
||||
Text {
|
||||
id: showText
|
||||
anchors {
|
||||
verticalCenter : parent.verticalCenter
|
||||
left : iconOnRight ? parent.left : showIcon.right
|
||||
leftMargin : iconOnRight ? 0 : margin
|
||||
}
|
||||
color : textColor
|
||||
font {
|
||||
pointSize : root.fontSize * Style.pt
|
||||
bold: root.textBold
|
||||
underline: root.textUnderline
|
||||
}
|
||||
text : root.text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
147
internal/frontend/qml/ProtonUI/Dialog.qml
Normal file
147
internal/frontend/qml/ProtonUI/Dialog.qml
Normal file
@ -0,0 +1,147 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Dialog with adding new user
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Layouts 1.3
|
||||
import ProtonUI 1.0
|
||||
|
||||
|
||||
StackLayout {
|
||||
id: root
|
||||
property string title : "title"
|
||||
property string subtitle : ""
|
||||
property alias timer : timer
|
||||
property alias warning : warningText
|
||||
property bool isDialogBusy : false
|
||||
property real titleHeight : 2*titleText.anchors.topMargin + titleText.height + (warningText.visible ? warningText.anchors.topMargin + warningText.height : 0)
|
||||
property Item background : Rectangle {
|
||||
parent: root
|
||||
width: root.width
|
||||
height: root.height
|
||||
color : Style.dialog.background
|
||||
visible: root.visible
|
||||
z: -1
|
||||
|
||||
AccessibleText {
|
||||
id: titleText
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
topMargin: Style.dialog.titleSize
|
||||
}
|
||||
font.pointSize : Style.dialog.titleSize * Style.pt
|
||||
color : Style.dialog.text
|
||||
text : root.title
|
||||
}
|
||||
|
||||
AccessibleText {
|
||||
id: subtitleText
|
||||
anchors {
|
||||
top: titleText.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pointSize : Style.dialog.fontSize * Style.pt
|
||||
color : Style.dialog.text
|
||||
text : root.subtitle
|
||||
visible : root.subtitle != ""
|
||||
}
|
||||
|
||||
AccessibleText {
|
||||
id:warningText
|
||||
anchors {
|
||||
top: subtitleText.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font {
|
||||
bold: true
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
text : ""
|
||||
color: Style.main.textBlue
|
||||
visible: false
|
||||
}
|
||||
|
||||
// prevent any action below
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
}
|
||||
|
||||
ClickIconText {
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
topMargin: Style.dialog.titleSize
|
||||
rightMargin: Style.dialog.titleSize
|
||||
}
|
||||
visible : !isDialogBusy
|
||||
iconText : Style.fa.times
|
||||
text : ""
|
||||
onClicked : root.hide()
|
||||
Accessible.description : qsTr("Close dialog %1", "Click to exit modal.").arg(root.title)
|
||||
}
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.Grouping
|
||||
Accessible.name: title
|
||||
Accessible.description: title
|
||||
Accessible.focusable: true
|
||||
|
||||
|
||||
visible : false
|
||||
anchors {
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
top : titleBar.bottom
|
||||
bottom : parent.bottom
|
||||
}
|
||||
currentIndex : 0
|
||||
|
||||
|
||||
signal show()
|
||||
signal hide()
|
||||
|
||||
function incrementCurrentIndex() {
|
||||
root.currentIndex++
|
||||
}
|
||||
|
||||
function decrementCurrentIndex() {
|
||||
root.currentIndex--
|
||||
}
|
||||
|
||||
onShow: {
|
||||
root.visible = true
|
||||
root.forceActiveFocus()
|
||||
}
|
||||
|
||||
onHide: {
|
||||
root.timer.stop()
|
||||
root.currentIndex=0
|
||||
root.visible = false
|
||||
root.timer.stop()
|
||||
gui.winMain.tabbar.focusButton()
|
||||
}
|
||||
|
||||
// QTimer is recommeded solution for creating trheads : http://doc.qt.io/qt-5/qtquick-threading-example.html
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 300 // wait for transistion
|
||||
repeat: false
|
||||
}
|
||||
}
|
||||
464
internal/frontend/qml/ProtonUI/DialogAddUser.qml
Normal file
464
internal/frontend/qml/ProtonUI/DialogAddUser.qml
Normal file
@ -0,0 +1,464 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Dialog with adding new user
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
|
||||
Dialog {
|
||||
id: root
|
||||
|
||||
title : ""
|
||||
|
||||
signal createAccount()
|
||||
|
||||
property alias inputPassword : inputPassword
|
||||
property alias input2FAuth : input2FAuth
|
||||
property alias inputPasswMailbox : inputPasswMailbox
|
||||
//
|
||||
property alias username : inputUsername.text
|
||||
property alias usernameElided : usernameMetrics.elidedText
|
||||
|
||||
isDialogBusy : currentIndex==waitingAuthIndex || currentIndex==addingAccIndex
|
||||
|
||||
property bool isFirstAccount: false
|
||||
|
||||
property color buttonOpaqueMain : "white"
|
||||
|
||||
|
||||
property int origin: 0
|
||||
property int nameAndPasswordIndex : 0
|
||||
property int waitingAuthIndex : 2
|
||||
property int twoFAIndex : 1
|
||||
property int mailboxIndex : 3
|
||||
property int addingAccIndex : 4
|
||||
property int newAccountIndex : 5
|
||||
|
||||
|
||||
signal cancel()
|
||||
signal okay()
|
||||
|
||||
TextMetrics {
|
||||
id: usernameMetrics
|
||||
font: dialogWaitingAuthText.font
|
||||
elideWidth : Style.dialog.widthInput
|
||||
elide : Qt.ElideMiddle
|
||||
text : root.username
|
||||
}
|
||||
|
||||
Column { // 0
|
||||
id: dialogNameAndPassword
|
||||
property int heightInputs : inputUsername.height + buttonRow.height + middleSep.height + inputPassword.height + middleSepPassw.height
|
||||
|
||||
Rectangle {
|
||||
id: topSep
|
||||
color : "transparent"
|
||||
width : Style.main.dummy
|
||||
height : root.height/2 - (dialogNameAndPassword.heightInputs)/2
|
||||
}
|
||||
|
||||
InputField {
|
||||
id: inputUsername
|
||||
iconText : Style.fa.user_circle
|
||||
label : qsTr("Username", "enter username to add account")
|
||||
onAccepted : inputPassword.focusInput = true
|
||||
}
|
||||
|
||||
Rectangle { id: middleSepPassw; color : "transparent"; width : Style.main.dummy; height : Style.dialog.heightSeparator}
|
||||
|
||||
InputField {
|
||||
id: inputPassword
|
||||
label : qsTr("Password", "password entry field")
|
||||
iconText : Style.fa.lock
|
||||
isPassword : true
|
||||
onAccepted : root.okay()
|
||||
}
|
||||
|
||||
Rectangle { id: middleSep; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
|
||||
|
||||
Row {
|
||||
id: buttonRow
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Style.dialog.fontSize
|
||||
ButtonRounded {
|
||||
id:buttonCancel
|
||||
fa_icon : Style.fa.times
|
||||
text : qsTr("Cancel", "dismisses current action")
|
||||
color_main : Style.dialog.text
|
||||
onClicked : root.cancel()
|
||||
}
|
||||
ButtonRounded {
|
||||
id: buttonNext
|
||||
fa_icon : Style.fa.check
|
||||
text : qsTr("Next", "navigate to next page in add account flow")
|
||||
color_main : buttonOpaqueMain
|
||||
color_minor : Style.dialog.textBlue
|
||||
isOpaque : true
|
||||
onClicked : root.okay()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color : "transparent"
|
||||
width : Style.main.dummy
|
||||
height : root.height - (topSep.height + dialogNameAndPassword.heightInputs + Style.main.bottomMargin + signUpForAccount.height)
|
||||
}
|
||||
|
||||
ClickIconText {
|
||||
id: signUpForAccount
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
fontSize : Style.dialog.fontSize
|
||||
iconSize : Style.dialog.fontSize
|
||||
iconText : "+"
|
||||
text : qsTr ("Sign Up for an Account", "takes user to web page where they can create a ProtonMail account")
|
||||
textBold : true
|
||||
textUnderline : true
|
||||
textColor : Style.dialog.text
|
||||
onClicked : root.createAccount()
|
||||
}
|
||||
}
|
||||
|
||||
Column { // 1
|
||||
id: dialog2FA
|
||||
property int heightInputs : buttonRowPassw.height + middleSep2FA.height + input2FAuth.height
|
||||
|
||||
Rectangle {
|
||||
color : "transparent"
|
||||
width : Style.main.dummy
|
||||
height : (root.height - dialog2FA.heightInputs)/2
|
||||
}
|
||||
|
||||
InputField {
|
||||
id: input2FAuth
|
||||
label : qsTr("Two Factor Code", "two factor code entry field")
|
||||
iconText : Style.fa.lock
|
||||
onAccepted : root.okay()
|
||||
}
|
||||
|
||||
Rectangle { id: middleSep2FA; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
|
||||
|
||||
Row {
|
||||
id: buttonRowPassw
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Style.dialog.fontSize
|
||||
ButtonRounded {
|
||||
id: buttonBack
|
||||
fa_icon: Style.fa.times
|
||||
text: qsTr("Back", "navigate back in add account flow")
|
||||
color_main: Style.dialog.text
|
||||
onClicked : root.cancel()
|
||||
}
|
||||
ButtonRounded {
|
||||
id: buttonNextTwo
|
||||
fa_icon: Style.fa.check
|
||||
text: qsTr("Next", "navigate to next page in add account flow")
|
||||
color_main: buttonOpaqueMain
|
||||
color_minor: Style.dialog.textBlue
|
||||
isOpaque: true
|
||||
onClicked : root.okay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column { // 2
|
||||
id: dialogWaitingAuth
|
||||
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height-dialogWaitingAuthText.height) /2 }
|
||||
Text {
|
||||
id: dialogWaitingAuthText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Style.dialog.text
|
||||
font.pointSize: Style.dialog.fontSize * Style.pt
|
||||
text : qsTr("Logging in") +"\n" + root.usernameElided
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
Column { // 3
|
||||
id: dialogMailboxPassword
|
||||
property int heightInputs : buttonRowMailbox.height + inputPasswMailbox.height + middleSepMailbox.height
|
||||
|
||||
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogMailboxPassword.heightInputs)/2}
|
||||
|
||||
InputField {
|
||||
id: inputPasswMailbox
|
||||
label : qsTr("Mailbox password for %1", "mailbox password entry field").arg(root.usernameElided)
|
||||
iconText : Style.fa.lock
|
||||
isPassword : true
|
||||
onAccepted : root.okay()
|
||||
}
|
||||
|
||||
Rectangle { id: middleSepMailbox; color : "transparent"; width : Style.main.dummy; height : 2*Style.dialog.heightSeparator }
|
||||
|
||||
Row {
|
||||
id: buttonRowMailbox
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Style.dialog.fontSize
|
||||
ButtonRounded {
|
||||
id: buttonBackBack
|
||||
fa_icon: Style.fa.times
|
||||
text: qsTr("Back", "navigate back in add account flow")
|
||||
color_main: Style.dialog.text
|
||||
onClicked : root.cancel()
|
||||
}
|
||||
ButtonRounded {
|
||||
id: buttonLogin
|
||||
fa_icon: Style.fa.check
|
||||
text: qsTr("Next", "navigate to next page in add account flow")
|
||||
color_main: buttonOpaqueMain
|
||||
color_minor: Style.dialog.textBlue
|
||||
isOpaque: true
|
||||
onClicked : root.okay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column { // 4
|
||||
id: dialogWaitingAccount
|
||||
|
||||
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogWaitingAccountText.height )/2 }
|
||||
|
||||
Text {
|
||||
id: dialogWaitingAccountText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Style.dialog.text
|
||||
font {
|
||||
bold : true
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
text : qsTr("Adding account, please wait ...", "displayed after user has logged in, before new account is displayed")
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
Column { // 5
|
||||
id: dialogFirstUserAdded
|
||||
|
||||
Rectangle { color : "transparent"; width : Style.main.dummy; height : (root.height - dialogWaitingAccountText.height - okButton.height*2 )/2 }
|
||||
|
||||
Text {
|
||||
id: textFirstUser
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Style.dialog.text
|
||||
font {
|
||||
bold : false
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
width: 2*root.width/3
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
textFormat: Text.RichText
|
||||
text: "<html><style>a { font-weight: bold; text-decoration: none; color: white;}</style>"+
|
||||
qsTr("Now you need to configure your client(s) to use the Bridge. Instructions for configuring your client can be found at", "") +
|
||||
"<br/><a href=\"https://protonmail.com/bridge/clients\">https://protonmail.com/bridge/clients</a>.<html>"
|
||||
wrapMode: Text.Wrap
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: parent.hoveredLink=="" ? Qt.PointingHandCursor : Qt.WaitCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { color : "transparent"; width : Style.main.dummy; height : okButton.height}
|
||||
|
||||
ButtonRounded{
|
||||
id: okButton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color_main: buttonOpaqueMain
|
||||
color_minor: Style.main.textBlue
|
||||
isOpaque: true
|
||||
text: qsTr("Okay", "confirms and dismisses a notification")
|
||||
onClicked: root.hide()
|
||||
}
|
||||
}
|
||||
|
||||
function clear_user() {
|
||||
inputUsername.text = ""
|
||||
inputUsername.rightIcon = ""
|
||||
}
|
||||
|
||||
function clear_passwd() {
|
||||
inputPassword.text = ""
|
||||
inputPassword.rightIcon = ""
|
||||
inputPassword.hidePasswordText()
|
||||
}
|
||||
|
||||
|
||||
function clear_2fa() {
|
||||
input2FAuth.text = ""
|
||||
input2FAuth.rightIcon = ""
|
||||
}
|
||||
|
||||
function clear_passwd_mailbox() {
|
||||
inputPasswMailbox.text = ""
|
||||
inputPasswMailbox.rightIcon = ""
|
||||
inputPasswMailbox.hidePasswordText()
|
||||
}
|
||||
|
||||
onCancel : {
|
||||
root.warning.visible=false
|
||||
if (currentIndex==0) {
|
||||
root.hide()
|
||||
} else {
|
||||
clear_passwd()
|
||||
clear_passwd_mailbox()
|
||||
currentIndex=0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function check_inputs() {
|
||||
var isOK = true
|
||||
switch (currentIndex) {
|
||||
case nameAndPasswordIndex :
|
||||
isOK &= inputUsername.checkNonEmpty()
|
||||
isOK &= inputPassword.checkNonEmpty()
|
||||
break
|
||||
case twoFAIndex :
|
||||
isOK &= input2FAuth.checkNonEmpty()
|
||||
break
|
||||
case mailboxIndex :
|
||||
isOK &= inputPasswMailbox.checkNonEmpty()
|
||||
break
|
||||
}
|
||||
if (isOK) {
|
||||
warning.visible = false
|
||||
warning.text= ""
|
||||
} else {
|
||||
setWarning(qsTr("Field required", "a field that must be filled in to submit form"),0)
|
||||
}
|
||||
return isOK
|
||||
}
|
||||
|
||||
function setWarning(msg, changeIndex) {
|
||||
// show message
|
||||
root.warning.text = msg
|
||||
root.warning.visible = true
|
||||
}
|
||||
|
||||
|
||||
onOkay : {
|
||||
var isOK = check_inputs()
|
||||
if (isOK) {
|
||||
root.origin = root.currentIndex
|
||||
switch (root.currentIndex) {
|
||||
case nameAndPasswordIndex:
|
||||
case twoFAIndex:
|
||||
root.currentIndex = waitingAuthIndex
|
||||
break;
|
||||
case mailboxIndex:
|
||||
root.currentIndex = addingAccIndex
|
||||
}
|
||||
timer.start()
|
||||
}
|
||||
}
|
||||
|
||||
onShow: {
|
||||
root.title = qsTr ("Log in to your ProtonMail account", "displayed on screen when user enters username to begin adding account")
|
||||
root.warning.visible = false
|
||||
inputUsername.forceFocus()
|
||||
root.isFirstAccount = go.isFirstStart && accountsModel.count==0
|
||||
}
|
||||
|
||||
function startAgain() {
|
||||
clear_passwd()
|
||||
clear_2fa()
|
||||
clear_passwd_mailbox()
|
||||
root.currentIndex = nameAndPasswordIndex
|
||||
root.inputPassword.focusInput = true
|
||||
}
|
||||
|
||||
function finishLogin(){
|
||||
root.currentIndex = addingAccIndex
|
||||
var auth = go.addAccount(inputPasswMailbox.text)
|
||||
if (auth<0) {
|
||||
startAgain()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: timer
|
||||
|
||||
onTriggered : {
|
||||
timer.repeat = false
|
||||
switch (root.origin) {
|
||||
case nameAndPasswordIndex:
|
||||
var auth = go.login(inputUsername.text, inputPassword.text)
|
||||
if (auth < 0) {
|
||||
startAgain()
|
||||
break
|
||||
}
|
||||
if (auth == 1) {
|
||||
root.currentIndex = twoFAIndex
|
||||
root.input2FAuth.focusInput = true
|
||||
break
|
||||
}
|
||||
if (auth == 2) {
|
||||
root.currentIndex = mailboxIndex
|
||||
root.inputPasswMailbox.focusInput = true
|
||||
break
|
||||
}
|
||||
root.inputPasswMailbox.text = inputPassword.text
|
||||
root.finishLogin()
|
||||
break;
|
||||
case twoFAIndex:
|
||||
var auth = go.auth2FA(input2FAuth.text)
|
||||
if (auth < 0) {
|
||||
startAgain()
|
||||
break
|
||||
}
|
||||
if (auth == 1) {
|
||||
root.currentIndex = mailboxIndex
|
||||
root.inputPasswMailbox.focusInput = true
|
||||
break
|
||||
}
|
||||
root.inputPasswMailbox.text = inputPassword.text
|
||||
root.finishLogin()
|
||||
break;
|
||||
case mailboxIndex:
|
||||
root.finishLogin()
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onHide: {
|
||||
// because hide slot is conneceted to processFinished it will update
|
||||
// the list evertyime `go` obejcet is finished
|
||||
clear_passwd()
|
||||
clear_passwd_mailbox()
|
||||
clear_2fa()
|
||||
clear_user()
|
||||
go.loadAccounts()
|
||||
if (root.isFirstAccount && accountsModel.count==1) {
|
||||
root.isFirstAccount=false
|
||||
root.currentIndex=5
|
||||
root.show()
|
||||
root.title=qsTr("Success, Account Added!", "shown after successful account addition")
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key == Qt.Key_Enter) {
|
||||
root.okay()
|
||||
}
|
||||
}
|
||||
}
|
||||
148
internal/frontend/qml/ProtonUI/DialogConnectionTroubleshoot.qml
Normal file
148
internal/frontend/qml/ProtonUI/DialogConnectionTroubleshoot.qml
Normal file
@ -0,0 +1,148 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Dialog with Yes/No buttons
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
Dialog {
|
||||
id: root
|
||||
|
||||
title : qsTr(
|
||||
"Common connection problems and solutions",
|
||||
"Title of the network troubleshooting modal"
|
||||
)
|
||||
isDialogBusy: false // can close
|
||||
property var parContent : [
|
||||
[
|
||||
qsTr("Allow alternative routing" , "Paragraph title"),
|
||||
qsTr(
|
||||
"In case Proton sites are blocked, this setting allows Bridge "+
|
||||
"to try alternative network routing to reach Proton, which can "+
|
||||
"be useful for bypassing firewalls or network issues. We recommend "+
|
||||
"keeping this setting on for greater reliability. "+
|
||||
'<a href="https://protonmail.com/blog/anti-censorship-alternative-routing/">Learn more</a>'+
|
||||
" and "+
|
||||
'<a href="showProxy">enable here</a>'+
|
||||
".",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("No internet connection" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Please make sure that your internet connection is working.",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("Internet Service Provider (ISP) problem" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Try connecting to Proton from a different network (or use "+
|
||||
'<a href="https://protonvpn.com/">ProtonVPN</a>'+
|
||||
" or "+
|
||||
'<a href="https://torproject.org/">Tor</a>'+
|
||||
").",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("Government block" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Your country may be blocking access to Proton. Try using "+
|
||||
'<a href="https://protonvpn.com/">ProtonVPN</a>'+
|
||||
" (or any other VPN) or "+
|
||||
'<a href="https://torproject.org/">Tor</a>'+
|
||||
".",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("Antivirus interference" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Temporarily disable or remove your antivirus software.",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("Proxy/Firewall interference" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Disable any proxies or firewalls, or contact your network administrator.",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("Still can’t find a solution" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Contact us directly through our "+
|
||||
'<a href="https://protonmail.com/support-form">support form</a>'+
|
||||
", email (support@protonmail.com), or "+
|
||||
'<a href="https://twitter.com/ProtonMail">Twitter</a>'+
|
||||
".",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
[
|
||||
qsTr("Proton is down" , "Paragraph title"),
|
||||
qsTr(
|
||||
"Check "+
|
||||
'<a href="https://protonstatus.com/">Proton Status</a>'+
|
||||
" for our system status.",
|
||||
"Paragraph content"
|
||||
),
|
||||
],
|
||||
|
||||
]
|
||||
|
||||
Item {
|
||||
AccessibleText {
|
||||
anchors.centerIn: parent
|
||||
color: Style.old.pm_white
|
||||
linkColor: color
|
||||
width: parent.width - 50 * Style.px
|
||||
wrapMode: Text.WordWrap
|
||||
font.pointSize: Style.main.fontSize*Style.pt
|
||||
onLinkActivated: {
|
||||
if (link=="showProxy") {
|
||||
dialogGlobal.state= "toggleAllowProxy"
|
||||
dialogGlobal.show()
|
||||
} else {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
}
|
||||
text: {
|
||||
var content=""
|
||||
for (var i=0; i<root.parContent.length; i++) {
|
||||
var par = root.parContent[i]
|
||||
content += "<p>"
|
||||
content += "<b>"+par[0]+":</b> "
|
||||
content += par[1]
|
||||
content += "</p>\n"
|
||||
}
|
||||
return content
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
250
internal/frontend/qml/ProtonUI/DialogUpdate.qml
Normal file
250
internal/frontend/qml/ProtonUI/DialogUpdate.qml
Normal file
@ -0,0 +1,250 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// default options to make button accessible
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import ProtonUI 1.0
|
||||
|
||||
|
||||
Dialog {
|
||||
id: root
|
||||
|
||||
title: "Bridge update "+go.newversion
|
||||
|
||||
property alias introductionText : introduction.text
|
||||
property bool hasError : false
|
||||
|
||||
signal cancel()
|
||||
signal okay()
|
||||
|
||||
|
||||
isDialogBusy: currentIndex==1
|
||||
|
||||
Rectangle { // 0: Release notes and confirm
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: Style.transparent
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 5*Style.dialog.spacing
|
||||
|
||||
AccessibleText {
|
||||
id:introduction
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: Style.dialog.text
|
||||
linkColor: Style.dialog.textBlue
|
||||
font {
|
||||
pointSize: 0.8 * Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
width: 2*root.width/3
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
// customize message per application
|
||||
text: ' <a href="%1">Release notes</a><br> New version %2<br> <br><br> <a href="%3">%3</a>'
|
||||
|
||||
onLinkActivated : {
|
||||
console.log("clicked link:", link)
|
||||
if (link == "releaseNotes"){
|
||||
root.hide()
|
||||
winMain.dialogVersionInfo.show()
|
||||
} else {
|
||||
root.hide()
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: introduction.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Style.dialog.spacing
|
||||
|
||||
ButtonRounded {
|
||||
fa_icon: Style.fa.times
|
||||
text: (go.goos=="linux" ? qsTr("Okay") : qsTr("Cancel"))
|
||||
color_main: Style.dialog.text
|
||||
onClicked: root.cancel()
|
||||
}
|
||||
|
||||
ButtonRounded {
|
||||
fa_icon: Style.fa.check
|
||||
text: qsTr("Update")
|
||||
visible: go.goos!="linux"
|
||||
color_main: Style.dialog.text
|
||||
color_minor: Style.main.textBlue
|
||||
isOpaque: true
|
||||
onClicked: root.okay()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { // 0: Check / download / unpack / prepare
|
||||
id: updateStatus
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: Style.transparent
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.dialog.spacing
|
||||
|
||||
AccessibleText {
|
||||
color: Style.dialog.text
|
||||
font {
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
bold: false
|
||||
}
|
||||
width: 2*root.width/3
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: {
|
||||
switch (go.progressDescription) {
|
||||
case 1: return qsTr("Checking the current version.")
|
||||
case 2: return qsTr("Downloading the update files.")
|
||||
case 3: return qsTr("Verifying the update files.")
|
||||
case 4: return qsTr("Unpacking the update files.")
|
||||
case 5: return qsTr("Starting the update.")
|
||||
case 6: return qsTr("Quitting the application.")
|
||||
default: return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: progressbar
|
||||
implicitWidth : 2*updateStatus.width/3
|
||||
implicitHeight : Style.exporting.rowHeight
|
||||
visible: go.progress!=0 // hack hide animation when clearing out progress bar
|
||||
value: go.progress
|
||||
property int current: go.total * go.progress
|
||||
property bool isFinished: finishedPartBar.width == progressbar.width
|
||||
background: Rectangle {
|
||||
radius : Style.exporting.boxRadius
|
||||
color : Style.exporting.progressBackground
|
||||
}
|
||||
contentItem: Item {
|
||||
Rectangle {
|
||||
id: finishedPartBar
|
||||
width : parent.width * progressbar.visualPosition
|
||||
height : parent.height
|
||||
radius : Style.exporting.boxRadius
|
||||
gradient : Gradient {
|
||||
GradientStop { position: 0.00; color: Qt.lighter(Style.main.textBlue,1.1) }
|
||||
GradientStop { position: 0.66; color: Style.main.textBlue }
|
||||
GradientStop { position: 1.00; color: Qt.darker(Style.main.textBlue,1.1) }
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration:300; easing.type: Easing.InOutQuad }
|
||||
}
|
||||
}
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: ""
|
||||
color: Style.main.background
|
||||
font {
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { // 1: Something went wrong / All ok, closing bridge
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: Style.transparent
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: 5*Style.dialog.spacing
|
||||
|
||||
AccessibleText {
|
||||
color: Style.dialog.text
|
||||
linkColor: Style.dialog.textBlue
|
||||
font {
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
}
|
||||
width: 2*root.width/3
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: !root.hasError ? qsTr('Application will quit now to finish the update.', "message after successful update") :
|
||||
qsTr('<b>The update procedure was not successful!</b><br>Please follow the download link and update manually. <br><br><a href="%1">%1</a>').arg(go.downloadLink)
|
||||
|
||||
onLinkActivated : {
|
||||
console.log("clicked link:", link)
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
ButtonRounded{
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: root.hasError
|
||||
text: qsTr("Close")
|
||||
onClicked: root.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clear() {
|
||||
root.hasError = false
|
||||
go.progress = 0.0
|
||||
go.progressDescription = 0
|
||||
}
|
||||
|
||||
function finished(hasError) {
|
||||
root.hasError = hasError
|
||||
root.incrementCurrentIndex()
|
||||
}
|
||||
|
||||
onShow: {
|
||||
root.clear()
|
||||
}
|
||||
|
||||
onHide: {
|
||||
root.clear()
|
||||
}
|
||||
|
||||
onOkay: {
|
||||
switch (root.currentIndex) {
|
||||
case 0:
|
||||
go.startUpdate()
|
||||
}
|
||||
root.incrementCurrentIndex()
|
||||
}
|
||||
|
||||
onCancel: {
|
||||
root.hide()
|
||||
}
|
||||
}
|
||||
78
internal/frontend/qml/ProtonUI/FileAndFolderSelect.qml
Normal file
78
internal/frontend/qml/ProtonUI/FileAndFolderSelect.qml
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// one line input text field with label
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Dialogs 1.0
|
||||
import ProtonUI 1.0
|
||||
|
||||
Row {
|
||||
id: root
|
||||
spacing: Style.dialog.spacing
|
||||
|
||||
property string title : "title"
|
||||
|
||||
property alias path: inputPath.text
|
||||
property alias inputPath: inputPath
|
||||
property alias dialogVisible: pathDialog.visible
|
||||
|
||||
InputBox {
|
||||
id: inputPath
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
}
|
||||
spacing: Style.dialog.spacing
|
||||
field {
|
||||
height: browseButton.height
|
||||
width: root.width - root.spacing - browseButton.width
|
||||
}
|
||||
|
||||
label: title
|
||||
Component.onCompleted: sanitizePath(pathDialog.shortcuts.home)
|
||||
}
|
||||
|
||||
ButtonRounded {
|
||||
id: browseButton
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: Style.dialog.heightInput
|
||||
color_main: Style.main.textBlue
|
||||
fa_icon: Style.fa.folder_open
|
||||
text: qsTr("Browse", "click to look through directory for a file or folder")
|
||||
onClicked: pathDialog.visible = true
|
||||
}
|
||||
|
||||
FileDialog {
|
||||
id: pathDialog
|
||||
title: root.title + ":"
|
||||
folder: shortcuts.home
|
||||
onAccepted: sanitizePath(pathDialog.fileUrl.toString())
|
||||
selectFolder: true
|
||||
}
|
||||
|
||||
function sanitizePath(path) {
|
||||
var pattern = "file://"
|
||||
if (go.goos=="windows") pattern+="/"
|
||||
inputPath.text = path.replace(pattern, "")
|
||||
}
|
||||
|
||||
function checkNonEmpty() {
|
||||
return inputPath.text != ""
|
||||
}
|
||||
}
|
||||
101
internal/frontend/qml/ProtonUI/InfoToolTip.qml
Normal file
101
internal/frontend/qml/ProtonUI/InfoToolTip.qml
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// on hover information
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import ProtonUI 1.0
|
||||
|
||||
Text { // info icon
|
||||
id:root
|
||||
property alias info : tip.text
|
||||
font {
|
||||
family: Style.fontawesome.name
|
||||
pointSize : Style.dialog.iconSize * Style.pt
|
||||
}
|
||||
text: Style.fa.info_circle
|
||||
color: Style.main.textDisabled
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onEntered : tip.visible=true
|
||||
onExited : tip.visible=false
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
id: tip
|
||||
width: Style.bubble.width
|
||||
x: - 0.2*tip.width
|
||||
y: - tip.height
|
||||
|
||||
topPadding : Style.main.fontSize/2
|
||||
bottomPadding : Style.main.fontSize/2
|
||||
leftPadding : Style.bubble.widthPane + Style.dialog.spacing
|
||||
rightPadding: Style.dialog.spacing
|
||||
delay: 800
|
||||
|
||||
background : Rectangle {
|
||||
id: bck
|
||||
color: Style.bubble.paneBackground
|
||||
radius : Style.bubble.radius
|
||||
|
||||
|
||||
Text {
|
||||
id: icon
|
||||
color: Style.bubble.background
|
||||
text: Style.fa.info_circle
|
||||
font {
|
||||
family : Style.fontawesome.name
|
||||
pointSize : Style.dialog.iconSize * Style.pt
|
||||
}
|
||||
anchors {
|
||||
verticalCenter : bck.verticalCenter
|
||||
left : bck.left
|
||||
leftMargin : (Style.bubble.widthPane - icon.width) / 2
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle { // right edge
|
||||
anchors {
|
||||
fill : bck
|
||||
leftMargin : Style.bubble.widthPane
|
||||
}
|
||||
radius: parent.radius
|
||||
color: Style.bubble.background
|
||||
}
|
||||
|
||||
Rectangle { // center background
|
||||
anchors {
|
||||
fill : parent
|
||||
leftMargin : Style.bubble.widthPane
|
||||
rightMargin : Style.bubble.widthPane
|
||||
}
|
||||
color: Style.bubble.background
|
||||
}
|
||||
}
|
||||
|
||||
contentItem : Text {
|
||||
text: tip.text
|
||||
color: Style.bubble.text
|
||||
wrapMode: Text.Wrap
|
||||
font.pointSize: Style.main.fontSize * Style.pt
|
||||
}
|
||||
}
|
||||
}
|
||||
233
internal/frontend/qml/ProtonUI/InformationBar.qml
Normal file
233
internal/frontend/qml/ProtonUI/InformationBar.qml
Normal file
@ -0,0 +1,233 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Important information under title bar
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
property var iTry: 0
|
||||
property var secLeft: 0
|
||||
property var second: 1000 // convert millisecond to second
|
||||
property var checkInterval: [ 5, 10, 30, 60, 120, 300, 600 ] // seconds
|
||||
property bool isVisible: true
|
||||
property var fontSize : 1.2 * Style.main.fontSize
|
||||
color : "black"
|
||||
state: "upToDate"
|
||||
|
||||
Timer {
|
||||
id: retryInternet
|
||||
interval: second
|
||||
triggeredOnStart: false
|
||||
repeat: true
|
||||
onTriggered : {
|
||||
secLeft--
|
||||
if (secLeft <= 0) {
|
||||
retryInternet.stop()
|
||||
go.checkInternet()
|
||||
if (iTry < checkInterval.length-1) {
|
||||
iTry++
|
||||
}
|
||||
secLeft=checkInterval[iTry]
|
||||
retryInternet.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.centerIn: root
|
||||
visible: root.isVisible
|
||||
spacing: Style.main.leftMarginButton
|
||||
|
||||
AccessibleText {
|
||||
id: message
|
||||
font.pointSize: root.fontSize * Style.pt
|
||||
}
|
||||
|
||||
ClickIconText {
|
||||
anchors.verticalCenter : message.verticalCenter
|
||||
text : "("+go.newversion+" " + qsTr("release notes", "display the release notes from the new version")+")"
|
||||
visible : root.state=="oldVersion" && ( go.changelog!="" || go.bugfixes!="")
|
||||
iconText : ""
|
||||
onClicked : {
|
||||
dialogVersionInfo.show()
|
||||
}
|
||||
fontSize : root.fontSize
|
||||
}
|
||||
|
||||
ClickIconText {
|
||||
anchors.verticalCenter : message.verticalCenter
|
||||
text : root.state=="oldVersion" || root.state == "forceUpdate" ?
|
||||
qsTr("Update", "click to update to a new version when one is available") :
|
||||
qsTr("Retry now", "click to try to connect to the internet when the app is disconnected from the internet")
|
||||
visible : root.state!="internetCheck"
|
||||
iconText : ""
|
||||
onClicked : {
|
||||
if (root.state=="oldVersion" || root.state=="forceUpdate" ) {
|
||||
winMain.dialogUpdate.show()
|
||||
} else {
|
||||
go.checkInternet()
|
||||
}
|
||||
}
|
||||
fontSize : root.fontSize
|
||||
textUnderline: true
|
||||
}
|
||||
Text {
|
||||
anchors.baseline : message.baseline
|
||||
color: Style.main.text
|
||||
font {
|
||||
pointSize : root.fontSize * Style.pt
|
||||
bold : true
|
||||
}
|
||||
visible: root.state=="oldVersion" || root.state=="noInternet"
|
||||
text : "|"
|
||||
}
|
||||
ClickIconText {
|
||||
anchors.verticalCenter : message.verticalCenter
|
||||
iconText : ""
|
||||
text : root.state == "noInternet" ?
|
||||
qsTr("Troubleshoot", "Show modal screen with additional tips for troubleshooting connection issues") :
|
||||
qsTr("Remind me later", "Do not install new version and dismiss a notification")
|
||||
visible : root.state=="oldVersion" || root.state=="noInternet"
|
||||
onClicked : {
|
||||
if (root.state == "oldVersion") {
|
||||
root.state = "upToDate"
|
||||
}
|
||||
if (root.state == "noInternet") {
|
||||
dialogConnectionTroubleshoot.show()
|
||||
}
|
||||
}
|
||||
fontSize : root.fontSize
|
||||
textUnderline: true
|
||||
}
|
||||
}
|
||||
|
||||
onStateChanged : {
|
||||
switch (root.state) {
|
||||
case "forceUpdate" :
|
||||
gui.warningFlags |= Style.errorInfoBar
|
||||
break;
|
||||
case "upToDate" :
|
||||
gui.warningFlags &= ~Style.warnInfoBar
|
||||
iTry = 0
|
||||
secLeft=checkInterval[iTry]
|
||||
break;
|
||||
case "noInternet" :
|
||||
gui.warningFlags |= Style.warnInfoBar
|
||||
retryInternet.start()
|
||||
secLeft=checkInterval[iTry]
|
||||
break;
|
||||
default :
|
||||
gui.warningFlags |= Style.warnInfoBar
|
||||
}
|
||||
|
||||
if (root.state!="noInternet") {
|
||||
retryInternet.stop()
|
||||
}
|
||||
}
|
||||
|
||||
function timeToRetry() {
|
||||
if (secLeft==1){
|
||||
return qsTr("a second", "time to wait till internet connection is retried")
|
||||
} else if (secLeft<60){
|
||||
return secLeft + " " + qsTr("seconds", "time to wait till internet connection is retried")
|
||||
} else {
|
||||
var leading = ""+secLeft%60
|
||||
if (leading.length < 2) {
|
||||
leading = "0" + leading
|
||||
}
|
||||
return Math.floor(secLeft/60) + ":" + leading
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "internetCheck"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
height: 2* Style.main.fontSize
|
||||
isVisible: true
|
||||
color: Style.main.textOrange
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
color: Style.main.background
|
||||
text: qsTr("Checking connection. Please wait...", "displayed after user retries internet connection")
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "noInternet"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
height: 2* Style.main.fontSize
|
||||
isVisible: true
|
||||
color: Style.main.textRed
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
color: Style.main.line
|
||||
text: qsTr("Cannot contact server. Retrying in ", "displayed when the app is disconnected from the internet or server has problems")+timeToRetry()+"."
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "oldVersion"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
height: 2* Style.main.fontSize
|
||||
isVisible: true
|
||||
color: Style.main.textBlue
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
color: Style.main.background
|
||||
text: qsTr("An update is available.", "displayed in a notification when an app update is available")
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "forceUpdate"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
height: 2* Style.main.fontSize
|
||||
isVisible: true
|
||||
color: Style.main.textRed
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
color: Style.main.line
|
||||
text: qsTr("%1 is outdated.", "displayed in a notification when app is outdated").arg(go.programTitle)
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "upToDate"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
height: 0
|
||||
isVisible: false
|
||||
color: Style.main.textBlue
|
||||
}
|
||||
PropertyChanges {
|
||||
target: message
|
||||
color: Style.main.background
|
||||
text: ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
78
internal/frontend/qml/ProtonUI/InputBox.qml
Normal file
78
internal/frontend/qml/ProtonUI/InputBox.qml
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// one line input text field with label
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import ProtonUI 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Column {
|
||||
id: root
|
||||
property alias label: textlabel.text
|
||||
property alias placeholderText: inputField.placeholderText
|
||||
property alias echoMode: inputField.echoMode
|
||||
property alias text: inputField.text
|
||||
property alias field: inputField
|
||||
|
||||
signal accepted()
|
||||
|
||||
spacing: Style.dialog.heightSeparator
|
||||
|
||||
Text {
|
||||
id: textlabel
|
||||
font {
|
||||
pointSize: Style.dialog.fontSize * Style.pt
|
||||
bold: true
|
||||
}
|
||||
color: Style.dialog.text
|
||||
}
|
||||
|
||||
|
||||
TextField {
|
||||
id: inputField
|
||||
width: Style.dialog.widthInput
|
||||
height: Style.dialog.heightButton
|
||||
selectByMouse : true
|
||||
selectionColor : Style.main.textBlue
|
||||
padding : Style.dialog.radiusButton
|
||||
color : Style.dialog.text
|
||||
font {
|
||||
pointSize : Style.dialog.fontSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
background: Rectangle {
|
||||
color : Style.dialog.background
|
||||
radius: Style.dialog.radiusButton
|
||||
border {
|
||||
color : Style.dialog.line
|
||||
width : Style.dialog.borderInput
|
||||
}
|
||||
layer.enabled: true
|
||||
layer.effect: FastBlur {
|
||||
anchors.fill: parent
|
||||
radius: 8 * Style.px
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target : inputField
|
||||
onAccepted : root.accepted()
|
||||
}
|
||||
}
|
||||
172
internal/frontend/qml/ProtonUI/InputField.qml
Normal file
172
internal/frontend/qml/ProtonUI/InputField.qml
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// one line input text field with label
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
Column {
|
||||
id: root
|
||||
property alias focusInput : inputField.focus
|
||||
property alias label : textlabel.text
|
||||
property alias iconText : iconInput.text
|
||||
property alias placeholderText : inputField.placeholderText
|
||||
property alias text : inputField.text
|
||||
property bool isPassword : false
|
||||
property string rightIcon : ""
|
||||
|
||||
signal accepted()
|
||||
signal editingFinished()
|
||||
|
||||
spacing: Style.dialog.heightSeparator
|
||||
anchors.horizontalCenter : parent.horizontalCenter
|
||||
|
||||
AccessibleText {
|
||||
id: textlabel
|
||||
anchors.left : parent.left
|
||||
font {
|
||||
pointSize : Style.dialog.fontSize * Style.pt
|
||||
bold : true
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color : Style.dialog.text
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: inputWrap
|
||||
anchors.horizontalCenter : parent.horizontalCenter
|
||||
width : Style.dialog.widthInput
|
||||
height : Style.dialog.heightInput
|
||||
color : "transparent"
|
||||
|
||||
Text {
|
||||
id: iconInput
|
||||
anchors {
|
||||
top : parent.top
|
||||
left : parent.left
|
||||
}
|
||||
color : Style.dialog.text
|
||||
font {
|
||||
pointSize : Style.dialog.iconSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
text: "o"
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: inputField
|
||||
anchors {
|
||||
fill: inputWrap
|
||||
leftMargin : Style.dialog.iconSize+Style.dialog.fontSize
|
||||
bottomMargin : inputWrap.height - Style.dialog.iconSize
|
||||
}
|
||||
verticalAlignment : TextInput.AlignTop
|
||||
horizontalAlignment : TextInput.AlignLeft
|
||||
selectByMouse : true
|
||||
color : Style.dialog.text
|
||||
selectionColor : Style.main.textBlue
|
||||
font {
|
||||
pointSize : Style.dialog.fontSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
padding: 0
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
color : "transparent"
|
||||
}
|
||||
Component.onCompleted : {
|
||||
if (isPassword) {
|
||||
echoMode = TextInput.Password
|
||||
} else {
|
||||
echoMode = TextInput.Normal
|
||||
}
|
||||
}
|
||||
|
||||
Accessible.name: textlabel.text
|
||||
Accessible.description: textlabel.text
|
||||
}
|
||||
|
||||
Text {
|
||||
id: iconRight
|
||||
anchors {
|
||||
top : parent.top
|
||||
right : parent.right
|
||||
}
|
||||
color : Style.dialog.text
|
||||
font {
|
||||
pointSize : Style.dialog.iconSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
text: ( !isPassword ? "" : (
|
||||
inputField.echoMode == TextInput.Password ? Style.fa.eye : Style.fa.eye_slash
|
||||
)) + " " + rightIcon
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (isPassword) {
|
||||
if (inputField.echoMode == TextInput.Password) inputField.echoMode = TextInput.Normal
|
||||
else inputField.echoMode = TextInput.Password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
bottom : parent.bottom
|
||||
}
|
||||
height: Math.max(Style.main.border,1)
|
||||
color: Style.dialog.text
|
||||
}
|
||||
}
|
||||
|
||||
function checkNonEmpty() {
|
||||
if (inputField.text == "") {
|
||||
rightIcon = Style.fa.exclamation_triangle
|
||||
root.placeholderText = ""
|
||||
inputField.focus = true
|
||||
return false
|
||||
} else {
|
||||
rightIcon = Style.fa.check_circle
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function hidePasswordText() {
|
||||
if (root.isPassword) inputField.echoMode = TextInput.Password
|
||||
}
|
||||
|
||||
function forceFocus() {
|
||||
inputField.forceActiveFocus()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: inputField
|
||||
onAccepted: root.accepted()
|
||||
onEditingFinished: root.editingFinished()
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key == Qt.Key_Enter) {
|
||||
root.accepted()
|
||||
}
|
||||
}
|
||||
}
|
||||
79
internal/frontend/qml/ProtonUI/InstanceExistsWindow.qml
Normal file
79
internal/frontend/qml/ProtonUI/InstanceExistsWindow.qml
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// This is main window
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Window 2.2
|
||||
import ProtonUI 1.0
|
||||
|
||||
|
||||
// Main Window
|
||||
Window {
|
||||
id:winMain
|
||||
|
||||
// main window appeareance
|
||||
width : Style.main.width
|
||||
height : Style.main.height
|
||||
flags : Qt.Window | Qt.Dialog
|
||||
title: qsTr("ProtonMail Bridge", "app title")
|
||||
color : Style.main.background
|
||||
visible : true
|
||||
|
||||
Text {
|
||||
id: title
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
top: parent.top
|
||||
topMargin: Style.main.topMargin
|
||||
}
|
||||
font{
|
||||
pointSize: Style.dialog.titleSize * Style.pt
|
||||
}
|
||||
color: Style.main.text
|
||||
text:
|
||||
"<span style='font-family: " + Style.fontawesome.name + "'>" + Style.fa.exclamation_triangle + "</span> " +
|
||||
qsTr ("Warning: Instance exists", "displayed when a version of the app is opened while another is already running")
|
||||
}
|
||||
|
||||
Text {
|
||||
id: message
|
||||
anchors.centerIn : parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pointSize: Style.dialog.fontSize * Style.pt
|
||||
color: Style.main.text
|
||||
width: 2*parent.width/3
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("An instance of the ProtonMail Bridge is already running.", "displayed when a version of the app is opened while another is already running") + " " +
|
||||
qsTr("Please close the existing ProtonMail Bridge process before starting a new one.", "displayed when a version of the app is opened while another is already running")+ " " +
|
||||
qsTr("This program will close now.", "displayed when a version of the app is opened while another is already running")
|
||||
}
|
||||
|
||||
ButtonRounded {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: Style.main.bottomMargin
|
||||
}
|
||||
text: qsTr("Okay", "confirms and dismisses a notification")
|
||||
color_main: Style.dialog.text
|
||||
color_minor: Style.main.textBlue
|
||||
isOpaque: true
|
||||
onClicked: Qt.quit()
|
||||
}
|
||||
}
|
||||
|
||||
150
internal/frontend/qml/ProtonUI/LogoHeader.qml
Normal file
150
internal/frontend/qml/ProtonUI/LogoHeader.qml
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Header of window with logo and buttons
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
import QtQuick.Window 2.2
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
// dimensions
|
||||
property Window parentWin
|
||||
property string title: "ProtonMail Bridge"
|
||||
property bool hasIcon : true
|
||||
anchors.top : parent.top
|
||||
anchors.right : parent.right
|
||||
width : Style.main.width
|
||||
height : Style.title.height
|
||||
// style
|
||||
color : Style.title.background
|
||||
|
||||
signal hideClicked()
|
||||
|
||||
// Drag to move : https://stackoverflow.com/a/18927884
|
||||
MouseArea {
|
||||
property variant clickPos: "1,1"
|
||||
anchors.fill: parent
|
||||
onPressed: {
|
||||
clickPos = Qt.point(mouse.x,mouse.y)
|
||||
}
|
||||
onPositionChanged: {
|
||||
var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
|
||||
parentWin.x += delta.x;
|
||||
parentWin.y += delta.y;
|
||||
}
|
||||
}
|
||||
|
||||
// logo
|
||||
Image {
|
||||
id: imgLogo
|
||||
height : Style.title.imgHeight
|
||||
fillMode : Image.PreserveAspectFit
|
||||
visible: root.hasIcon
|
||||
anchors {
|
||||
left : root.left
|
||||
leftMargin : Style.title.leftMargin
|
||||
verticalCenter : root.verticalCenter
|
||||
}
|
||||
//source : "qrc://logo.svg"
|
||||
source : "logo.svg"
|
||||
smooth : true
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: titleMetrics
|
||||
elideWidth: 2*root.width/3
|
||||
elide: Qt.ElideMiddle
|
||||
font: titleText.font
|
||||
text: root.title
|
||||
}
|
||||
|
||||
// Title
|
||||
Text {
|
||||
id: titleText
|
||||
anchors {
|
||||
left : hasIcon ? imgLogo.right : parent.left
|
||||
leftMargin : hasIcon ? Style.title.leftMargin : Style.main.leftMargin
|
||||
verticalCenter : root.verticalCenter
|
||||
}
|
||||
text : titleMetrics.elidedText
|
||||
color : Style.title.text
|
||||
font.pointSize : Style.title.fontSize * Style.pt
|
||||
}
|
||||
|
||||
// Underline Button
|
||||
Rectangle {
|
||||
id: buttonUndrLine
|
||||
anchors {
|
||||
verticalCenter : root.verticalCenter
|
||||
right : buttonCross.left
|
||||
rightMargin : 2*Style.title.fontSize
|
||||
}
|
||||
width : Style.title.fontSize
|
||||
height : Style.title.fontSize
|
||||
color : "transparent"
|
||||
Canvas {
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
var val = Style.title.fontSize
|
||||
var ctx = getContext("2d")
|
||||
ctx.strokeStyle = 'white'
|
||||
ctx.strokeWidth = 4
|
||||
ctx.moveTo(0 , val-1)
|
||||
ctx.lineTo(val, val-1)
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.hideClicked()
|
||||
}
|
||||
}
|
||||
|
||||
// Cross Button
|
||||
Rectangle {
|
||||
id: buttonCross
|
||||
anchors {
|
||||
verticalCenter : root.verticalCenter
|
||||
right : root.right
|
||||
rightMargin : Style.main.rightMargin
|
||||
}
|
||||
width : Style.title.fontSize
|
||||
height : Style.title.fontSize
|
||||
color : "transparent"
|
||||
Canvas {
|
||||
anchors.fill: parent
|
||||
onPaint: {
|
||||
var val = Style.title.fontSize
|
||||
var ctx = getContext("2d")
|
||||
ctx.strokeStyle = 'white'
|
||||
ctx.strokeWidth = 4
|
||||
ctx.moveTo(0,0)
|
||||
ctx.lineTo(val,val)
|
||||
ctx.moveTo(val,0)
|
||||
ctx.lineTo(0,val)
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.hideClicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
81
internal/frontend/qml/ProtonUI/PopupMessage.qml
Normal file
81
internal/frontend/qml/ProtonUI/PopupMessage.qml
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Popup message
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Controls 2.2
|
||||
import ProtonUI 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: Style.transparent
|
||||
property alias text: message.text
|
||||
visible: false
|
||||
|
||||
MouseArea { // prevent action below
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: backgroundInp
|
||||
anchors.centerIn : root
|
||||
color : Style.errorDialog.background
|
||||
radius : Style.errorDialog.radius
|
||||
width : parent.width/3.
|
||||
height : contentInp.height
|
||||
|
||||
Column {
|
||||
id: contentInp
|
||||
anchors.horizontalCenter: backgroundInp.horizontalCenter
|
||||
spacing: Style.dialog.heightSeparator
|
||||
topPadding: Style.dialog.heightSeparator
|
||||
bottomPadding: Style.dialog.heightSeparator
|
||||
|
||||
AccessibleText {
|
||||
id: message
|
||||
font {
|
||||
pointSize : Style.errorDialog.fontSize * Style.pt
|
||||
bold : true
|
||||
}
|
||||
color: Style.errorDialog.text
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
width : backgroundInp.width - 2*Style.main.rightMargin
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
ButtonRounded {
|
||||
text : qsTr("Okay", "todo")
|
||||
isOpaque : true
|
||||
color_main : Style.dialog.background
|
||||
color_minor : Style.dialog.textBlue
|
||||
onClicked : root.hide()
|
||||
anchors.horizontalCenter : parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function show(text) {
|
||||
root.text = text
|
||||
root.visible = true
|
||||
}
|
||||
|
||||
function hide() {
|
||||
root.state = "Okay"
|
||||
root.visible=false
|
||||
}
|
||||
}
|
||||
16
internal/frontend/qml/ProtonUI/ProgressBar.qml
Normal file
16
internal/frontend/qml/ProtonUI/ProgressBar.qml
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
1089
internal/frontend/qml/ProtonUI/Style.qml
Normal file
1089
internal/frontend/qml/ProtonUI/Style.qml
Normal file
File diff suppressed because it is too large
Load Diff
69
internal/frontend/qml/ProtonUI/TLSCertPinIssueBar.qml
Normal file
69
internal/frontend/qml/ProtonUI/TLSCertPinIssueBar.qml
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Important information under title bar
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.1
|
||||
import ProtonUI 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
height: 0
|
||||
visible: state != "ok"
|
||||
state: "ok"
|
||||
color: "black"
|
||||
property var fontSize : 1.0 * Style.main.fontSize
|
||||
|
||||
Row {
|
||||
anchors.centerIn: root
|
||||
visible: root.visible
|
||||
spacing: Style.main.leftMarginButton
|
||||
|
||||
AccessibleText {
|
||||
id: message
|
||||
font.pointSize: root.fontSize * Style.pt
|
||||
|
||||
text: qsTr("Connection security error: Your network connection to Proton services may be insecure.", "message in bar showed when TLS Pinning fails")
|
||||
}
|
||||
|
||||
ClickIconText {
|
||||
anchors.verticalCenter : message.verticalCenter
|
||||
iconText : ""
|
||||
text : qsTr("Learn more", "This button opens TLS Pinning issue modal with more explanation")
|
||||
visible : root.visible
|
||||
onClicked : {
|
||||
winMain.dialogTlsCert.show()
|
||||
}
|
||||
fontSize : root.fontSize
|
||||
textUnderline: true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "notOK"
|
||||
PropertyChanges {
|
||||
target: root
|
||||
height: 2* Style.main.fontSize
|
||||
color: Style.main.textRed
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
103
internal/frontend/qml/ProtonUI/TabButton.qml
Normal file
103
internal/frontend/qml/ProtonUI/TabButton.qml
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Button with text and icon for tabbar
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
import QtQuick.Controls 2.1
|
||||
|
||||
AccessibleButton {
|
||||
id: root
|
||||
property alias iconText : icon.text
|
||||
property alias title : titleText.text
|
||||
property color textColor : {
|
||||
if (root.state=="deactivated") {
|
||||
return Qt.lighter(Style.tabbar.textInactive, root.hovered || root.activeFocus ? 1.25 : 1.0)
|
||||
}
|
||||
if (root.state=="activated") {
|
||||
return Style.tabbar.text
|
||||
}
|
||||
}
|
||||
|
||||
text: root.title
|
||||
Accessible.description: root.title + " tab"
|
||||
|
||||
width : titleMetrics.width // Style.tabbar.widthButton
|
||||
height : Style.tabbar.heightButton
|
||||
padding: 0
|
||||
|
||||
background: Rectangle {
|
||||
color : Style.transparent
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
acceptedButtons: Qt.NoButton
|
||||
}
|
||||
}
|
||||
|
||||
contentItem : Rectangle {
|
||||
color: "transparent"
|
||||
scale : root.pressed ? 0.96 : 1.00
|
||||
|
||||
Text {
|
||||
id: icon
|
||||
// dimenstions
|
||||
anchors {
|
||||
top : parent.top
|
||||
horizontalCenter : parent.horizontalCenter
|
||||
}
|
||||
// style
|
||||
color : root.textColor
|
||||
font {
|
||||
family : Style.fontawesome.name
|
||||
pointSize : Style.tabbar.iconSize * Style.pt
|
||||
}
|
||||
}
|
||||
|
||||
TextMetrics {
|
||||
id: titleMetrics
|
||||
text : root.title
|
||||
font.pointSize : titleText.font.pointSize
|
||||
}
|
||||
|
||||
Text {
|
||||
id: titleText
|
||||
// dimenstions
|
||||
anchors {
|
||||
bottom : parent.bottom
|
||||
horizontalCenter : parent.horizontalCenter
|
||||
}
|
||||
// style
|
||||
color : root.textColor
|
||||
font {
|
||||
pointSize : Style.tabbar.fontSize * Style.pt
|
||||
bold : root.state=="activated"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "activated"
|
||||
},
|
||||
State {
|
||||
name: "deactivated"
|
||||
}
|
||||
]
|
||||
}
|
||||
107
internal/frontend/qml/ProtonUI/TabLabels.qml
Normal file
107
internal/frontend/qml/ProtonUI/TabLabels.qml
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// Tab labels
|
||||
|
||||
import QtQuick 2.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
// attributes
|
||||
property alias model : tablist.model
|
||||
property alias currentIndex : tablist.currentIndex
|
||||
property int spacing : Style.tabbar.widthButton + Style.tabbar.spacingButton
|
||||
currentIndex: 0
|
||||
|
||||
// appereance
|
||||
height : Style.tabbar.height
|
||||
color : Style.tabbar.background
|
||||
|
||||
// content
|
||||
ListView {
|
||||
id: tablist
|
||||
// dimensions
|
||||
anchors {
|
||||
fill: root
|
||||
leftMargin : Style.tabbar.leftMargin
|
||||
rightMargin : Style.main.rightMargin
|
||||
bottomMargin : Style.tabbar.bottomMargin
|
||||
}
|
||||
spacing: Style.tabbar.spacingButton
|
||||
interactive : false
|
||||
// style
|
||||
orientation: Qt.Horizontal
|
||||
delegate: TabButton {
|
||||
anchors.bottom : parent.bottom
|
||||
title : modelData.title
|
||||
iconText : modelData.iconText
|
||||
state : index == tablist.currentIndex ? "activated" : "deactivated"
|
||||
onClicked : {
|
||||
tablist.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Quit button
|
||||
TabButton {
|
||||
id: buttonQuit
|
||||
title : qsTr("Close Bridge", "quits the application")
|
||||
iconText : Style.fa.power_off
|
||||
state : "deactivated"
|
||||
visible : Style.tabbar.rightButton=="quit"
|
||||
anchors {
|
||||
right : root.right
|
||||
bottom : root.bottom
|
||||
rightMargin : Style.main.rightMargin
|
||||
bottomMargin : Style.tabbar.bottomMargin
|
||||
}
|
||||
|
||||
Accessible.description: buttonQuit.title
|
||||
|
||||
onClicked : {
|
||||
dialogGlobal.state = "quit"
|
||||
dialogGlobal.show()
|
||||
}
|
||||
}
|
||||
|
||||
// Add account
|
||||
TabButton {
|
||||
id: buttonAddAccount
|
||||
title : qsTr("Add account", "start the authentication to add account")
|
||||
iconText : Style.fa.plus_circle
|
||||
state : "deactivated"
|
||||
visible : Style.tabbar.rightButton=="add account"
|
||||
anchors {
|
||||
right : root.right
|
||||
bottom : root.bottom
|
||||
rightMargin : Style.main.rightMargin
|
||||
bottomMargin : Style.tabbar.bottomMargin
|
||||
}
|
||||
|
||||
Accessible.description: buttonAddAccount.title
|
||||
|
||||
onClicked : dialogAddUser.show()
|
||||
}
|
||||
|
||||
function focusButton() {
|
||||
tablist.currentItem.forceActiveFocus()
|
||||
tablist.currentItem.Accessible.focusedChanged(true)
|
||||
}
|
||||
}
|
||||
|
||||
45
internal/frontend/qml/ProtonUI/TextLabel.qml
Normal file
45
internal/frontend/qml/ProtonUI/TextLabel.qml
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2020 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.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
AccessibleText{
|
||||
id: root
|
||||
property bool hasCopyButton : false
|
||||
font.pointSize: Style.main.fontSize * Style.pt
|
||||
state: "label"
|
||||
|
||||
states : [
|
||||
State {
|
||||
name: "label"
|
||||
PropertyChanges {
|
||||
target : root
|
||||
font.bold : false
|
||||
color : Style.main.textDisabled
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "heading"
|
||||
PropertyChanges {
|
||||
target : root
|
||||
font.bold : true
|
||||
color : Style.main.textDisabled
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
85
internal/frontend/qml/ProtonUI/TextValue.qml
Normal file
85
internal/frontend/qml/ProtonUI/TextValue.qml
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2020 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.8
|
||||
import ProtonUI 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
property string text: "undef"
|
||||
width: copyIcon.width + valueText.width
|
||||
height: Math.max(copyIcon.height, valueText.contentHeight)
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: copyIcon
|
||||
width: Style.info.leftMarginIcon*2 + Style.info.iconSize
|
||||
height : Style.info.iconSize
|
||||
color: "transparent"
|
||||
anchors {
|
||||
top: root.top
|
||||
left: root.left
|
||||
}
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
font {
|
||||
pointSize : Style.info.iconSize * Style.pt
|
||||
family : Style.fontawesome.name
|
||||
}
|
||||
color : Style.main.textInactive
|
||||
text: Style.fa.copy
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked : {
|
||||
valueText.select(0, valueText.length)
|
||||
valueText.copy()
|
||||
valueText.deselect()
|
||||
}
|
||||
onPressed: copyIcon.scale = 0.90
|
||||
onReleased: copyIcon.scale = 1
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Copy %1 to clipboard", "Click to copy the value to system clipboard.").arg(root.text)
|
||||
Accessible.description: Accessible.name
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: valueText
|
||||
width: Style.info.widthValue
|
||||
height: Style.main.fontSize
|
||||
anchors {
|
||||
top: root.top
|
||||
left: copyIcon.right
|
||||
}
|
||||
font {
|
||||
pointSize: Style.main.fontSize * Style.pt
|
||||
}
|
||||
color: Style.main.text
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
selectByKeyboard: true
|
||||
wrapMode: TextEdit.Wrap
|
||||
text: root.text
|
||||
selectionColor: Style.dialog.textBlue
|
||||
|
||||
Accessible.role: Accessible.StaticText
|
||||
Accessible.name: root.text
|
||||
Accessible.description: Accessible.name
|
||||
}
|
||||
}
|
||||
348
internal/frontend/qml/ProtonUI/WindowTitleBar.qml
Normal file
348
internal/frontend/qml/ProtonUI/WindowTitleBar.qml
Normal file
@ -0,0 +1,348 @@
|
||||
// Copyright (c) 2020 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/>.
|
||||
|
||||
// simulating window title bar with different color
|
||||
|
||||
import QtQuick 2.8
|
||||
import QtQuick.Window 2.2
|
||||
import ProtonUI 1.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
height: root.isDarwin ? Style.titleMacOS.height : Style.title.height
|
||||
color: "transparent"
|
||||
property bool isDarwin : (go.goos == "darwin")
|
||||
property QtObject window
|
||||
anchors {
|
||||
left : parent.left
|
||||
right : parent.right
|
||||
top : parent.top
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
property point diff: "0,0"
|
||||
anchors {
|
||||
top: root.top
|
||||
bottom: root.bottom
|
||||
left: root.left
|
||||
right: root.isDarwin ? root.right : iconRowWin.left
|
||||
}
|
||||
onPressed: {
|
||||
diff = Qt.point(window.x, window.y)
|
||||
var mousePos = mapToGlobal(mouse.x, mouse.y)
|
||||
diff.x -= mousePos.x
|
||||
diff.y -= mousePos.y
|
||||
}
|
||||
onPositionChanged: {
|
||||
var currPos = mapToGlobal(mouse.x, mouse.y)
|
||||
window.x = currPos.x + diff.x
|
||||
window.y = currPos.y + diff.y
|
||||
}
|
||||
}
|
||||
|
||||
// top background
|
||||
Rectangle {
|
||||
id: upperBackground
|
||||
anchors.fill: root
|
||||
color: (isDarwin? Style.titleMacOS.background : Style.title.background )
|
||||
radius: (isDarwin? Style.titleMacOS.radius : 0)
|
||||
border {
|
||||
width: Style.main.border
|
||||
color: Style.title.background
|
||||
}
|
||||
}
|
||||
// bottom background
|
||||
Rectangle {
|
||||
id: lowerBorder
|
||||
anchors {
|
||||
top: root.verticalCenter
|
||||
left: root.left
|
||||
right: root.right
|
||||
bottom: root.bottom
|
||||
}
|
||||
color: Style.title.background
|
||||
Rectangle {
|
||||
id: lowerBackground
|
||||
anchors{
|
||||
fill : parent
|
||||
leftMargin : Style.main.border
|
||||
rightMargin : Style.main.border
|
||||
}
|
||||
color: upperBackground.color
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Title
|
||||
TextMetrics {
|
||||
id: titleMetrics
|
||||
text : window.title
|
||||
font : isDarwin ? titleMac.font : titleWin.font
|
||||
elide: Qt.ElideMiddle
|
||||
elideWidth : window.width/2
|
||||
}
|
||||
Text {
|
||||
id: titleWin
|
||||
visible: !isDarwin
|
||||
anchors {
|
||||
baseline : logo.bottom
|
||||
left : logo.right
|
||||
leftMargin : Style.title.leftMargin/1.5
|
||||
}
|
||||
color : window.active ? Style.title.text : Style.main.textDisabled
|
||||
text : titleMetrics.elidedText
|
||||
font.pointSize : Style.main.fontSize * Style.pt
|
||||
}
|
||||
Text {
|
||||
id: titleMac
|
||||
visible: isDarwin
|
||||
anchors {
|
||||
verticalCenter : parent.verticalCenter
|
||||
left : parent.left
|
||||
leftMargin : (parent.width-width)/2
|
||||
}
|
||||
color : window.active ? Style.title.text : Style.main.textDisabled
|
||||
text : titleMetrics.elidedText
|
||||
font.pointSize : Style.main.fontSize * Style.pt
|
||||
}
|
||||
|
||||
|
||||
// MACOS
|
||||
MouseArea {
|
||||
anchors.fill: iconRowMac
|
||||
property string beforeHover
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
beforeHover=iconRed.state
|
||||
//iconYellow.state="hover"
|
||||
iconRed.state="hover"
|
||||
}
|
||||
onExited: {
|
||||
//iconYellow.state=beforeHover
|
||||
iconRed.state=beforeHover
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: window
|
||||
onActiveChanged : {
|
||||
if (window.active) {
|
||||
//iconYellow.state="normal"
|
||||
iconRed.state="normal"
|
||||
} else {
|
||||
//iconYellow.state="disabled"
|
||||
iconRed.state="disabled"
|
||||
}
|
||||
}
|
||||
}
|
||||
Row {
|
||||
id: iconRowMac
|
||||
visible : isDarwin
|
||||
spacing : Style.titleMacOS.leftMargin
|
||||
anchors {
|
||||
left : parent.left
|
||||
verticalCenter : parent.verticalCenter
|
||||
leftMargin : Style.title.leftMargin
|
||||
}
|
||||
Image {
|
||||
id: iconRed
|
||||
width : Style.titleMacOS.imgHeight
|
||||
height : Style.titleMacOS.imgHeight
|
||||
fillMode : Image.PreserveAspectFit
|
||||
smooth : true
|
||||
state : "normal"
|
||||
states: [
|
||||
State { name: "normal" ; PropertyChanges { target: iconRed ; source: "images/macos_red.png" } },
|
||||
State { name: "hover" ; PropertyChanges { target: iconRed ; source: "images/macos_red_hl.png" } },
|
||||
State { name: "pressed" ; PropertyChanges { target: iconRed ; source: "images/macos_red_dark.png" } },
|
||||
State { name: "disabled" ; PropertyChanges { target: iconRed ; source: "images/macos_gray.png" } }
|
||||
]
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property string beforePressed : "normal"
|
||||
onClicked : {
|
||||
window.close()
|
||||
}
|
||||
onPressed: {
|
||||
beforePressed = parent.state
|
||||
parent.state="pressed"
|
||||
}
|
||||
onReleased: {
|
||||
parent.state=beforePressed
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Close", "Close the window button")
|
||||
Accessible.description: Accessible.name
|
||||
Accessible.ignored: !parent.visible
|
||||
Accessible.onPressAction: {
|
||||
window.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
Image {
|
||||
id: iconYellow
|
||||
width : Style.titleMacOS.imgHeight
|
||||
height : Style.titleMacOS.imgHeight
|
||||
fillMode : Image.PreserveAspectFit
|
||||
smooth : true
|
||||
state : "disabled"
|
||||
states: [
|
||||
State { name: "normal" ; PropertyChanges { target: iconYellow ; source: "images/macos_yellow.png" } },
|
||||
State { name: "hover" ; PropertyChanges { target: iconYellow ; source: "images/macos_yellow_hl.png" } },
|
||||
State { name: "pressed" ; PropertyChanges { target: iconYellow ; source: "images/macos_yellow_dark.png" } },
|
||||
State { name: "disabled" ; PropertyChanges { target: iconYellow ; source: "images/macos_gray.png" } }
|
||||
]
|
||||
/*
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
property string beforePressed : "normal"
|
||||
onClicked : {
|
||||
window.visibility = Window.Minimized
|
||||
}
|
||||
onPressed: {
|
||||
beforePressed = parent.state
|
||||
parent.state="pressed"
|
||||
}
|
||||
onReleased: {
|
||||
parent.state=beforePressed
|
||||
}
|
||||
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Minimize", "Minimize the window button")
|
||||
Accessible.description: Accessible.name
|
||||
Accessible.ignored: !parent.visible
|
||||
Accessible.onPressAction: {
|
||||
window.visibility = Window.Minimized
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
Image {
|
||||
id: iconGreen
|
||||
width : Style.titleMacOS.imgHeight
|
||||
height : Style.titleMacOS.imgHeight
|
||||
fillMode : Image.PreserveAspectFit
|
||||
smooth : true
|
||||
source : "images/macos_gray.png"
|
||||
Component.onCompleted : {
|
||||
visible = false // (window.flags&Qt.Dialog) != Qt.Dialog
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Windows
|
||||
Image {
|
||||
id: logo
|
||||
visible: !isDarwin
|
||||
anchors {
|
||||
left : parent.left
|
||||
verticalCenter : parent.verticalCenter
|
||||
leftMargin : Style.title.leftMargin
|
||||
}
|
||||
height : Style.title.fontSize-2*Style.px
|
||||
fillMode : Image.PreserveAspectFit
|
||||
mipmap : true
|
||||
source : "images/pm_logo.png"
|
||||
}
|
||||
|
||||
Row {
|
||||
id: iconRowWin
|
||||
visible: !isDarwin
|
||||
anchors {
|
||||
right : parent.right
|
||||
verticalCenter : root.verticalCenter
|
||||
}
|
||||
Rectangle {
|
||||
height : root.height
|
||||
width : 1.5*height
|
||||
color: Style.transparent
|
||||
Image {
|
||||
id: iconDash
|
||||
anchors.centerIn: parent
|
||||
height : iconTimes.height*0.90
|
||||
fillMode : Image.PreserveAspectFit
|
||||
mipmap : true
|
||||
source : "images/win10_Dash.png"
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill : parent
|
||||
hoverEnabled : true
|
||||
onClicked : {
|
||||
window.visibility = Window.Minimized
|
||||
}
|
||||
onPressed: {
|
||||
parent.scale=0.92
|
||||
}
|
||||
onReleased: {
|
||||
parent.scale=1
|
||||
}
|
||||
onEntered: {
|
||||
parent.color= Qt.lighter(Style.title.background,1.2)
|
||||
}
|
||||
onExited: {
|
||||
parent.color=Style.transparent
|
||||
}
|
||||
|
||||
Accessible.role : Accessible.Button
|
||||
Accessible.name : qsTr("Minimize", "Minimize the window button")
|
||||
Accessible.description : Accessible.name
|
||||
Accessible.ignored : !parent.visible
|
||||
Accessible.onPressAction : {
|
||||
window.visibility = Window.Minimized
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
height : root.height
|
||||
width : 1.5*height
|
||||
color : Style.transparent
|
||||
Image {
|
||||
id: iconTimes
|
||||
anchors.centerIn : parent
|
||||
mipmap : true
|
||||
height : parent.height/1.5
|
||||
fillMode : Image.PreserveAspectFit
|
||||
source : "images/win10_Times.png"
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill : parent
|
||||
hoverEnabled : true
|
||||
onClicked : window.close()
|
||||
onPressed : {
|
||||
iconTimes.scale=0.92
|
||||
}
|
||||
onReleased: {
|
||||
parent.scale=1
|
||||
}
|
||||
onEntered: {
|
||||
parent.color=Style.main.textRed
|
||||
}
|
||||
onExited: {
|
||||
parent.color=Style.transparent
|
||||
}
|
||||
|
||||
Accessible.role : Accessible.Button
|
||||
Accessible.name : qsTr("Close", "Close the window button")
|
||||
Accessible.description : Accessible.name
|
||||
Accessible.ignored : !parent.visible
|
||||
Accessible.onPressAction : {
|
||||
window.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
internal/frontend/qml/ProtonUI/qmldir
Normal file
31
internal/frontend/qml/ProtonUI/qmldir
Normal file
@ -0,0 +1,31 @@
|
||||
module ProtonUI
|
||||
singleton Style 1.0 Style.qml
|
||||
AccessibleButton 1.0 AccessibleButton.qml
|
||||
AccessibleText 1.0 AccessibleText.qml
|
||||
AccessibleSelectableText 1.0 AccessibleSelectableText.qml
|
||||
AccountView 1.0 AccountView.qml
|
||||
AddAccountBar 1.0 AddAccountBar.qml
|
||||
BubbleNote 1.0 BubbleNote.qml
|
||||
BugReportWindow 1.0 BugReportWindow.qml
|
||||
ButtonIconText 1.0 ButtonIconText.qml
|
||||
ButtonRounded 1.0 ButtonRounded.qml
|
||||
CheckBoxLabel 1.0 CheckBoxLabel.qml
|
||||
ClickIconText 1.0 ClickIconText.qml
|
||||
Dialog 1.0 Dialog.qml
|
||||
DialogAddUser 1.0 DialogAddUser.qml
|
||||
DialogUpdate 1.0 DialogUpdate.qml
|
||||
DialogConnectionTroubleshoot 1.0 DialogConnectionTroubleshoot.qml
|
||||
FileAndFolderSelect 1.0 FileAndFolderSelect.qml
|
||||
InfoToolTip 1.0 InfoToolTip.qml
|
||||
InformationBar 1.0 InformationBar.qml
|
||||
InputBox 1.0 InputBox.qml
|
||||
InputField 1.0 InputField.qml
|
||||
InstanceExistsWindow 1.0 InstanceExistsWindow.qml
|
||||
LogoHeader 1.0 LogoHeader.qml
|
||||
PopupMessage 1.0 PopupMessage.qml
|
||||
TabButton 1.0 TabButton.qml
|
||||
TabLabels 1.0 TabLabels.qml
|
||||
TextLabel 1.0 TextLabel.qml
|
||||
TextValue 1.0 TextValue.qml
|
||||
TLSCertPinIssueBar 1.0 TLSCertPinIssueBar.qml
|
||||
WindowTitleBar 1.0 WindowTitleBar.qml
|
||||
Reference in New Issue
Block a user