feat: implement design on the login screen

This commit is contained in:
Jonathan Rainville 2020-06-11 17:23:27 -04:00 committed by Iuri Matias
parent eb9c948bb0
commit 67c7e9b0ca
13 changed files with 442 additions and 224 deletions

View File

@ -16,7 +16,8 @@ import core
type type
AccountRoles {.pure.} = enum AccountRoles {.pure.} = enum
Username = UserRole + 1, Username = UserRole + 1,
Identicon = UserRole + 2 Identicon = UserRole + 2,
Address = UserRole + 3
QtObject: QtObject:
type LoginView* = ref object of QAbstractListModel type LoginView* = ref object of QAbstractListModel
@ -38,9 +39,22 @@ QtObject:
result.status = status result.status = status
result.setup result.setup
proc getCurrentAccount*(self: LoginView): QVariant {.slot.} =
result = newQVariant(self.currentAccount)
proc setCurrentAccount*(self: LoginView, selectedAccountIdx: int) {.slot.} =
let currNodeAcct = self.accounts[selectedAccountIdx]
self.currentAccount.setAccount(GeneratedAccount(name: currNodeAcct.name, photoPath: currNodeAcct.photoPath, address: currNodeAcct.keyUid))
QtProperty[QVariant] currentAccount:
read = getCurrentAccount
write = setCurrentAccount
proc addAccountToList*(self: LoginView, account: NodeAccount) = proc addAccountToList*(self: LoginView, account: NodeAccount) =
self.beginInsertRows(newQModelIndex(), self.accounts.len, self.accounts.len) self.beginInsertRows(newQModelIndex(), self.accounts.len, self.accounts.len)
self.accounts.add(account) self.accounts.add(account)
if (self.accounts.len == 1):
self.setCurrentAccount(0)
self.endInsertRows() self.endInsertRows()
proc removeAccounts*(self: LoginView) = proc removeAccounts*(self: LoginView) =
@ -62,25 +76,24 @@ QtObject:
case assetRole: case assetRole:
of AccountRoles.Username: result = newQVariant(asset.name) of AccountRoles.Username: result = newQVariant(asset.name)
of AccountRoles.Identicon: result = newQVariant(asset.photoPath) of AccountRoles.Identicon: result = newQVariant(asset.photoPath)
of AccountRoles.Address: result = newQVariant(asset.keyUid)
method roleNames(self: LoginView): Table[int, string] = method roleNames(self: LoginView): Table[int, string] =
{ AccountRoles.Username.int:"username", { AccountRoles.Username.int:"username",
AccountRoles.Identicon.int:"identicon" }.toTable AccountRoles.Identicon.int:"identicon",
AccountRoles.Address.int:"address" }.toTable
proc getCurrentAccount*(self: LoginView): QVariant {.slot.} = proc login(self: LoginView, password: string): string {.slot.} =
result = newQVariant(self.currentAccount) var currentAccountId = 0
var i = 0
for account in self.accounts:
if (account.keyUid == self.currentAccount.address):
currentAccountId = i
break
i = i + 1
proc setCurrentAccount*(self: LoginView, selectedAccountIdx: int) {.slot.} =
let currNodeAcct = self.accounts[selectedAccountIdx]
self.currentAccount.setAccount(GeneratedAccount(name: currNodeAcct.name, photoPath: currNodeAcct.photoPath))
QtProperty[QVariant] currentAccount:
read = getCurrentAccount
write = setCurrentAccount
proc login(self: LoginView, selectedAccountIndex: int, password: string): string {.slot.} =
try: try:
result = self.status.accounts.login(selectedAccountIndex, password).toJson result = self.status.accounts.login(currentAccountId, password).toJson
except: except:
let let
e = getCurrentException() e = getCurrentException()

View File

@ -33,7 +33,7 @@ QtObject:
read = identicon read = identicon
notify = accountChanged notify = accountChanged
proc address*(self: AccountInfoView): string {.slot.} = result = ?.self.account.derived.whisper.publicKey proc address*(self: AccountInfoView): string {.slot.} = result = ?.self.account.address
QtProperty[string] address: QtProperty[string] address:
read = address read = address
notify = accountChanged notify = accountChanged

