From 67c7e9b0ca6208b4e6c97bdd820bdbc68e251b4f Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 11 Jun 2020 17:23:27 -0400 Subject: [PATCH] feat: implement design on the login screen --- src/app/login/view.nim | 41 ++-- src/app/onboarding/views/account_info.nim | 2 +- ui/app/img/refresh.svg | 4 + ui/nim-status-client.pro | 2 + ui/onboarding/Login.qml | 204 +++++++++++----- ui/onboarding/Login/AccountList.qml | 37 ++- ui/onboarding/Login/AddressView.qml | 74 ++++-- .../Login/SelectAnotherAccountModal.qml | 41 ++++ ui/onboarding/Login/qmldir | 1 + ui/onboarding/Login/samples/AccountsData.qml | 6 +- ui/shared/ModalPopup.qml | 224 +++++++++--------- ui/shared/RoundImage.qml | 29 +++ ui/shared/qmldir | 1 + 13 files changed, 442 insertions(+), 224 deletions(-) create mode 100644 ui/app/img/refresh.svg create mode 100644 ui/onboarding/Login/SelectAnotherAccountModal.qml create mode 100644 ui/shared/RoundImage.qml diff --git a/src/app/login/view.nim b/src/app/login/view.nim index f397cce96c..fce94b1b44 100644 --- a/src/app/login/view.nim +++ b/src/app/login/view.nim @@ -16,7 +16,8 @@ import core type AccountRoles {.pure.} = enum Username = UserRole + 1, - Identicon = UserRole + 2 + Identicon = UserRole + 2, + Address = UserRole + 3 QtObject: type LoginView* = ref object of QAbstractListModel @@ -38,9 +39,22 @@ QtObject: result.status = status 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) = self.beginInsertRows(newQModelIndex(), self.accounts.len, self.accounts.len) self.accounts.add(account) + if (self.accounts.len == 1): + self.setCurrentAccount(0) self.endInsertRows() proc removeAccounts*(self: LoginView) = @@ -62,25 +76,24 @@ QtObject: case assetRole: of AccountRoles.Username: result = newQVariant(asset.name) of AccountRoles.Identicon: result = newQVariant(asset.photoPath) + of AccountRoles.Address: result = newQVariant(asset.keyUid) method roleNames(self: LoginView): Table[int, string] = { AccountRoles.Username.int:"username", - AccountRoles.Identicon.int:"identicon" }.toTable + AccountRoles.Identicon.int:"identicon", + AccountRoles.Address.int:"address" }.toTable - proc getCurrentAccount*(self: LoginView): QVariant {.slot.} = - result = newQVariant(self.currentAccount) + proc login(self: LoginView, password: string): string {.slot.} = + 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: - result = self.status.accounts.login(selectedAccountIndex, password).toJson + result = self.status.accounts.login(currentAccountId, password).toJson except: let e = getCurrentException() diff --git a/src/app/onboarding/views/account_info.nim b/src/app/onboarding/views/account_info.nim index 9d2e871a57..a9d555dacb 100644 --- a/src/app/onboarding/views/account_info.nim +++ b/src/app/onboarding/views/account_info.nim @@ -33,7 +33,7 @@ QtObject: read = identicon 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: read = address notify = accountChanged diff --git a/ui/app/img/refresh.svg b/ui/app/img/refresh.svg new file mode 100644 index 0000000000..18799994b9 --- /dev/null +++ b/ui/app/img/refresh.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ui/nim-status-client.pro b/ui/nim-status-client.pro index bc0d9493d1..3f9e64f281 100644 --- a/ui/nim-status-client.pro +++ b/ui/nim-status-client.pro @@ -144,6 +144,7 @@ DISTFILES += \ onboarding/Login/AccountList.qml \ onboarding/Login/AccountSelection.qml \ onboarding/Login/AddressView.qml \ + onboarding/Login/SelectAnotherAccountModal.qml \ onboarding/Login/qmldir \ onboarding/Login/samples/AccountsData.qml \ onboarding/Login/samples/qmldir \ @@ -168,6 +169,7 @@ DISTFILES += \ shared/Input.qml \ shared/ModalPopup.qml \ shared/PopupMenu.qml \ + shared/RoundImage.qml \ shared/Select.qml \ shared/Separator.qml \ shared/StatusTabButton.qml \ diff --git a/ui/onboarding/Login.qml b/ui/onboarding/Login.qml index 36aa120d1b..41a4db3e01 100644 --- a/ui/onboarding/Login.qml +++ b/ui/onboarding/Login.qml @@ -3,75 +3,161 @@ import QtQuick.Controls 2.4 import QtQuick.Layouts 1.11 import QtQuick.Window 2.11 import QtQuick.Dialogs 1.3 +import QtGraphicalEffects 1.0 import "../shared" import "../imports" import "./Login" -SwipeView { - property alias btnGenKey: accountSelection.btnGenKey +Item { + property alias btnGenKey: genrateKeysLink + property bool loading: false - id: swipeView + id: loginView anchors.fill: parent - currentIndex: 0 - interactive: false - onCurrentItemChanged: { - if(currentItem.txtPassword) { - currentItem.txtPassword.textField.focus = true - } + Component.onCompleted: { + txtPassword.forceActiveFocus(Qt.MouseFocusReason) } - - AccountSelection { - id: accountSelection - onAccountSelect: function() { - loginModel.setCurrentAccount(this.selectedIndex) - swipeView.incrementCurrentIndex() - } - } - Item { - id: wizardStep2 - property Item txtPassword: txtPassword + id: element + 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 { - id: step2Title - text: "Enter password" - font.pointSize: 36 - anchors.top: parent.top - anchors.topMargin: 20 + id: usernameText + text: loginModel.currentAccount.username + font.weight: Font.Bold + font.pixelSize: 17 + anchors.top: userImage.bottom + anchors.topMargin: 4 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.top: step2Title.bottom - anchors.topMargin: 30 - Column { - Image { - source: loginModel.currentAccount.identicon - } - } - Column { - Text { - text: loginModel.currentAccount.username - } - } } Input { id: txtPassword - anchors.verticalCenter: parent.verticalCenter - anchors.rightMargin: Theme.padding - anchors.leftMargin: Theme.padding - anchors.left: parent.left - anchors.right: parent.right + anchors.top: addressText.bottom + anchors.topMargin: Theme.padding * 2 placeholderText: "Enter password" textField.echoMode: TextInput.Password + textField.focus: true Keys.onReturnPressed: { 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 { id: loginError title: "Login failed" @@ -81,6 +167,7 @@ SwipeView { onAccepted: { txtPassword.textField.clear() txtPassword.textField.focus = true + loading = false } } @@ -88,23 +175,26 @@ SwipeView { target: loginModel ignoreUnknownSignals: true onLoginResponseChanged: { - if(error){ - loginError.open() - } + if (error) { + loginError.open() + } } } - StyledButton { - id: submitBtn - label: "Finish" + MouseArea { + id: genrateKeysLink + width: genrateKeysLinkText.width + height: genrateKeysLinkText.height + cursorShape: Qt.PointingHandCursor + anchors.top: txtPassword.bottom + anchors.topMargin: 26 anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: 20 - onClicked: { - const selectedAccountIndex = accountSelection.selectedIndex - const response = loginModel.login(selectedAccountIndex, txtPassword.textField.text) - // TODO: replace me with something graphical (ie spinner) - console.log("Logging in...") + + Text { + id: genrateKeysLinkText + color: Theme.blue + text: qsTr("Generate new keys") + font.pixelSize: 13 } } } @@ -112,7 +202,7 @@ SwipeView { /*##^## Designer { - D{i:0;autoSize:true;height:480;width:640} + D{i:0;autoSize:true;formeditorColor:"#ffffff";formeditorZoom:0.75;height:480;width:640} } ##^##*/ diff --git a/ui/onboarding/Login/AccountList.qml b/ui/onboarding/Login/AccountList.qml index c95f79d6d1..77f5b533f5 100644 --- a/ui/onboarding/Login/AccountList.qml +++ b/ui/onboarding/Login/AccountList.qml @@ -3,34 +3,31 @@ import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import Qt.labs.platform 1.1 import "./samples/" +import "../../imports" ListView { property var accounts: AccountsData {} - property var onAccountSelect: function() {} + property var onAccountSelect: function () {} id: addressesView - anchors.right: parent.right - 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 + anchors.fill: parent model: accounts + focus: true + spacing: Theme.smallPadding delegate: AddressView { - username: model.username - identicon: model.identicon - onAccountSelect: function(index) { - addressesView.onAccountSelect(index) - } + username: model.username + address: model.address + identicon: model.identicon + onAccountSelect: function (index) { + addressesView.onAccountSelect(index) + } } - - Layout.fillHeight: true - Layout.fillWidth: true - focus: true } +/*##^## +Designer { + D{i:0;autoSize:true;height:480;width:640} +} +##^##*/ + diff --git a/ui/onboarding/Login/AddressView.qml b/ui/onboarding/Login/AddressView.qml index e4a499de90..d7489c5e87 100644 --- a/ui/onboarding/Login/AddressView.qml +++ b/ui/onboarding/Login/AddressView.qml @@ -2,34 +2,72 @@ import QtQuick 2.0 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import Qt.labs.platform 1.1 +import "../../imports" +import "../../shared" -Item { +Rectangle { 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 bool selected: loginModel.currentAccount.address === address + property bool isHovered: false id: addressViewDelegate - height: 56 + height: 64 anchors.right: parent.right - anchors.rightMargin: 0 anchors.left: parent.left - anchors.leftMargin: 0 + border.width: 0 + color: selected || isHovered ? Theme.grey : Theme.transparent + radius: Theme.radius - Row { - RadioButton { - checked: index == 0 ? true : false - ButtonGroup.group: accountGroup - onClicked: { onAccountSelect(index) } + RoundImage { + id: accountImage + anchors.left: parent.left + anchors.leftMargin: Theme.padding + 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 { - Image { - source: identicon - } + onEntered: { + addressViewDelegate.isHovered = true } - Column { - Text { - text: username - } + onExited: { + addressViewDelegate.isHovered = false } } } + +/*##^## +Designer { + D{i:0;formeditorColor:"#ffffff";height:64;width:450} +} +##^##*/ diff --git a/ui/onboarding/Login/SelectAnotherAccountModal.qml b/ui/onboarding/Login/SelectAnotherAccountModal.qml new file mode 100644 index 0000000000..ff476a15c5 --- /dev/null +++ b/ui/onboarding/Login/SelectAnotherAccountModal.qml @@ -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} +} +##^##*/ diff --git a/ui/onboarding/Login/qmldir b/ui/onboarding/Login/qmldir index 43f5bc0a5f..7174342c17 100644 --- a/ui/onboarding/Login/qmldir +++ b/ui/onboarding/Login/qmldir @@ -1,3 +1,4 @@ AccountSelection 1.0 AccountSelection.qml AccountList 1.0 AccountList.qml AddressView 1.0 AddressView.qml +SelectAnotherAccountModal 1.0 SelectAnotherAccountModal.qml diff --git a/ui/onboarding/Login/samples/AccountsData.qml b/ui/onboarding/Login/samples/AccountsData.qml index fd8b24db21..d5f4ec1903 100644 --- a/ui/onboarding/Login/samples/AccountsData.qml +++ b/ui/onboarding/Login/samples/AccountsData.qml @@ -6,11 +6,13 @@ import Qt.labs.platform 1.1 ListModel { ListElement { username: "Ferocious Herringbone Sinewave2" - identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" + identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAg0lEQVR4nOzXwQmAMBAFURV7sQybsgybsgyr0QYUlE1g+Mw7ioQMe9lMQwhDaAyhMYTGEJqYkPnrj/t5XE/ft2UdW1yken7MRAyhMYTGEBpDaAyhKe9JbzvSX9WdLWYihtAYQuMLkcYQGkPUScxEDKExhMYQGkNoDKExhMYQmjsAAP//ZfIUZgXTZXQAAAAASUVORK5CYII=" + address: "0x123456789009876543211234567890" } ListElement { username: "Another Account" - identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" + identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAg0lEQVR4nOzXwQmAMBAFURV7sQybsgybsgyr0QYUlE1g+Mw7ioQMe9lMQwhDaAyhMYTGEJqYkPnrj/t5XE/ft2UdW1yken7MRAyhMYTGEBpDaAyhKe9JbzvSX9WdLWYihtAYQuMLkcYQGkPUScxEDKExhMYQGkNoDKExhMYQmjsAAP//ZfIUZgXTZXQAAAAASUVORK5CYII=" + address: "0x123456789009876543211234567890" } } diff --git a/ui/shared/ModalPopup.qml b/ui/shared/ModalPopup.qml index 737c29e90f..0b11f6ba20 100644 --- a/ui/shared/ModalPopup.qml +++ b/ui/shared/ModalPopup.qml @@ -5,125 +5,125 @@ import "../imports" import "./" Popup { - property string title - default property alias content : popupContent.children - property alias header: headerContent.children + property string title + default property alias content: popupContent.children + property alias header: headerContent.children - id: popup - modal: true - property alias footer : footerContent.children + id: popup + modal: true + property alias footer: footerContent.children - Overlay.modal: Rectangle { - color: "#60000000" - } - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - parent: Overlay.overlay - x: Math.round((parent.width - width) / 2) - y: Math.round((parent.height - height) / 2) - width: 480 - height: 510 // TODO find a way to make this dynamic - background: Rectangle { - color: Theme.white - radius: 8 - } - padding: 0 - contentItem: Item { - - Item { - id: headerContent - width: parent.width - height: { - var idx = !!title ? 0 : 1 - return children[idx] && children[idx].height + Theme.padding + Overlay.modal: Rectangle { + color: "#60000000" + } + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + parent: Overlay.overlay + x: Math.round((parent.width - width) / 2) + y: Math.round((parent.height - height) / 2) + width: 480 + height: 510 // TODO find a way to make this dynamic + background: Rectangle { + color: Theme.white + radius: 8 + } + padding: 0 + contentItem: Item { + + Item { + id: headerContent + width: parent.width + height: { + var idx = !!title ? 0 : 1 + 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 { - 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 + Rectangle { + id: closeButton + height: 32 + width: 32 + anchors.top: parent.top + anchors.topMargin: Theme.padding + anchors.rightMargin: Theme.padding + anchors.right: parent.right + radius: 8 + + 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 { - id: closeButton - height: 32 - width: 32 - anchors.top: parent.top - anchors.topMargin: Theme.padding - anchors.rightMargin: Theme.padding - anchors.right: parent.right - radius: 8 + Separator { + id: separator + anchors.top: headerContent.bottom + } - Image { - id: closeModalImg - source: "./img/close.svg" - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - } + Item { + id: popupContent + anchors.top: separator.bottom + anchors.topMargin: Theme.padding + 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 { - id: closeModalMouseArea - cursorShape: Qt.PointingHandCursor - anchors.fill: parent - hoverEnabled: true - onExited: { - closeButton.color = Theme.white - } - onEntered:{ - closeButton.color = Theme.grey - } - onClicked : { - popup.close() - } - } - } - - Separator { - id: separator - anchors.top: headerContent.bottom - } + Separator { + id: separator2 + anchors.bottom: parent.bottom + anchors.bottomMargin: 75 + } - Item { - id: popupContent - anchors.top: separator.bottom - anchors.topMargin: Theme.padding - anchors.bottomMargin: Theme.padding - anchors.left: parent.left - anchors.leftMargin: Theme.padding - anchors.right: parent.right - anchors.rightMargin: 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 - } - } + 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 + } + } } - diff --git a/ui/shared/RoundImage.qml b/ui/shared/RoundImage.qml new file mode 100644 index 0000000000..d715cf88d5 --- /dev/null +++ b/ui/shared/RoundImage.qml @@ -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} +} +##^##*/ diff --git a/ui/shared/qmldir b/ui/shared/qmldir index fb59f7859b..dcc4f30032 100644 --- a/ui/shared/qmldir +++ b/ui/shared/qmldir @@ -8,3 +8,4 @@ TextWithLabel 1.0 TextWithLabel.qml Input 1.0 Input.qml Select 1.0 Select.qml StyledTextArea 1.0 StyledTextArea.qml +RoundImage 1.0 RoundImage.qml