From 2b1daa60bb4d8e1364cc015614c3f43e9fcbfddb Mon Sep 17 00:00:00 2001 From: Alexander Bilyak Date: Fri, 28 May 2021 12:12:57 +0200 Subject: [PATCH] GODT-1167 GODT-1179 make run-qml-preview --- Makefile | 4 +- internal/frontend/qml/Bridge.qml | 64 ++++ internal/frontend/qml/Bridge_test.qml | 56 ++++ internal/frontend/qml/MainWindow.qml | 63 ++-- internal/frontend/qml/Proton/Button.qml | 128 ++++++++ internal/frontend/qml/Proton/ColorScheme.qml | 88 ++++++ internal/frontend/qml/Proton/Style.qml | 302 +++++++++++++++++++ internal/frontend/qml/Proton/qmldir | 6 + internal/frontend/qml/qtquickcontrols2.conf | 2 + 9 files changed, 674 insertions(+), 39 deletions(-) create mode 100644 internal/frontend/qml/Bridge.qml create mode 100644 internal/frontend/qml/Bridge_test.qml create mode 100644 internal/frontend/qml/Proton/Button.qml create mode 100644 internal/frontend/qml/Proton/ColorScheme.qml create mode 100644 internal/frontend/qml/Proton/Style.qml create mode 100644 internal/frontend/qml/Proton/qmldir create mode 100644 internal/frontend/qml/qtquickcontrols2.conf diff --git a/Makefile b/Makefile index da99e87c..cd958edb 100644 --- a/Makefile +++ b/Makefile @@ -291,7 +291,9 @@ run-debug: PROTONMAIL_ENV=dev dlv debug --build-flags "${BUILD_FLAGS}" cmd/${TARGET_CMD}/main.go -- ${RUN_FLAGS} run-qml-preview: - $(MAKE) -C internal/frontend/qt -f Makefile.local qmlpreview + find internal/frontend/qml/ -iname '*qmlc' | xargs rm -f + cd internal/frontend/qml/ && qmlscene -verbose -I . -f Bridge_test.qml + clean-frontend-qt: # TODO: $(MAKE) -C internal/frontend/qt -f Makefile.local clean diff --git a/internal/frontend/qml/Bridge.qml b/internal/frontend/qml/Bridge.qml new file mode 100644 index 00000000..382774aa --- /dev/null +++ b/internal/frontend/qml/Bridge.qml @@ -0,0 +1,64 @@ +// Copyright (c) 2021 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +import QtQuick 2.13 +import QtQuick.Window 2.13 +import Qt.labs.platform 1.0 + +QtObject { + // default property list children: [] + + property var _mainWindow: MainWindow { + id: mainWindow + title: "ProtonMail Bridge" + visible: false + } + + property var _trayMenu: Window { + id: trayMenu + title: "window 2" + visible: false + flags: Qt.Dialog + + width: 448 + } + + property var _trayIcon: SystemTrayIcon { + id: trayIcon + visible: true + iconSource: "./icons/rectangle-systray.png" + onActivated: { + switch (reason) { + case SystemTrayIcon.Unknown: + break; + case SystemTrayIcon.Context: + break + case SystemTrayIcon.DoubleClick: + break + case SystemTrayIcon.Trigger: + trayMenu.x = (Screen.desktopAvailableWidth - trayMenu.width) / 2 + trayMenu.visible = !trayMenu.visible + break; + case SystemTrayIcon.MiddleClick: + mainWindow.visible = !mainWindow.visible + break; + default: + break; + } + } + } +} diff --git a/internal/frontend/qml/Bridge_test.qml b/internal/frontend/qml/Bridge_test.qml new file mode 100644 index 00000000..b772401a --- /dev/null +++ b/internal/frontend/qml/Bridge_test.qml @@ -0,0 +1,56 @@ +// Copyright (c) 2021 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +import QtQuick 2.13 +import QtQuick.Window 2.13 +import QtQuick.Controls 2.13 + +Window { + id: testroot + width : 250 + height : 600 + flags : Qt.Window | Qt.Dialog | Qt.FramelessWindowHint + visible : true + title : "GUI test Window" + color : "#10101010" + + Column { + anchors.horizontalCenter: parent.horizontalCenter + spacing : 5 + Button { + text: "Show window" + onClicked: { + bridge._mainWindow.visible = true + } + } + Button { + text: "Hide window" + onClicked: { + bridge._mainWindow.visible = false + } + } + } + + Component.onCompleted : { + testroot.x= 10 + testroot.y= 100 + bridge._mainWindow.visible = true + } + + + Bridge {id:bridge} +} diff --git a/internal/frontend/qml/MainWindow.qml b/internal/frontend/qml/MainWindow.qml index f7e3faa6..c72ca68e 100644 --- a/internal/frontend/qml/MainWindow.qml +++ b/internal/frontend/qml/MainWindow.qml @@ -16,48 +16,35 @@ // along with ProtonMail Bridge. If not, see . import QtQuick 2.13 -import QtQuick.Window 2.15 -import Qt.labs.platform 1.0 +import QtQuick.Window 2.13 +import QtQuick.Layouts 1.12 +import QtQuick.Controls 2.12 -QtObject { +import Proton 4.0 - property var _mainWindow: Window { - id: mainWindow - title: "window 1" - visible: false - } +Window { + //currentStyle: Proton.Style.prominentStyle - property var _trayMenu: Window { - id: trayMenu - title: "window 2" - visible: false - flags: Qt.Dialog + //Button { + // + //} - width: 448 - } - - property var _trayIcon: SystemTrayIcon { - id: trayIcon visible: true - iconSource: "./icons/rectangle-systray.png" - onActivated: { - switch (reason) { - case SystemTrayIcon.Unknown: - break; - case SystemTrayIcon.Context: - break - case SystemTrayIcon.DoubleClick: - break - case SystemTrayIcon.Trigger: - trayMenu.x = (Screen.desktopAvailableWidth - trayMenu.width) / 2 - trayMenu.visible = !trayMenu.visible - break; - case SystemTrayIcon.MiddleClick: - mainWindow.visible = !mainWindow.visible - break; - default: - break; + color: ProtonStyle.currentStyle.background_norm + //StackLayout { + // SignIn { + // + // } + //} + + Button { + id: testButton1 + text: "Test button" + } + + Button { + anchors.top: testButton1.bottom + secondary: true + text: "Test button" } } - } -} diff --git a/internal/frontend/qml/Proton/Button.qml b/internal/frontend/qml/Proton/Button.qml new file mode 100644 index 00000000..43edbab0 --- /dev/null +++ b/internal/frontend/qml/Proton/Button.qml @@ -0,0 +1,128 @@ +// Copyright (c) 2021 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Controls.impl 2.12 +import QtQuick.Templates 2.12 as T +import "." + +T.Button { + property var colorScheme: parent.colorScheme ? parent.colorScheme : Style.currentStyle + + property alias secondary: control.flat + readonly property bool primary: !secondary + readonly property bool isIcon: control.text === "" + + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + + padding: 8 + horizontalPadding: 16 + spacing: 10 + + icon.width: 12 + icon.height: 12 + icon.color: control.checked || control.highlighted ? control.palette.brightText : + control.flat && !control.down ? (control.visualFocus ? control.palette.highlight : control.palette.windowText) : control.palette.buttonText + + contentItem: IconLabel { + spacing: control.spacing + mirrored: control.mirrored + display: control.display + + icon: control.icon + text: control.text + font: control.font + color: { + if (!secondary) { + // Primary colors + return "#FFFFFF" + } else { + // Secondary colors + return colorScheme.text_norm + } + } + } + + background: Rectangle { + implicitWidth: 72 + implicitHeight: 36 + radius: 4 + visible: !control.flat || control.down || control.checked || control.highlighted + color: { + if (!isIcon) { + if (!secondary) { + // Primary colors + + if (control.down) { + return colorScheme.interaction_norm_active + } + + if (control.enabled && (control.highlighted || control.hovered || control.checked)) { + return colorScheme.interaction_norm_hover + } + + return colorScheme.interaction_norm + } else { + // Secondary colors + + if (control.down) { + return colorScheme.interaction_default_active + } + + if (control.enabled && (control.highlighted || control.hovered || control.checked)) { + return colorScheme.interaction_default_hover + } + + return colorScheme.interaction_default + } + } else { + if (!secondary) { + // Primary icon colors + + if (control.down) { + return colorScheme.interaction_default_active + } + + if (control.enabled && (control.highlighted || control.hovered || control.checked)) { + return colorScheme.interaction_default_hover + } + + return colorScheme.interaction_default + } else { + // Secondary icon colors + + if (control.down) { + return colorScheme.interaction_default_active + } + + if (control.enabled && (control.highlighted || control.hovered || control.checked)) { + return colorScheme.interaction_default_hover + } + + return colorScheme.interaction_default + } + } + } + opacity: control.enabled ? 1.0 : 0.5 + } +} diff --git a/internal/frontend/qml/Proton/ColorScheme.qml b/internal/frontend/qml/Proton/ColorScheme.qml new file mode 100644 index 00000000..3cf677fb --- /dev/null +++ b/internal/frontend/qml/Proton/ColorScheme.qml @@ -0,0 +1,88 @@ +// Copyright (c) 2021 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +import QtQml 2.13 + +// https://wiki.qt.io/Qml_Styling +// http://imaginativethinking.ca/make-qml-component-singleton/ + +QtObject { + // Primary + property color primay_norm + + // Interaction-norm + property color interaction_norm + property color interaction_norm_hover + property color interaction_norm_active + + // Text + property color text_norm + property color text_weak + property color text_hint + property color text_disabled + property color text_invert + + // Field + property color field_norm + property color field_hover + property color field_disabled + + // Border + property color border_norm + property color border_weak + + // Background + property color background_norm + property color background_weak + property color background_strong + property color background_avatar + + // Interaction-weak + property color interaction_weak + property color interaction_weak_hover + property color interaction_weak_active + + // Interaction-default + property color interaction_default + property color interaction_default_hover + property color interaction_default_active + + // Scrollbar + property color scrollbar_norm + property color scrollbar_hover + + // Signal + property color signal_danger + property color signal_danger_hover + property color signal_danger_active + property color signal_warning + property color signal_warning_hover + property color signal_warning_active + property color signal_success + property color signal_success_hover + property color signal_success_active + property color signal_info + property color signal_info_hover + property color signal_info_active + + // Shadows + property color shadow_norm + property color shadow_lifted + + // Backdrop + property color backdrop_norm +} diff --git a/internal/frontend/qml/Proton/Style.qml b/internal/frontend/qml/Proton/Style.qml new file mode 100644 index 00000000..22840556 --- /dev/null +++ b/internal/frontend/qml/Proton/Style.qml @@ -0,0 +1,302 @@ +// Copyright (c) 2021 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ProtonMail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with ProtonMail Bridge. If not, see . + +pragma Singleton +import QtQml 2.13 + +import "./" + +// https://wiki.qt.io/Qml_Styling +// http://imaginativethinking.ca/make-qml-component-singleton/ + +QtObject { + + // TODO: Once we will use Qt >=5.15 this should be refactored with inline components as follows: + // https://doc.qt.io/qt-5/qtqml-documents-definetypes.html#inline-components + + //component ColorScheme: QtObject { + // property color primay_norm + // ... + //} + + // and instead of "var" later on "ColorScheme" should be used + + property var _lightStyle: ColorScheme { + id: lightStyle + + // Primary + primay_norm: "#657EE4" + + // Interaction-norm + interaction_norm: "#657EE4" + interaction_norm_hover: "#5064B6" + interaction_norm_active: "#3C4B88" + + // Text + text_norm: "#262A33" + text_weak: "#696F7D" + text_hint: "#A4A9B5" + text_disabled: "#BABEC7" + text_invert: "#FFFFFF" + + // Field + field_norm: "#BABEC7" + field_hover: "#A4A9B5" + field_disabled: "#D0D3DA" + + // Border + border_norm: "#D0D3DA" + border_weak: "#E7E9EC" + + // Background + background_norm: "#FFFFFF" + background_weak: "#F3F4F6" + background_strong: "#E7E9EC" + background_avatar: "#A4A9B5" + + // Interaction-weak + interaction_weak: "#D0D3DA" + interaction_weak_hover: "#BABEC7" + interaction_weak_active: "#A4A9B5" + + // Interaction-default + interaction_default: "#00000000" + interaction_default_hover: "#33BABEC7" + interaction_default_active: "#4DBABEC7" + + // Scrollbar + scrollbar_norm: "#D0D3DA" + scrollbar_hover: "#BABEC7" + + // Signal + signal_danger: "#D42F34" + signal_danger_hover: "#C7262B" + signal_danger_active: "#BA1E23" + signal_warning: "#F5830A" + signal_warning_hover: "#F5740A" + signal_warning_active: "#F5640A" + signal_success: "#1B8561" + signal_success_hover: "#147857" + signal_success_active: "#0F6B4C" + signal_info: "#1578CF" + signal_info_hover: "#0E6DC2" + signal_info_active: "#0764B5" + + // Shadows + shadow_norm: "#FFFFFF" + shadow_lifted: "#FFFFFF" + + // Backdrop + backdrop_norm: "#7A262A33" + } + + property var _prominentStyle: ColorScheme { + id: prominentStyle + + // Primary + primay_norm: "#657EE4" + + // Interaction-norm + interaction_norm: "#657EE4" + interaction_norm_hover: "#7D92E8" + interaction_norm_active: "#98A9EE" + + // Text + text_norm: "#FFFFFF" + text_weak: "#949BB9" + text_hint: "#565F84" + text_disabled: "#444E72" + text_invert: "#1C223D" + + // Field + field_norm: "#565F84" + field_hover: "#949BB9" + field_disabled: "#353E60" + + // Border + border_norm: "#353E60" + border_weak: "#2D3657" + + // Background + background_norm: "#1C223D" + background_weak: "#272F4F" + background_strong: "#2D3657" + background_avatar: "#444E72" + + // Interaction-weak + interaction_weak: "#353E60" + interaction_weak_hover: "#444E72" + interaction_weak_active: "#565F84" + + // Interaction-default + interaction_default: "#00000000" + interaction_default_hover: "#4D444E72" + interaction_default_active: "#66444E72" + + // Scrollbar + scrollbar_norm: "#353E60" + scrollbar_hover: "#444E72" + + // Signal + signal_danger: "#ED4C51" + signal_danger_hover: "#F7595E" + signal_danger_active: "#FF666B" + signal_warning: "#F5930A" + signal_warning_hover: "#F5A716" + signal_warning_active: "#F5B922" + signal_success: "#349172" + signal_success_hover: "#339C79" + signal_success_active: "#31A67F" + signal_info: "#2C89DB" + signal_info_hover: "#3491E3" + signal_info_active: "#3D99EB" + + // Shadows + shadow_norm: "#1C223D" + shadow_lifted: "#1C223D" + + // Backdrop + backdrop_norm: "#52000000" + } + + property var _darkStyle: ColorScheme { + id: darkStyle + + // Primary + primay_norm: "#657EE4" + + // Interaction-norm + interaction_norm: "#657EE4" + interaction_norm_hover: "#7D92E8" + interaction_norm_active: "#98A9EE" + + // Text + text_norm: "#FFFFFF" + text_weak: "#A4A9B5" + text_hint: "#696F7D" + text_disabled: "#575D6B" + text_invert: "#262A33" + + // Field + field_norm: "#575D6B" + field_hover: "#696F7D" + field_disabled: "#464B58" + + // Border + border_norm: "#464B58" + border_weak: "#363A46" + + // Background + background_norm: "#262A33" + background_weak: "#2E323C" + background_strong: "#363A46" + background_avatar: "#575D6B" + + // Interaction-weak + interaction_weak: "#464B58" + interaction_weak_hover: "#575D6B" + interaction_weak_active: "#696F7D" + + // Interaction-default + interaction_default: "#00000000" + interaction_default_hover: "#33575D6B" + interaction_default_active: "#4D575D6B" + + // Scrollbar + scrollbar_norm: "#464B58" + scrollbar_hover: "#575D6B" + + // Signal + signal_danger: "#ED4C51" + signal_danger_hover: "#F7595E" + signal_danger_active: "#FF666B" + signal_warning: "#F5930A" + signal_warning_hover: "#F5A716" + signal_warning_active: "#F5B922" + signal_success: "#349172" + signal_success_hover: "#339C79" + signal_success_active: "#31A67F" + signal_info: "#2C89DB" + signal_info_hover: "#3491E3" + signal_info_active: "#3D99EB" + + // Shadows + shadow_norm: "#262A33" + shadow_lifted: "#262A33" + + // Backdrop + backdrop_norm: "#52000000" + } + + // TODO: if default style should be loaded from somewhere - it should be loaded here + property var currentStyle: lightStyle + + property var _timer: Timer { + interval: 1000 + repeat: true + running: true + onTriggered: { + switch (currentStyle) { + case lightStyle: + console.debug("Dark Style") + currentStyle = darkStyle + return + case darkStyle: + console.debug("Prominent Style") + currentStyle = prominentStyle + return + case prominentStyle: + console.debug("Light Style") + currentStyle = lightStyle + return + } + } + } + + + + property string font: { + // TODO: add OS to backend + return "Ubuntu" + + //switch (backend.OS) { + // case "Windows": + // return "Segoe UI" + // case "OSX": + // return "SF Pro Display" + // case "Linux": + // return "Ubuntu" + //} + } + + property int heading_font_size: 28 + property int heading_line_height: 36 + + property int title_font_size: 20 + property int title_line_height: 24 + + property int lead_font_size: 18 + property int lead_line_height: 26 + + property int body_font_size: 14 + property int body_line_height: 20 + property real body_letter_spacing: 0.2 + + property int caption_font_size: 12 + property int caption_line_height: 16 + property real caption_letter_spacing: 0.4 + } diff --git a/internal/frontend/qml/Proton/qmldir b/internal/frontend/qml/Proton/qmldir new file mode 100644 index 00000000..d518f67c --- /dev/null +++ b/internal/frontend/qml/Proton/qmldir @@ -0,0 +1,6 @@ +module QQtQuick.Controls.Proton +depends QtQuick.Controls 2.12 + +singleton ProtonStyle 4.0 Style.qml +Button 4.0 Button.qml + diff --git a/internal/frontend/qml/qtquickcontrols2.conf b/internal/frontend/qml/qtquickcontrols2.conf new file mode 100644 index 00000000..3512d512 --- /dev/null +++ b/internal/frontend/qml/qtquickcontrols2.conf @@ -0,0 +1,2 @@ +[Controls] +Style=Proton