4
ui/app/img/refresh.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="20" height="19" viewBox="0 0 20 19" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.85365 15.7033C6.52223 15.4548 6.05005 15.4497 5.75716 15.7426C5.46426 16.0355 5.46194 16.5142 5.78534 16.773C6.94028 17.6973 8.40549 18.25 9.9998 18.25C13.7277 18.25 16.7498 15.2279 16.7498 11.5V11.0176C16.7498 10.5721 17.2884 10.349 17.6034 10.664L18.4697 11.5303C18.7626 11.8232 19.2374 11.8232 19.5303 11.5303C19.8232 11.2374 19.8232 10.7626 19.5303 10.4697L16.5303 7.46967C16.2374 7.17678 15.7626 7.17678 15.4697 7.46967L12.4697 10.4697C12.1768 10.7626 12.1768 11.2374 12.4697 11.5303C12.7626 11.8232 13.2374 11.8232 13.5303 11.5303L14.3962 10.6644C14.7112 10.3494 15.2498 10.5725 15.2498 11.018V11.5C15.2498 14.3995 12.8993 16.75 9.9998 16.75C8.81964 16.75 7.73043 16.3606 6.85365 15.7033Z" fill="black"/>
<path d="M4.53033 10.5303L7.53033 7.53033C7.82322 7.23744 7.82322 6.76256 7.53033 6.46967C7.23744 6.17678 6.76256 6.17678 6.46967 6.46967L5.60278 7.33656C5.30293 7.63641 4.79024 7.42405 4.79024 7C4.79024 4.1005 7.14075 1.75 10.0402 1.75C11.2204 1.75 12.3096 2.1394 13.1864 2.79673C13.5178 3.04519 13.99 3.05025 14.2829 2.75736C14.5758 2.46447 14.5781 1.98584 14.2547 1.72703C13.0998 0.802734 11.6345 0.25 10.0402 0.25C6.31232 0.25 3.29024 3.27208 3.29024 7V7.02247C3.29024 7.46793 2.75167 7.69101 2.43669 7.37603L1.53033 6.46967C1.23744 6.17678 0.762563 6.17678 0.46967 6.46967C0.176777 6.76256 0.176777 7.23744 0.46967 7.53033L3.46967 10.5303C3.76256 10.8232 4.23744 10.8232 4.53033 10.5303Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -144,6 +144,7 @@ DISTFILES += \
onboarding/Login/AccountList.qml \ onboarding/Login/AccountList.qml \
onboarding/Login/AccountSelection.qml \ onboarding/Login/AccountSelection.qml \
onboarding/Login/AddressView.qml \ onboarding/Login/AddressView.qml \
onboarding/Login/SelectAnotherAccountModal.qml \
onboarding/Login/qmldir \ onboarding/Login/qmldir \
onboarding/Login/samples/AccountsData.qml \ onboarding/Login/samples/AccountsData.qml \
onboarding/Login/samples/qmldir \ onboarding/Login/samples/qmldir \
@ -168,6 +169,7 @@ DISTFILES += \
shared/Input.qml \ shared/Input.qml \
shared/ModalPopup.qml \ shared/ModalPopup.qml \
shared/PopupMenu.qml \ shared/PopupMenu.qml \
shared/RoundImage.qml \
shared/Select.qml \ shared/Select.qml \
shared/Separator.qml \ shared/Separator.qml \
shared/StatusTabButton.qml \ shared/StatusTabButton.qml \

View File

@ -3,75 +3,161 @@ import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11 import QtQuick.Layouts 1.11
import QtQuick.Window 2.11 import QtQuick.Window 2.11
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.3
import QtGraphicalEffects 1.0
import "../shared" import "../shared"
import "../imports" import "../imports"
import "./Login" import "./Login"
SwipeView { Item {
property alias btnGenKey: accountSelection.btnGenKey property alias btnGenKey: genrateKeysLink
property bool loading: false
id: swipeView id: loginView
anchors.fill: parent anchors.fill: parent
currentIndex: 0
interactive: false
onCurrentItemChanged: { Component.onCompleted: {
if(currentItem.txtPassword) { txtPassword.forceActiveFocus(Qt.MouseFocusReason)
currentItem.txtPassword.textField.focus = true
}
} }
AccountSelection {
id: accountSelection
onAccountSelect: function() {
loginModel.setCurrentAccount(this.selectedIndex)
swipeView.incrementCurrentIndex()
}
}
Item { Item {
id: wizardStep2 id: element
property Item txtPassword: txtPassword width: 360
height: 200
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
RoundImage {
id: userImage
width: 40
height: 40
anchors.horizontalCenter: parent.horizontalCenter
source: loginModel.currentAccount.identicon
}
Text { Text {
id: step2Title id: usernameText
text: "Enter password" text: loginModel.currentAccount.username
font.pointSize: 36 font.weight: Font.Bold
anchors.top: parent.top font.pixelSize: 17
anchors.topMargin: 20 anchors.top: userImage.bottom
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
Row { SelectAnotherAccountModal {
id: selectAnotherAccountModal
onAccountSelect: function (index) {
loginModel.setCurrentAccount(index)
}
}
Rectangle {
property bool isHovered: false
id: changeAccountBtn
width: 24
height: 24
anchors.left: usernameText.right
anchors.leftMargin: 4
anchors.verticalCenter: usernameText.verticalCenter
color: isHovered ? Theme.grey : Theme.transparent
radius: 4
Image {
id: caretImg
width: 10
height: 6
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
source: "../app/img/caret.svg"
fillMode: Image.PreserveAspectFit
}
ColorOverlay {
anchors.fill: caretImg
source: caretImg
color: Theme.darkGrey
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onEntered: {
changeAccountBtn.isHovered = true
}
onExited: {
changeAccountBtn.isHovered = false
}
onClicked: {
selectAnotherAccountModal.open()
// TODO add popup for when there are no other accounts
}
}
}
Text {
id: addressText
width: 90
color: Theme.darkGrey
text: loginModel.currentAccount.address
elide: Text.ElideMiddle
font.pixelSize: 15
anchors.top: usernameText.bottom
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: step2Title.bottom
anchors.topMargin: 30
Column {
Image {
source: loginModel.currentAccount.identicon
}
}
Column {
Text {
text: loginModel.currentAccount.username
}
}
} }
Input { Input {
id: txtPassword id: txtPassword
anchors.verticalCenter: parent.verticalCenter anchors.top: addressText.bottom
anchors.rightMargin: Theme.padding anchors.topMargin: Theme.padding * 2
anchors.leftMargin: Theme.padding
anchors.left: parent.left
anchors.right: parent.right
placeholderText: "Enter password" placeholderText: "Enter password"
textField.echoMode: TextInput.Password textField.echoMode: TextInput.Password
textField.focus: true
Keys.onReturnPressed: { Keys.onReturnPressed: {
submitBtn.clicked() submitBtn.clicked()
} }
} }
Button {
id: submitBtn
visible: txtPassword.text.length > 0
width: 40
height: 40
anchors.left: txtPassword.right
anchors.leftMargin: Theme.padding
anchors.verticalCenter: txtPassword.verticalCenter
onClicked: {
if (loading) {
return;
}
loading = true
loginModel.login(txtPassword.textField.text)
}
Image {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
// TODO replace by a real loading image
source: loading ? "../app/img/refresh.svg" : "../app/img/arrowUp.svg"
width: 13.5
height: 17.5
fillMode: Image.PreserveAspectFit
rotation: 90
}
background: Rectangle {
color: Theme.blue
radius: 50
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
submitBtn.onClicked()
}
}
}
MessageDialog { MessageDialog {
id: loginError id: loginError
title: "Login failed" title: "Login failed"
@ -81,6 +167,7 @@ SwipeView {
onAccepted: { onAccepted: {
txtPassword.textField.clear() txtPassword.textField.clear()
txtPassword.textField.focus = true txtPassword.textField.focus = true
loading = false
} }
} }
@ -88,23 +175,26 @@ SwipeView {
target: loginModel target: loginModel
ignoreUnknownSignals: true ignoreUnknownSignals: true
onLoginResponseChanged: { onLoginResponseChanged: {
if(error){ if (error) {
loginError.open() loginError.open()
} }
} }
} }
StyledButton { MouseArea {
id: submitBtn id: genrateKeysLink
label: "Finish" width: genrateKeysLinkText.width
height: genrateKeysLinkText.height
cursorShape: Qt.PointingHandCursor
anchors.top: txtPassword.bottom
anchors.topMargin: 26
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20 Text {
onClicked: { id: genrateKeysLinkText
const selectedAccountIndex = accountSelection.selectedIndex color: Theme.blue
const response = loginModel.login(selectedAccountIndex, txtPassword.textField.text) text: qsTr("Generate new keys")
// TODO: replace me with something graphical (ie spinner) font.pixelSize: 13
console.log("Logging in...")
} }
} }
} }
@ -112,7 +202,7 @@ SwipeView {
/*##^## /*##^##
Designer { Designer {
D{i:0;autoSize:true;height:480;width:640} D{i:0;autoSize:true;formeditorColor:"#ffffff";formeditorZoom:0.75;height:480;width:640}
} }
##^##*/ ##^##*/

View File

@ -3,34 +3,31 @@ import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1 import Qt.labs.platform 1.1
import "./samples/" import "./samples/"
import "../../imports"
ListView { ListView {
property var accounts: AccountsData {} property var accounts: AccountsData {}
property var onAccountSelect: function() {} property var onAccountSelect: function () {}
id: addressesView id: addressesView
anchors.right: parent.right anchors.fill: parent
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.bottom: footer.top
anchors.bottomMargin: 0
anchors.top: title.bottom
anchors.topMargin: 16
contentWidth: 200
height: parent.height
model: accounts model: accounts
focus: true
spacing: Theme.smallPadding
delegate: AddressView { delegate: AddressView {
username: model.username username: model.username
identicon: model.identicon address: model.address
onAccountSelect: function(index) { identicon: model.identicon
addressesView.onAccountSelect(index) onAccountSelect: function (index) {
} addressesView.onAccountSelect(index)
}
} }
Layout.fillHeight: true
Layout.fillWidth: true
focus: true
} }
/*##^##
Designer {
D{i:0;autoSize:true;height:480;width:640}
}
##^##*/

View File

@ -2,34 +2,72 @@ import QtQuick 2.0
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1 import Qt.labs.platform 1.1
import "../../imports"
import "../../shared"
Item { Rectangle {
property string username: "Jotaro Kujo" property string username: "Jotaro Kujo"
property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" property string address: "0x123345677890987654321123456"
property url identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAg0lEQVR4nOzXwQmAMBAFURV7sQybsgybsgyr0QYUlE1g+Mw7ioQMe9lMQwhDaAyhMYTGEJqYkPnrj/t5XE/ft2UdW1yken7MRAyhMYTGEBpDaAyhKe9JbzvSX9WdLWYihtAYQuMLkcYQGkPUScxEDKExhMYQGkNoDKExhMYQmjsAAP//ZfIUZgXTZXQAAAAASUVORK5CYII="
property var onAccountSelect: function() {} property var onAccountSelect: function() {}
property bool selected: loginModel.currentAccount.address === address
property bool isHovered: false
id: addressViewDelegate id: addressViewDelegate
height: 56 height: 64
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 0 border.width: 0
color: selected || isHovered ? Theme.grey : Theme.transparent
radius: Theme.radius
Row { RoundImage {
RadioButton { id: accountImage
checked: index == 0 ? true : false anchors.left: parent.left
ButtonGroup.group: accountGroup anchors.leftMargin: Theme.padding
onClicked: { onAccountSelect(index) } anchors.verticalCenter: parent.verticalCenter
source: identicon
}
Text {
id: usernameText
text: username
font.pixelSize: 17
anchors.top: accountImage.top
anchors.left: accountImage.right
anchors.leftMargin: Theme.padding
}
Text {
id: addressText
width: 108
text: address
elide: Text.ElideMiddle
anchors.bottom: accountImage.bottom
anchors.bottomMargin: 0
anchors.left: usernameText.left
anchors.leftMargin: 0
font.pixelSize: 15
color: Theme.darkGrey
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
onAccountSelect(index)
} }
Column { onEntered: {
Image { addressViewDelegate.isHovered = true
source: identicon
}
} }
Column { onExited: {
Text { addressViewDelegate.isHovered = false
text: username
}
} }
} }
} }
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";height:64;width:450}
}
##^##*/

View File

@ -0,0 +1,41 @@
import QtQuick 2.12
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import "../../imports"
import "../../shared"
ModalPopup {
property var onAccountSelect: function () {}
id: popup
title: qsTr("Your accounts")
AccountList {
id: accountList
anchors.fill: parent
accounts: loginModel
onAccountSelect: function(index) {
popup.onAccountSelect(index)
popup.close()
}
}
footer: StyledButton {
anchors.top: parent.top
anchors.topMargin: Theme.padding
anchors.right: parent.right
anchors.rightMargin: Theme.padding
label: "Add another existing key"
onClicked : {
console.log('Open other popup for seed')
}
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";height:500;width:400}
}
##^##*/

View File

@ -1,3 +1,4 @@
AccountSelection 1.0 AccountSelection.qml AccountSelection 1.0 AccountSelection.qml
AccountList 1.0 AccountList.qml AccountList 1.0 AccountList.qml
AddressView 1.0 AddressView.qml AddressView 1.0 AddressView.qml
SelectAnotherAccountModal 1.0 SelectAnotherAccountModal.qml

View File

@ -6,11 +6,13 @@ import Qt.labs.platform 1.1
ListModel { ListModel {
ListElement { ListElement {
username: "Ferocious Herringbone Sinewave2" username: "Ferocious Herringbone Sinewave2"
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAg0lEQVR4nOzXwQmAMBAFURV7sQybsgybsgyr0QYUlE1g+Mw7ioQMe9lMQwhDaAyhMYTGEJqYkPnrj/t5XE/ft2UdW1yken7MRAyhMYTGEBpDaAyhKe9JbzvSX9WdLWYihtAYQuMLkcYQGkPUScxEDKExhMYQGkNoDKExhMYQmjsAAP//ZfIUZgXTZXQAAAAASUVORK5CYII="
address: "0x123456789009876543211234567890"
} }
ListElement { ListElement {
username: "Another Account" username: "Another Account"
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAg0lEQVR4nOzXwQmAMBAFURV7sQybsgybsgyr0QYUlE1g+Mw7ioQMe9lMQwhDaAyhMYTGEJqYkPnrj/t5XE/ft2UdW1yken7MRAyhMYTGEBpDaAyhKe9JbzvSX9WdLWYihtAYQuMLkcYQGkPUScxEDKExhMYQGkNoDKExhMYQmjsAAP//ZfIUZgXTZXQAAAAASUVORK5CYII="
address: "0x123456789009876543211234567890"
} }
} }

View File

@ -5,125 +5,125 @@ import "../imports"
import "./" import "./"
Popup { Popup {
property string title property string title
default property alias content : popupContent.children default property alias content: popupContent.children
property alias header: headerContent.children property alias header: headerContent.children
id: popup id: popup
modal: true modal: true
property alias footer : footerContent.children property alias footer: footerContent.children
Overlay.modal: Rectangle { Overlay.modal: Rectangle {
color: "#60000000" color: "#60000000"
} }
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
parent: Overlay.overlay parent: Overlay.overlay
x: Math.round((parent.width - width) / 2) x: Math.round((parent.width - width) / 2)
y: Math.round((parent.height - height) / 2) y: Math.round((parent.height - height) / 2)
width: 480 width: 480
height: 510 // TODO find a way to make this dynamic height: 510 // TODO find a way to make this dynamic
background: Rectangle { background: Rectangle {
color: Theme.white color: Theme.white
radius: 8 radius: 8
} }
padding: 0 padding: 0
contentItem: Item { contentItem: Item {
Item { Item {
id: headerContent id: headerContent
width: parent.width width: parent.width
height: { height: {
var idx = !!title ? 0 : 1 var idx = !!title ? 0 : 1
return children[idx] && children[idx].height + Theme.padding return children[idx] && children[idx].height + Theme.padding
}
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottomMargin: Theme.padding
anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
Text {
text: title
anchors.top: parent.top
anchors.left: parent.left
font.bold: true
font.pixelSize: 17
anchors.leftMargin: 16
anchors.topMargin: Theme.padding
anchors.bottomMargin: Theme.padding
visible: !!title
}
} }
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottomMargin: Theme.padding
anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
Text { Rectangle {
text: title id: closeButton
anchors.top: parent.top height: 32
anchors.left: parent.left width: 32
font.bold: true anchors.top: parent.top
font.pixelSize: 17 anchors.topMargin: Theme.padding
anchors.leftMargin: 16 anchors.rightMargin: Theme.padding
anchors.topMargin: Theme.padding anchors.right: parent.right
anchors.bottomMargin: Theme.padding radius: 8
visible: !!title
Image {
id: closeModalImg
source: "./img/close.svg"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: closeModalMouseArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onExited: {
closeButton.color = Theme.white
}
onEntered: {
closeButton.color = Theme.grey
}
onClicked: {
popup.close()
}
}
} }
}
Rectangle { Separator {
id: closeButton id: separator
height: 32 anchors.top: headerContent.bottom
width: 32 }
anchors.top: parent.top
anchors.topMargin: Theme.padding
anchors.rightMargin: Theme.padding
anchors.right: parent.right
radius: 8
Image { Item {
id: closeModalImg id: popupContent
source: "./img/close.svg" anchors.top: separator.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.topMargin: Theme.padding
anchors.verticalCenter: parent.verticalCenter anchors.bottom: separator2.top
} anchors.bottomMargin: Theme.padding
anchors.left: parent.left
anchors.leftMargin: Theme.padding
anchors.right: parent.right
anchors.rightMargin: Theme.padding
}
MouseArea { Separator {
id: closeModalMouseArea id: separator2
cursorShape: Qt.PointingHandCursor anchors.bottom: parent.bottom
anchors.fill: parent anchors.bottomMargin: 75
hoverEnabled: true }
onExited: {
closeButton.color = Theme.white
}
onEntered:{
closeButton.color = Theme.grey
}
onClicked : {
popup.close()
}
}
}
Separator {
id: separator
anchors.top: headerContent.bottom
}
Item { Item {
id: popupContent id: footerContent
anchors.top: separator.bottom height: children[0] && children[0].height
anchors.topMargin: Theme.padding width: parent.width
anchors.bottomMargin: Theme.padding anchors.top: separator2.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Theme.padding anchors.right: parent.right
anchors.right: parent.right anchors.bottom: parent.bottom
anchors.rightMargin: Theme.padding anchors.bottomMargin: Theme.padding
} anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
Separator { }
id: separator2 }
anchors.bottom: parent.bottom
anchors.bottomMargin: 75
}
Item {
id: footerContent
height: children[0] && children[0].height
width: parent.width
anchors.top: separator2.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.padding
anchors.rightMargin: Theme.padding
anchors.leftMargin: Theme.padding
}
}
} }

29
ui/shared/RoundImage.qml Normal file
View File

@ -0,0 +1,29 @@
import QtQuick 2.3
import "../imports"
Rectangle {
id: roundedImage
property url source:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAg0lEQVR4nOzXwQmAMBAFURV7sQybsgybsgyr0QYUlE1g+Mw7ioQMe9lMQwhDaAyhMYTGEJqYkPnrj/t5XE/ft2UdW1yken7MRAyhMYTGEBpDaAyhKe9JbzvSX9WdLWYihtAYQuMLkcYQGkPUScxEDKExhMYQGkNoDKExhMYQmjsAAP//ZfIUZgXTZXQAAAAASUVORK5CYII="
width: 40
height: 40
color: Theme.white
radius: 50
border.width: 1
border.color: Theme.darkGrey
Image {
width: parent.width
height: parent.height
fillMode: Image.PreserveAspectFit
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
source: roundedImage.source
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#4c4e50";formeditorZoom:2}
}
##^##*/

View File

@ -8,3 +8,4 @@ TextWithLabel 1.0 TextWithLabel.qml
Input 1.0 Input.qml Input 1.0 Input.qml
Select 1.0 Select.qml Select 1.0 Select.qml
StyledTextArea 1.0 StyledTextArea.qml StyledTextArea 1.0 StyledTextArea.qml
RoundImage 1.0 RoundImage.qml