Merge pull request #826

Remote nodes + mobile layout
This commit is contained in:
luigi1111
2017-11-03 15:29:10 -05:00
60 changed files with 2174 additions and 1383 deletions

8
.gitignore vendored
View File

@@ -3,3 +3,11 @@
translations/*.qm translations/*.qm
build build
version.js version.js
# IOS stuff below
moc_*
*.o
*.mak
*.build
*.xcodeproj
monero-wallet-gui_plugin_import.cpp
monero-wallet-gui_qml_plugin_import.cpp

View File

@@ -50,6 +50,7 @@ Rectangle {
signal addressBookClicked() signal addressBookClicked()
signal miningClicked() signal miningClicked()
signal signClicked() signal signClicked()
signal keysClicked()
function selectItem(pos) { function selectItem(pos) {
menuColumn.previousButton.checked = false menuColumn.previousButton.checked = false
@@ -69,6 +70,8 @@ Rectangle {
width: (isMobile)? appWindow.width : 260 width: (isMobile)? appWindow.width : 260
color: "#FFFFFF" color: "#FFFFFF"
anchors.bottom: parent.bottom
anchors.top: parent.top
// Item with monero logo // Item with monero logo
Item { Item {
@@ -138,8 +141,8 @@ Rectangle {
visible: !isMobile visible: !isMobile
Item { Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
height: 26 height: 26 * scaleRatio
width: 50 width: 50 * scaleRatio
Image { Image {
anchors.centerIn: parent anchors.centerIn: parent
@@ -228,7 +231,8 @@ Rectangle {
Flickable { Flickable {
contentHeight: 500 id:flicker
contentHeight: 500 * scaleRatio
anchors.fill: parent anchors.fill: parent
clip: true clip: true
@@ -239,7 +243,7 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
clip: true
property var previousButton: transferButton property var previousButton: transferButton
// ------------- Dashboard tab --------------- // ------------- Dashboard tab ---------------
@@ -393,6 +397,7 @@ Rectangle {
// ------------- Mining tab --------------- // ------------- Mining tab ---------------
MenuButton { MenuButton {
id: miningButton id: miningButton
visible: !isAndroid && !isIOS
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
text: qsTr("Mining") + translationManager.emptyString text: qsTr("Mining") + translationManager.emptyString
@@ -483,10 +488,33 @@ Rectangle {
color: "#505050" color: "#505050"
height: 1 height: 1
} }
// ------------- Sign/verify tab ---------------
MenuButton {
id: keysButton
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("Seed & Keys") + translationManager.emptyString
symbol: qsTr("Y") + translationManager.emptyString
dotColor: "#FFD781"
under: settingsButton
onClicked: {
parent.previousButton.checked = false
parent.previousButton = keysButton
panel.keysClicked()
}
}
Rectangle {
visible: settingsButton.present
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
color: "#505050"
height: 1
}
} } // Column
} } // Flickable
NetworkStatusItem { NetworkStatusItem {
id: networkStatus id: networkStatus
@@ -494,6 +522,7 @@ Rectangle {
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: (progressBar.visible)? progressBar.top : parent.bottom; anchors.bottom: (progressBar.visible)? progressBar.top : parent.bottom;
connected: Wallet.ConnectionStatus_Disconnected connected: Wallet.ConnectionStatus_Disconnected
height: 58 * scaleRatio
} }
ProgressBar { ProgressBar {
@@ -501,8 +530,9 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
height: 35 * scaleRatio
} }
} } // menuRect

View File

@@ -29,6 +29,7 @@
import QtQml 2.0 import QtQml 2.0
import QtQuick 2.2 import QtQuick 2.2
// QtQuick.Controls 2.0 isn't stable enough yet. Needs more testing.
//import QtQuick.Controls 2.0 //import QtQuick.Controls 2.0
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
@@ -47,7 +48,7 @@ Rectangle {
property string balanceText property string balanceText
property string unlockedBalanceLabelText: qsTr("Unlocked Balance") + translationManager.emptyString property string unlockedBalanceLabelText: qsTr("Unlocked Balance") + translationManager.emptyString
property string unlockedBalanceText property string unlockedBalanceText
property int minHeight: (appWindow.height > 800) ? appWindow.height : 800 property int minHeight: (appWindow.height > 800) ? appWindow.height : 800 * scaleRatio
// property int headerHeight: header.height // property int headerHeight: header.height
property Transfer transferView: Transfer { } property Transfer transferView: Transfer { }
@@ -58,6 +59,7 @@ Rectangle {
property Settings settingsView: Settings { } property Settings settingsView: Settings { }
property Mining miningView: Mining { } property Mining miningView: Mining { }
property AddressBook addressBookView: AddressBook { } property AddressBook addressBookView: AddressBook { }
property Keys keysView: Keys { }
signal paymentClicked(string address, string paymentId, string amount, int mixinCount, int priority, string description) signal paymentClicked(string address, string paymentId, string amount, int mixinCount, int priority, string description)
@@ -93,33 +95,6 @@ Rectangle {
transferView.sendTo(address, paymentId, description); transferView.sendTo(address, paymentId, description);
} }
// XXX: just for memo, to be removed
// states: [
// State {
// name: "Dashboard"
// PropertyChanges { target: loader; source: "pages/Dashboard.qml" }
// }, State {
// name: "History"
// PropertyChanges { target: loader; source: "pages/History.qml" }
// }, State {
// name: "Transfer"
// PropertyChanges { target: loader; source: "pages/Transfer.qml" }
// }, State {
// name: "Receive"
// PropertyChanges { target: loader; source: "pages/Receive.qml" }
// }, State {
// name: "AddressBook"
// PropertyChanges { target: loader; source: "pages/AddressBook.qml" }
// }, State {
// name: "Settings"
// PropertyChanges { target: loader; source: "pages/Settings.qml" }
// }, State {
// name: "Mining"
// PropertyChanges { target: loader; source: "pages/Mining.qml" }
// }
// ]
states: [ states: [
State { State {
name: "Dashboard" name: "Dashboard"
@@ -132,7 +107,7 @@ Rectangle {
}, State { }, State {
name: "Transfer" name: "Transfer"
PropertyChanges { target: root; currentView: transferView } PropertyChanges { target: root; currentView: transferView }
PropertyChanges { target: mainFlickable; contentHeight: 1000 } PropertyChanges { target: mainFlickable; contentHeight: 1000 * scaleRatio }
}, State { }, State {
name: "Receive" name: "Receive"
PropertyChanges { target: root; currentView: receiveView } PropertyChanges { target: root; currentView: receiveView }
@@ -152,11 +127,15 @@ Rectangle {
}, State { }, State {
name: "Settings" name: "Settings"
PropertyChanges { target: root; currentView: settingsView } PropertyChanges { target: root; currentView: settingsView }
PropertyChanges { target: mainFlickable; contentHeight: 1200 } PropertyChanges { target: mainFlickable; contentHeight: 1200 * scaleRatio }
}, State { }, State {
name: "Mining" name: "Mining"
PropertyChanges { target: root; currentView: miningView } PropertyChanges { target: root; currentView: miningView }
PropertyChanges { target: mainFlickable; contentHeight: minHeight } PropertyChanges { target: mainFlickable; contentHeight: minHeight }
}, State {
name: "Keys"
PropertyChanges { target: root; currentView: keysView }
PropertyChanges { target: mainFlickable; contentHeight: minHeight + 200 * scaleRatio }
} }
] ]
@@ -187,6 +166,11 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
clip: true clip: true
onFlickingChanged: {
releaseFocus();
}
// Disabled scrollbars, gives crash on startup on windows // Disabled scrollbars, gives crash on startup on windows
// ScrollIndicator.vertical: ScrollIndicator { } // ScrollIndicator.vertical: ScrollIndicator { }
// ScrollBar.vertical: ScrollBar { } // uncomment to test // ScrollBar.vertical: ScrollBar { } // uncomment to test
@@ -195,11 +179,7 @@ Rectangle {
StackView { StackView {
id: stackView id: stackView
initialItem: transferView initialItem: transferView
// anchors.topMargin: 30
// Layout.fillWidth: true
// Layout.fillHeight: true
anchors.fill:parent anchors.fill:parent
// anchors.margins: 4
clip: true // otherwise animation will affect left panel clip: true // otherwise animation will affect left panel
delegate: StackViewDelegate { delegate: StackViewDelegate {

View File

@@ -38,121 +38,4 @@ Rectangle {
id: root id: root
width: 330 width: 330
color: "#FFFFFF" color: "#FFFFFF"
function updateTweets() {
tabView.twitter.item.updateTweets()
}
TabView {
id: tabView
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: styledRow.top
anchors.leftMargin: 14
anchors.rightMargin: 14
anchors.topMargin: 40
property alias twitter: twitter
Tab { id: twitter; title: qsTr("Twitter"); source: "tabs/Twitter.qml" }
Tab { title: qsTr("News") + translationManager.emptyString }
Tab { title: qsTr("Help") + translationManager.emptyString }
Tab { title: qsTr("About") + translationManager.emptyString }
style: TabViewStyle {
frameOverlap: 0
tabOverlap: 0
tab: Rectangle {
implicitHeight: 31
implicitWidth: styleData.index === tabView.count - 1 ? tabView.width - (tabView.count - 1) * 68 : 68
Text {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 12
anchors.rightMargin: 12
elide: Text.ElideRight
font.family: "Arial"
font.pixelSize: 14
color: styleData.selected ? "#FF4E40" : "#4A4646"
text: styleData.title
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
color: "#DBDBDB"
visible: styleData.index !== tabView.count - 1
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.bottomMargin: -1
height: 1
color: styleData.selected ? "#FFFFFF" : "#DBDBDB"
}
}
frame: Rectangle {
color: "#FFFFFF"
anchors.fill: parent
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
//anchors.topMargin: 1
height: 1
color: "#DBDBDB"
}
}
}
}
Row {
id: styledRow
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
Rectangle { height: 8; width: parent.width / 5; color: "#FFE00A" }
Rectangle { height: 8; width: parent.width / 5; color: "#6B0072" }
Rectangle { height: 8; width: parent.width / 5; color: "#FF6C3C" }
Rectangle { height: 8; width: parent.width / 5; color: "#FFD781" }
Rectangle { height: 8; width: parent.width / 5 - 30; color: "#FF4F41" }
}
Rectangle {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: "#DBDBDB"
}
Rectangle {
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: 1
color: "#DBDBDB"
}
// indicate disabled state
// Desaturate {
// anchors.fill: parent
// source: parent
// desaturation: root.enabled ? 0.0 : 1.0
// }
} }

View File

@@ -144,8 +144,10 @@ ListView {
onOptionClicked: { onOptionClicked: {
// Ensure tooltip is closed // Ensure tooltip is closed
appWindow.toolTip.visible = false; appWindow.toolTip.visible = false;
if(option === 0) if(option === 0) {
clipboard.setText(address) clipboard.setText(address)
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3)
}
else if(option === 1){ else if(option === 1){
console.log("Sending to: ", address +" "+ paymentId); console.log("Sending to: ", address +" "+ paymentId);
middlePanel.sendTo(address, paymentId, description); middlePanel.sendTo(address, paymentId, description);

View File

@@ -29,61 +29,70 @@
import QtQuick 2.0 import QtQuick 2.0
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
Item { RowLayout {
id: checkBox id: checkBox
property alias text: label.text property alias text: label.text
property string checkedIcon property string checkedIcon
property string uncheckedIcon property string uncheckedIcon
property bool checked: false property bool checked: false
property alias background: backgroundRect.color property alias background: backgroundRect.color
property int fontSize: 14 property int fontSize: 14 * scaleRatio
property alias fontColor: label.color property alias fontColor: label.color
signal clicked() signal clicked()
height: 25 height: 25 * scaleRatio
width: label.x + label.width
Layout.minimumWidth: label.x + label.contentWidth
clip: true
Rectangle { function toggle(){
anchors.left: parent.left checkBox.checked = !checkBox.checked
height: parent.height - 1 checkBox.clicked()
width: 25
//radius: 4
y: 0
color: "#DBDBDB"
} }
Rectangle { RowLayout {
id: backgroundRect Layout.fillWidth: true
anchors.left: parent.left Rectangle {
height: parent.height - 1 anchors.left: parent.left
width: 25 width: 25 * scaleRatio
//radius: 4 height: checkBox.height - 1
y: 1 //radius: 4
color: "#FFFFFF" y: 0
color: "#DBDBDB"
Image {
anchors.centerIn: parent
source: checkBox.checked ? checkBox.checkedIcon :
checkBox.uncheckedIcon
} }
}
Text { Rectangle {
id: label id: backgroundRect
anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left
anchors.left: parent.left width: 25 * scaleRatio
anchors.leftMargin: 25 + 12 height: checkBox.height - 1
font.family: "Arial" //radius: 4
font.pixelSize: checkBox.fontSize y: 1
color: "#525252" color: "#FFFFFF"
}
MouseArea { Image {
anchors.fill: parent anchors.centerIn: parent
onClicked: { source: checkBox.checked ? checkBox.checkedIcon :
checkBox.checked = !checkBox.checked checkBox.uncheckedIcon
checkBox.clicked() }
MouseArea {
anchors.fill: parent
onClicked: {
toggle()
}
}
}
Text {
id: label
font.family: "Arial"
font.pixelSize: checkBox.fontSize
color: "#525252"
wrapMode: Text.Wrap
Layout.fillWidth: true
MouseArea {
anchors.fill: parent
onClicked: {
toggle()
}
}
} }
} }
} }

View File

@@ -90,7 +90,7 @@ Window {
} }
Text { Text {
text: qsTr("Starting Monero daemon in %1 seconds").arg(countDown); text: qsTr("Starting local node in %1 seconds").arg(countDown);
font.pixelSize: 18 font.pixelSize: 18
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true Layout.fillWidth: true

View File

@@ -79,14 +79,6 @@ ListView {
} }
} }
StandardDialog {
id: detailsPopup
cancelVisible: false
okVisible: true
width:850
}
delegate: Rectangle { delegate: Rectangle {
id: delegate id: delegate
height: 144 height: 144
@@ -111,10 +103,10 @@ ListView {
onClicked: { onClicked: {
var tx_key = currentWallet.getTxKey(hash) var tx_key = currentWallet.getTxKey(hash)
var tx_note = currentWallet.getUserNote(hash) var tx_note = currentWallet.getUserNote(hash)
detailsPopup.title = "Transaction details"; informationPopup.title = "Transaction details";
detailsPopup.content = buildTxDetailsString(hash,paymentId,tx_key,tx_note,destinations); informationPopup.content = buildTxDetailsString(hash,paymentId,tx_key,tx_note,destinations);
detailsPopup.open(); informationPopup.onCloseCallback = null
informationPopup.open();
} }
} }
@@ -383,7 +375,7 @@ ListView {
Column { Column {
anchors.top: parent.top anchors.top: parent.top
width: 148 width: 148
visible: isOut visible: isOut && fee != ""
Text { Text {
anchors.left: parent.left anchors.left: parent.left
font.family: "Arial" font.family: "Arial"

View File

@@ -0,0 +1,191 @@
// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.0
import QtQuick.Layouts 1.1
import moneroComponents.Clipboard 1.0
import moneroComponents.AddressBookModel 1.0
ListView {
id: listView
clip: true
boundsBehavior: ListView.StopAtBounds
property var previousItem
property var addressBookModel: null
function buildTxDetailsString(tx_id, paymentId, tx_key,tx_note, destinations) {
var trStart = '<tr><td width="85" style="padding-top:5px"><b>',
trMiddle = '</b></td><td style="padding-left:10px;padding-top:5px;">',
trEnd = "</td></tr>";
return '<table border="0">'
+ (tx_id ? trStart + qsTr("Tx ID:") + trMiddle + tx_id + trEnd : "")
+ (paymentId ? trStart + qsTr("Payment ID:") + trMiddle + paymentId + trEnd : "")
+ (tx_key ? trStart + qsTr("Tx key:") + trMiddle + tx_key + trEnd : "")
+ (tx_note ? trStart + qsTr("Tx note:") + trMiddle + tx_note + trEnd : "")
+ (destinations ? trStart + qsTr("Destinations:") + trMiddle + destinations + trEnd : "")
+ "</table>"
+ translationManager.emptyString;
}
function lookupPaymentID(paymentId) {
if (!addressBookModel)
return ""
var idx = addressBookModel.lookupPaymentID(paymentId)
if (idx < 0)
return ""
idx = addressBookModel.index(idx, 0)
return addressBookModel.data(idx, AddressBookModel.AddressBookDescriptionRole)
}
footer: Rectangle {
height: 127 * scaleRatio
width: listView.width
color: "#FFFFFF"
Text {
anchors.centerIn: parent
font.family: "Arial"
font.pixelSize: 14 * scaleRatio
color: "#545454"
text: qsTr("No more results") + translationManager.emptyString
}
}
delegate: Rectangle {
id: delegate
height: tableContent.height + 20 * scaleRatio
width: listView.width
color: index % 2 ? "#F8F8F8" : "#FFFFFF"
Layout.leftMargin: 10 * scaleRatio
z: listView.count - index
function collapseDropdown() { dropdown.expanded = false }
MouseArea {
anchors.fill: parent
onClicked: {
var tx_key = currentWallet.getTxKey(hash)
var tx_note = currentWallet.getUserNote(hash)
informationPopup.title = "Transaction details";
informationPopup.text = buildTxDetailsString(hash,paymentId,tx_key,tx_note,destinations);
informationPopup.open();
informationPopup.onCloseCallback = null
}
}
Rectangle {
anchors.right: parent.right
anchors.rightMargin: 15 * scaleRatio
anchors.top: parent.top
anchors.topMargin: parent.height/2 - this.height/2
width: 30 * scaleRatio; height: 30 * scaleRatio
radius: 25
color: "#FF4304"
Image {
width: 20 * scaleRatio
height: 20 * scaleRatio
fillMode: Image.PreserveAspectFit
anchors.centerIn: parent
source: "qrc:///images/nextPage.png"
}
}
ColumnLayout {
id: tableContent
// Date
RowLayout {
Layout.topMargin: 20 * scaleRatio
Layout.leftMargin: 10 * scaleRatio
Text {
font.family: "Arial"
font.pixelSize: 14 * scaleRatio
color: "#555555"
text: date
}
Text {
font.family: "Arial"
font.pixelSize: 14 * scaleRatio
color: "#555555"
text: time
}
// Show confirmations
Text {
visible: confirmations < confirmationsRequired || isPending
Layout.leftMargin: 5 * scaleRatio
font.family: "Arial"
font.pixelSize: 14 * scaleRatio
color: (confirmations < confirmationsRequired)? "#FF6C3C" : "#545454"
text: {
if (!isPending)
if(confirmations < confirmationsRequired)
return qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired)
if (!isOut)
return qsTr("UNCONFIRMED") + translationManager.emptyString
return qsTr("PENDING") + translationManager.emptyString
}
}
}
// Amount & confirmations
RowLayout {
Layout.leftMargin: 10 * scaleRatio
spacing: 2
Text {
font.family: "Arial"
font.pixelSize: 14 * scaleRatio
color: isOut ? "#FF4F41" : "#36B05B"
text: isOut ? "↓" : "↑"
}
Text {
id: amountText
font.family: "Arial"
font.pixelSize: 18 * scaleRatio
color: isOut ? "#FF4F41" : "#36B05B"
text: displayAmount
}
}
}
}
ListModel {
id: dropModel
ListElement { name: "<b>Copy address to clipboard</b>"; icon: "../images/dropdownCopy.png" }
ListElement { name: "<b>Add to address book</b>"; icon: "../images/dropdownAdd.png" }
ListElement { name: "<b>Send to this address</b>"; icon: "../images/dropdownSend.png" }
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
}
Clipboard { id: clipboard }
}

View File

@@ -33,7 +33,7 @@ import QtQuick 2.2
TextField { TextField {
font.family: "Arial" font.family: "Arial"
horizontalAlignment: TextInput.AlignLeft horizontalAlignment: TextInput.AlignLeft
selectByMouse: true
style: TextFieldStyle { style: TextFieldStyle {
textColor: "#3F3F3F" textColor: "#3F3F3F"
placeholderTextColor: "#BABABA" placeholderTextColor: "#BABABA"

View File

@@ -35,19 +35,21 @@ Item {
property alias color: label.color property alias color: label.color
property alias textFormat: label.textFormat property alias textFormat: label.textFormat
property string tipText: "" property string tipText: ""
property int fontSize: 12 property int fontSize: 16 * scaleRatio
property alias wrapMode: label.wrapMode property alias wrapMode: label.wrapMode
property alias horizontalAlignment: label.horizontalAlignment
signal linkActivated() signal linkActivated()
width: icon.x + icon.width width: icon.x + icon.width * scaleRatio
height: icon.height height: icon.height * scaleRatio
Layout.topMargin: 10 * scaleRatio
Text { Text {
id: label id: label
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: 2 anchors.bottomMargin: 2 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
font.family: "Arial" font.family: "Arial"
font.pixelSize: parent.fontSize font.pixelSize: fontSize
color: "#555555" color: "#555555"
onLinkActivated: item.linkActivated() onLinkActivated: item.linkActivated()
} }
@@ -56,7 +58,7 @@ Item {
id: icon id: icon
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: label.right anchors.left: label.right
anchors.leftMargin: 5 anchors.leftMargin: 5 * scaleRatio
source: "../images/whatIsIcon.png" source: "../images/whatIsIcon.png"
visible: appWindow.whatIsEnable visible: appWindow.whatIsEnable
} }

View File

@@ -36,13 +36,13 @@ Item {
property alias readOnly : input.readOnly property alias readOnly : input.readOnly
property alias cursorPosition: input.cursorPosition property alias cursorPosition: input.cursorPosition
property alias echoMode: input.echoMode property alias echoMode: input.echoMode
property int fontSize: 18 property int fontSize: 18 * scaleRatio
property bool error: false property bool error: false
signal editingFinished() signal editingFinished()
signal accepted(); signal accepted();
signal textUpdated(); signal textUpdated();
height: 37 height: 37 * scaleRatio
function getColor(error) { function getColor(error) {
if (error) if (error)
@@ -53,14 +53,14 @@ Item {
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: 1 anchors.bottomMargin: 1 * scaleRatio
color: "#DBDBDB" color: "#DBDBDB"
//radius: 4 //radius: 4
} }
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 1 anchors.topMargin: 1 * scaleRatio
color: getColor(error) color: getColor(error)
//radius: 4 //radius: 4
} }
@@ -68,8 +68,8 @@ Item {
Input { Input {
id: input id: input
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 4 anchors.leftMargin: 4 * scaleRatio
anchors.rightMargin: 30 anchors.rightMargin: 30 * scaleRatio
font.pixelSize: parent.fontSize font.pixelSize: parent.fontSize
onEditingFinished: item.editingFinished() onEditingFinished: item.editingFinished()
onAccepted: item.accepted(); onAccepted: item.accepted();

View File

@@ -38,11 +38,18 @@ Rectangle {
property var under: null property var under: null
signal clicked() signal clicked()
function doClick() {
// Android workaround
releaseFocus();
clicked();
}
function getOffset() { function getOffset() {
var offset = 0 var offset = 0
var item = button var item = button
while (item.under) { while (item.under) {
offset += 20 offset += 20 * scaleRatio
item = item.under item = item.under
} }
return offset return offset
@@ -50,7 +57,7 @@ Rectangle {
color: checked ? "#FFFFFF" : "#1C1C1C" color: checked ? "#FFFFFF" : "#1C1C1C"
property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 property bool present: !under || under.checked || checked || under.numSelectedChildren > 0
height: present ? ((appWindow.height >= 800) ? 64 : 52) : 0 height: present ? ((appWindow.height >= 800) ? 64 * scaleRatio : 52 * scaleRatio ) : 0
transform: Scale { transform: Scale {
yScale: button.present ? 1 : 0 yScale: button.present ? 1 : 0
@@ -76,18 +83,18 @@ Rectangle {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: parent.getOffset() anchors.leftMargin: parent.getOffset()
width: 50 width: 50 * scaleRatio
Rectangle { Rectangle {
id: dot id: dot
anchors.centerIn: parent anchors.centerIn: parent
width: 16 width: 16 * scaleRatio
height: width height: width
radius: height / 2 radius: height / 2
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
width: 12 width: 12 * scaleRatio
height: width height: width
radius: height / 2 radius: height / 2
color: "#1C1C1C" color: "#1C1C1C"
@@ -98,7 +105,7 @@ Rectangle {
Text { Text {
id: symbolText id: symbolText
anchors.centerIn: parent anchors.centerIn: parent
font.pixelSize: 11 font.pixelSize: 11 * scaleRatio
font.bold: true font.bold: true
color: button.checked || buttonArea.containsMouse ? "#FFFFFF" : dot.color color: button.checked || buttonArea.containsMouse ? "#FFFFFF" : dot.color
visible: appWindow.ctrlPressed visible: appWindow.ctrlPressed
@@ -117,7 +124,7 @@ Rectangle {
Image { Image {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 20 anchors.rightMargin: 20 * scaleRatio
anchors.leftMargin: parent.getOffset() anchors.leftMargin: parent.getOffset()
source: "../images/menuIndicator.png" source: "../images/menuIndicator.png"
} }
@@ -126,9 +133,9 @@ Rectangle {
id: label id: label
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: parent.getOffset() + 50 anchors.leftMargin: parent.getOffset() + 50 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18 * scaleRatio
color: parent.checked ? "#000000" : "#FFFFFF" color: parent.checked ? "#000000" : "#FFFFFF"
} }
@@ -139,7 +146,7 @@ Rectangle {
onClicked: { onClicked: {
if(parent.checked) if(parent.checked)
return return
button.clicked() button.doClick()
parent.checked = true parent.checked = true
} }
} }

View File

@@ -10,17 +10,16 @@ Rectangle {
anchors.leftMargin: 1 anchors.leftMargin: 1
anchors.rightMargin: 1 anchors.rightMargin: 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 64 Layout.preferredHeight: 64 * scaleRatio
color: "#FFFFFF" color: "#FFFFFF"
// visible: basicMode
Image { Image {
id: logo id: logo
visible: appWindow.width > 460 visible: appWindow.width > 460 * scaleRatio
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -5 anchors.verticalCenterOffset: -5
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: appWindow.persistentSettings.customDecorations ? 20 : 40 anchors.leftMargin: 50 * scaleRatio
source: "../images/moneroLogo2.png" source: "../images/moneroLogo2.png"
} }
@@ -28,9 +27,8 @@ Rectangle {
id: icon id: icon
visible: !logo.visible visible: !logo.visible
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
// anchors.verticalCenterOffset: -5
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: appWindow.persistentSettings.customDecorations ? 20 : 40 anchors.leftMargin: 40 * scaleRatio
source: "../images/moneroIcon.png" source: "../images/moneroIcon.png"
} }
@@ -38,16 +36,16 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 10 anchors.topMargin: 10 * scaleRatio
width: 256 width: 256 * scaleRatio
columns: 3 columns: 3
Text { Text {
id: balanceLabel id: balanceLabel
width: 116 width: 116 * scaleRatio
height: 20 height: 20 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
font.letterSpacing: -1 font.letterSpacing: -1
elide: Text.ElideRight elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
@@ -58,10 +56,10 @@ Rectangle {
Text { Text {
id: balanceText id: balanceText
width: 110 width: 110 * scaleRatio
height: 20 height: 20 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18 * scaleRatio
font.letterSpacing: -1 font.letterSpacing: -1
elide: Text.ElideRight elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
@@ -71,8 +69,8 @@ Rectangle {
} }
Item { Item {
height: 20 height: 20 * scaleRatio
width: 20 width: 20 * scaleRatio
Image { Image {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@@ -82,10 +80,10 @@ Rectangle {
} }
Text { Text {
width: 116 width: 116 * scaleRatio
height: 20 height: 20 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
font.letterSpacing: -1 font.letterSpacing: -1
elide: Text.ElideRight elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
@@ -96,10 +94,10 @@ Rectangle {
Text { Text {
id: availableBalanceText id: availableBalanceText
width: 110 width: 110 * scaleRatio
height: 20 height: 20 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 14 font.pixelSize: 14 * scaleRatio
font.letterSpacing: -1 font.letterSpacing: -1
elide: Text.ElideRight elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft

View File

@@ -29,7 +29,7 @@
import QtQuick 2.0 import QtQuick 2.0
import moneroComponents.Wallet 1.0 import moneroComponents.Wallet 1.0
Row { Rectangle {
id: item id: item
property var connected: Wallet.ConnectionStatus_Disconnected property var connected: Wallet.ConnectionStatus_Disconnected
@@ -51,6 +51,8 @@ Row {
if (status == Wallet.ConnectionStatus_Connected) { if (status == Wallet.ConnectionStatus_Connected) {
if(!appWindow.daemonSynced) if(!appWindow.daemonSynced)
return qsTr("Synchronizing") return qsTr("Synchronizing")
if(appWindow.remoteNodeConnected)
return qsTr("Remote node")
return qsTr("Connected") return qsTr("Connected")
} }
if (status == Wallet.ConnectionStatus_WrongVersion) if (status == Wallet.ConnectionStatus_WrongVersion)
@@ -60,37 +62,44 @@ Row {
return qsTr("Invalid connection status") return qsTr("Invalid connection status")
} }
Item {
id: iconItem
anchors.bottom: parent.bottom
width: 50
height: 50
Image { color: "#1C1C1C"
anchors.centerIn: parent Row {
source: getConnectionStatusImage(item.connected) height: 60 * scaleRatio
Item {
id: iconItem
anchors.bottom: parent.bottom
width: 50 * scaleRatio
height: 50 * scaleRatio
Image {
anchors.centerIn: parent
source: getConnectionStatusImage(item.connected)
}
}
Column {
anchors.bottom: parent.bottom
height: 53 * scaleRatio
spacing: 3 * scaleRatio
Text {
anchors.left: parent.left
font.family: "Arial"
font.pixelSize: 12 * scaleRatio
color: "#545454"
text: qsTr("Network status") + translationManager.emptyString
}
Text {
anchors.left: parent.left
font.family: "Arial"
font.pixelSize: 18 * scaleRatio
color: getConnectionStatusColor(item.connected)
text: getConnectionStatusString(item.connected) + translationManager.emptyString
}
} }
} }
Column {
anchors.bottom: parent.bottom
height: 53
spacing: 3
Text {
anchors.left: parent.left
font.family: "Arial"
font.pixelSize: 12
color: "#545454"
text: qsTr("Network status") + translationManager.emptyString
}
Text {
anchors.left: parent.left
font.family: "Arial"
font.pixelSize: 18
color: getConnectionStatusColor(item.connected)
text: getConnectionStatusString(item.connected) + translationManager.emptyString
}
}
} }

View File

@@ -35,40 +35,48 @@ import QtQuick.Window 2.0
import "../components" as MoneroComponents import "../components" as MoneroComponents
Window { Item {
id: root id: root
modality: Qt.ApplicationModal visible: false
flags: Qt.Window | Qt.FramelessWindowHint Rectangle {
id: bg
z: parent.z + 1
anchors.fill: parent
color: "white"
opacity: 0.9
}
property alias password: passwordInput.text property alias password: passwordInput.text
property string walletName property string walletName
// same signals as Dialog has // same signals as Dialog has
signal accepted() signal accepted()
signal rejected() signal rejected()
signal closeCallback()
function open(walletName) { function open(walletName) {
root.walletName = walletName ? walletName : "" root.walletName = walletName ? walletName : ""
leftPanel.enabled = false
middlePanel.enabled = false
titleBar.enabled = false
show() show()
root.visible = true;
passwordInput.focus = true
} }
// TODO: implement without hardcoding sizes function close() {
width: 480 leftPanel.enabled = true
height: walletName ? 240 : 200 middlePanel.enabled = true
titleBar.enabled = true
// Make window draggable root.visible = false;
MouseArea { closeCallback();
anchors.fill: parent
property point lastMousePos: Qt.point(0, 0)
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
} }
ColumnLayout { ColumnLayout {
z: bg.z + 1
id: mainLayout id: mainLayout
spacing: 10 spacing: 10
anchors { fill: parent; margins: 35 } anchors { fill: parent; margins: 35 * scaleRatio }
ColumnLayout { ColumnLayout {
id: column id: column
@@ -81,20 +89,20 @@ Window {
Layout.columnSpan: 2 Layout.columnSpan: 2
Layout.fillWidth: true Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
font.pixelSize: 24 font.pixelSize: 18 * scaleRatio
font.family: "Arial" font.family: "Arial"
color: "#555555" color: "#555555"
} }
TextField { TextField {
id : passwordInput id : passwordInput
focus: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 400 * scaleRatio
horizontalAlignment: TextInput.AlignHCenter horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter verticalAlignment: TextInput.AlignVCenter
font.family: "Arial" font.family: "Arial"
font.pixelSize: 32 font.pixelSize: 32 * scaleRatio
echoMode: TextInput.Password echoMode: TextInput.Password
KeyNavigation.tab: okButton KeyNavigation.tab: okButton
@@ -128,27 +136,18 @@ Window {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
anchors.bottomMargin: 3 anchors.bottomMargin: 3
Layout.maximumWidth: passwordInput.width
} }
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
} }
// Ok/Cancel buttons // Ok/Cancel buttons
RowLayout { RowLayout {
id: buttons id: buttons
spacing: 60 spacing: 60 * scaleRatio
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
MoneroComponents.StandardButton { MoneroComponents.StandardButton {
id: cancelButton id: cancelButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
@@ -162,13 +161,11 @@ Window {
} }
MoneroComponents.StandardButton { MoneroComponents.StandardButton {
id: okButton id: okButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
pressedColor: "#FF4304" pressedColor: "#FF4304"
text: qsTr("Ok") text: qsTr("Continue")
KeyNavigation.tab: cancelButton KeyNavigation.tab: cancelButton
onClicked: { onClicked: {
root.close() root.close()
@@ -178,6 +175,3 @@ Window {
} }
} }
} }

View File

@@ -31,17 +31,26 @@ import QtQuick.Window 2.1
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
Window { Rectangle {
id: root id: root
modality: Qt.ApplicationModal color: "white"
flags: Qt.Window visible: false
z:11
property alias messageText: messageTitle.text property alias messageText: messageTitle.text
property alias heightProgressText : heightProgress.text property alias heightProgressText : heightProgress.text
width: 200 width: 200 * scaleRatio
height: 100 height: 100 * scaleRatio
opacity: 0.7 opacity: 0.7
function show() {
root.visible = true;
}
function close() {
root.visible = false;
}
ColumnLayout { ColumnLayout {
id: rootLayout id: rootLayout
@@ -49,8 +58,8 @@ Window {
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: 30 anchors.leftMargin: 30 * scaleRatio
anchors.rightMargin: 30 anchors.rightMargin: 30 * scaleRatio
BusyIndicator { BusyIndicator {
running: parent.visible running: parent.visible
@@ -61,7 +70,7 @@ Window {
id: messageTitle id: messageTitle
text: "Please wait..." text: "Please wait..."
font { font {
pixelSize: 22 pixelSize: 22 * scaleRatio
} }
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
@@ -72,7 +81,7 @@ Window {
Text { Text {
id: heightProgress id: heightProgress
font { font {
pixelSize: 18 pixelSize: 18 * scaleRatio
} }
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter

View File

@@ -29,15 +29,13 @@
import QtQuick 2.0 import QtQuick 2.0
import moneroComponents.Wallet 1.0 import moneroComponents.Wallet 1.0
Item { Rectangle {
id: item id: item
property int fillLevel: 0 property int fillLevel: 0
height: 22
anchors.margins:15
visible: false visible: false
//clip: true color: "#1C1C1C"
function updateProgress(currentBlock,targetBlock, blocksToSync){ function updateProgress(currentBlock,targetBlock, blocksToSync, statusTxt){
if(targetBlock == 1) { if(targetBlock == 1) {
fillLevel = 0 fillLevel = 0
progressText.text = qsTr("Establishing connection..."); progressText.text = qsTr("Establishing connection...");
@@ -54,53 +52,68 @@ Item {
else else
var progressLevel = (100*(currentBlock/targetBlock)).toFixed(0); var progressLevel = (100*(currentBlock/targetBlock)).toFixed(0);
fillLevel = progressLevel fillLevel = progressLevel
progressText.text = qsTr("Blocks remaining: %1").arg(remaining.toFixed(0)); if(typeof statusTxt != "undefined" && statusTxt != "") {
progressText.text = statusTxt + (" %1").arg(remaining.toFixed(0));
} else {
progressText.text = qsTr("Blocks remaining: %1").arg(remaining.toFixed(0));
}
progressBar.visible = currentBlock < targetBlock progressBar.visible = currentBlock < targetBlock
} }
} }
Rectangle { Item {
id: bar anchors.leftMargin: 15 * scaleRatio
anchors.left: parent.left anchors.rightMargin: 15 * scaleRatio
anchors.right: parent.right anchors.fill: parent
anchors.top: parent.top
height: 22
radius: 2
color: "#FFFFFF"
Rectangle { Rectangle {
id: fillRect id: bar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom height: 22 * scaleRatio
anchors.left: parent.left radius: 2 * scaleRatio
anchors.margins: 2 color: "#FFFFFF"
height: bar.height
property int maxWidth: parent.width - 4
width: (maxWidth * fillLevel) / 100
color: {
if(item.fillLevel < 99 ) return "#FF6C3C"
//if(item.fillLevel < 99) return "#FFE00A"
return "#36B25C"
}
} Rectangle {
id: fillRect
Rectangle { anchors.top: parent.top
color:"#333"
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: 8
Text {
id:progressText
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
font.family: "Arial" anchors.left: parent.left
font.pixelSize: 12 anchors.margins: 2 * scaleRatio
color: "#000" height: bar.height
text: qsTr("Synchronizing blocks") property int maxWidth: parent.width - 4 * scaleRatio
height:18 width: (maxWidth * fillLevel) / 100
color: {
if(item.fillLevel < 99 ) return "#FF6C3C"
//if(item.fillLevel < 99) return "#FFE00A"
return "#36B25C"
}
}
Rectangle {
color:"#333"
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: 8 * scaleRatio
Text {
id:progressText
anchors.bottom: parent.bottom
font.family: "Arial"
font.pixelSize: 12 * scaleRatio
color: "#000"
text: qsTr("Synchronizing blocks")
height:18 * scaleRatio
}
} }
} }
} }
} }

View File

@@ -44,7 +44,7 @@ Rectangle {
color: "black" color: "black"
state: "Stopped" state: "Stopped"
signal qrcode_decoded(string address, string payment_id, string amount, string tx_description, string recipient_name) signal qrcode_decoded(string address, string payment_id, string amount, string tx_description, string recipient_name, var extra_parameters)
states: [ states: [
State { State {
@@ -83,7 +83,7 @@ Rectangle {
id : finder id : finder
objectName: "QrFinder" objectName: "QrFinder"
onDecoded : { onDecoded : {
root.qrcode_decoded(address, payment_id, amount, tx_description, recipient_name) root.qrcode_decoded(address, payment_id, amount, tx_description, recipient_name, extra_parameters)
root.state = "Stopped" root.state = "Stopped"
} }
onNotifyError : { onNotifyError : {
@@ -126,7 +126,7 @@ Rectangle {
MessageDialog { MessageDialog {
id: messageDialog id: messageDialog
title: "Scanning QrCode" title: qsTr("QrCode Scanned") + translationManager.emptyString
onAccepted: { onAccepted: {
root.state = "Stopped" root.state = "Stopped"
} }

View File

@@ -0,0 +1,60 @@
// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick 2.2
import QtQuick.Layouts 1.1
GridLayout {
columns: (isMobile) ? 1 : 2
id: root
property alias daemonAddrText: daemonAddr.text
property alias daemonPortText: daemonPort.text
signal editingFinished()
function getAddress() {
return daemonAddr.text.trim() + ":" + daemonPort.text.trim()
}
LineEdit {
id: daemonAddr
Layout.fillWidth: true
placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString
onEditingFinished: root.editingFinished()
}
LineEdit {
id: daemonPort
Layout.fillWidth: true
placeholderText: qsTr("Port") + translationManager.emptyString
onEditingFinished: root.editingFinished()
}
}

View File

@@ -31,19 +31,25 @@ import QtQuick.Layouts 1.1
Item { Item {
id: button id: button
height: 37 height: 37 * scaleRatio
property string shadowPressedColor property string shadowPressedColor: "#B32D00"
property string shadowReleasedColor property string shadowReleasedColor: "#FF4304"
property string pressedColor property string pressedColor: "#FF4304"
property string releasedColor property string releasedColor: "#FF6C3C"
property string icon: "" property string icon: ""
property string textColor: "#FFFFFF" property string textColor: "#FFFFFF"
property int fontSize: 12 property int fontSize: 12 * scaleRatio
property alias text: label.text property alias text: label.text
signal clicked() signal clicked()
// Dynamic label width // Dynamic label width
Layout.minimumWidth: (label.contentWidth > 80)? label.contentWidth + 20 : 100 Layout.minimumWidth: (label.contentWidth > 50)? label.contentWidth + 10 : 60
function doClick() {
// Android workaround
releaseFocus();
clicked();
}
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
@@ -98,9 +104,9 @@ Item {
MouseArea { MouseArea {
id: buttonArea id: buttonArea
anchors.fill: parent anchors.fill: parent
onClicked: parent.clicked() onClicked: doClick()
} }
Keys.onSpacePressed: clicked() Keys.onSpacePressed: doClick()
Keys.onReturnPressed: clicked() Keys.onReturnPressed: doClick()
} }

View File

@@ -35,10 +35,10 @@ import QtQuick.Window 2.0
import "../components" as MoneroComponents import "../components" as MoneroComponents
Window { Rectangle {
id: root id: root
modality: Qt.ApplicationModal color: "white"
flags: Qt.Window | Qt.FramelessWindowHint visible: false
property alias title: dialogTitle.text property alias title: dialogTitle.text
property alias text: dialogContent.text property alias text: dialogContent.text
property alias content: root.text property alias content: root.text
@@ -53,6 +53,7 @@ Window {
// same signals as Dialog has // same signals as Dialog has
signal accepted() signal accepted()
signal rejected() signal rejected()
signal closeCallback();
// Make window draggable // Make window draggable
MouseArea { MouseArea {
@@ -64,12 +65,24 @@ Window {
} }
function open() { function open() {
// Center
if(!isMobile) {
root.x = parent.width/2 - root.width/2
root.y = screenHeight/2 - root.height/2
}
show() show()
root.z = 11
root.visible = true;
}
function close() {
root.visible = false;
closeCallback();
} }
// TODO: implement without hardcoding sizes // TODO: implement without hardcoding sizes
width: 480 width: isMobile ? screenWidth : 480
height: 280 height: isMobile ? screenHeight : 280
ColumnLayout { ColumnLayout {
id: mainLayout id: mainLayout
@@ -84,7 +97,7 @@ Window {
Label { Label {
id: dialogTitle id: dialogTitle
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
font.pixelSize: 32 font.pixelSize: 18 * scaleRatio
font.family: "Arial" font.family: "Arial"
color: "#555555" color: "#555555"
} }
@@ -99,7 +112,23 @@ Window {
font.family: "Arial" font.family: "Arial"
textFormat: TextEdit.AutoText textFormat: TextEdit.AutoText
readOnly: true readOnly: true
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
selectByMouse: false
wrapMode: TextEdit.Wrap
MouseArea {
anchors.fill: parent
onClicked: {
appWindow.showStatusMessage(qsTr("Double tap to copy"),3)
}
onDoubleClicked: {
parent.selectAll()
parent.copy()
parent.deselect()
console.log("copied to clipboard");
appWindow.showStatusMessage(qsTr("Content copied to clipboard"),3)
}
}
} }
} }
@@ -111,8 +140,6 @@ Window {
MoneroComponents.StandardButton { MoneroComponents.StandardButton {
id: cancelButton id: cancelButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
@@ -126,13 +153,11 @@ Window {
MoneroComponents.StandardButton { MoneroComponents.StandardButton {
id: okButton id: okButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
pressedColor: "#FF4304" pressedColor: "#FF4304"
text: qsTr("Ok") text: qsTr("OK")
KeyNavigation.tab: cancelButton KeyNavigation.tab: cancelButton
onClicked: { onClicked: {
root.close() root.close()

View File

@@ -38,7 +38,10 @@ Item {
property string textColor: "#FFFFFF" property string textColor: "#FFFFFF"
property alias currentIndex: column.currentIndex property alias currentIndex: column.currentIndex
property bool expanded: false property bool expanded: false
height: 37
signal changed();
height: 37 * scaleRatio
onExpandedChanged: if(expanded) appWindow.currentItem = dropdown onExpandedChanged: if(expanded) appWindow.currentItem = dropdown
function hide() { dropdown.expanded = false } function hide() { dropdown.expanded = false }
@@ -54,12 +57,18 @@ Item {
return true return true
} }
// Workaroud for suspected memory leak in 5.8 causing malloc crash on app exit
function update() {
firstColText.text = column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column1) + translationManager.emptyString : ""
secondColText.text = column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column2) + translationManager.emptyString : ""
}
Item { Item {
id: head id: head
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
height: 37 height: 37 * scaleRatio
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
@@ -82,8 +91,8 @@ Item {
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
height: 3 height: 3 * scaleRatio
width: 3 width: 3 * scaleRatio
color: dropdown.pressedColor color: dropdown.pressedColor
visible: dropdown.expanded || droplist.height > 0 visible: dropdown.expanded || droplist.height > 0
} }
@@ -91,8 +100,8 @@ Item {
Rectangle { Rectangle {
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
height: 3 height: 3 * scaleRatio
width: 3 width: 3 * scaleRatio
color: dropdown.pressedColor color: dropdown.pressedColor
visible: dropdown.expanded || droplist.height > 0 visible: dropdown.expanded || droplist.height > 0
} }
@@ -101,26 +110,23 @@ Item {
id: firstColText id: firstColText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 12 anchors.leftMargin: 12 * scaleRatio
elide: Text.ElideRight elide: Text.ElideRight
font.family: "Arial" font.family: "Arial"
font.bold: true font.bold: true
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
color: "#FFFFFF" color: "#FFFFFF"
text: column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column1) + translationManager.emptyString : ""
} }
Text { Text {
id: secondColText id: secondColText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.right: separator.left anchors.right: separator.left
anchors.rightMargin: 12 anchors.rightMargin: 12 * scaleRatio
width: dropdown.expanded ? w : (separator.x - 12) - (firstColText.x + firstColText.width + 5) width: dropdown.expanded ? w : (separator.x - 12) - (firstColText.x + firstColText.width + 5)
font.family: "Arial" font.family: "Arial"
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
color: "#FFFFFF" color: "#FFFFFF"
text: column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column2) + translationManager.emptyString : ""
property int w: 0 property int w: 0
Component.onCompleted: w = implicitWidth Component.onCompleted: w = implicitWidth
} }
@@ -129,7 +135,7 @@ Item {
id: separator id: separator
anchors.right: dropIndicator.left anchors.right: dropIndicator.left
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
height: 18 height: 18 * scaleRatio
width: 1 width: 1
color: "#FFFFFF" color: "#FFFFFF"
} }
@@ -139,12 +145,12 @@ Item {
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
width: 32 width: 32 * scaleRatio
Image { Image {
anchors.centerIn: parent anchors.centerIn: parent
source: "../images/whiteDropIndicator.png" source: "../images/whiteDropIndicator.png"
rotation: dropdown.expanded ? 180 : 0 rotation: dropdown.expanded ? 180 * scaleRatio : 0
} }
} }
@@ -168,14 +174,14 @@ Item {
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
width: 3; height: 3 width: 3 * scaleRatio; height: 3 * scaleRatio
color: dropdown.pressedColor color: dropdown.pressedColor
} }
Rectangle { Rectangle {
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
width: 3; height: 3 width: 3 * scaleRatio; height: 3 * scaleRatio
color: dropdown.pressedColor color: dropdown.pressedColor
} }
@@ -209,7 +215,7 @@ Item {
delegate: Rectangle { delegate: Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: 30 height: 30 * scaleRatio
//radius: index === repeater.count - 1 ? 4 : 0 //radius: index === repeater.count - 1 ? 4 : 0
color: itemArea.containsMouse || index === column.currentIndex || itemArea.containsMouse ? dropdown.releasedColor : dropdown.pressedColor color: itemArea.containsMouse || index === column.currentIndex || itemArea.containsMouse ? dropdown.releasedColor : dropdown.pressedColor
@@ -217,11 +223,11 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.right: col2Text.left anchors.right: col2Text.left
anchors.leftMargin: 12 anchors.leftMargin: 12 * scaleRatio
anchors.rightMargin: column2.length > 0 ? 12 : 0 anchors.rightMargin: column2.length > 0 ? 12 * scaleRatio: 0
font.family: "Arial" font.family: "Arial"
font.bold: true font.bold: true
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
color: "#FFFFFF" color: "#FFFFFF"
text: qsTr(column1) + translationManager.emptyString text: qsTr(column1) + translationManager.emptyString
} }
@@ -230,9 +236,9 @@ Item {
id: col2Text id: col2Text
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 45 anchors.rightMargin: 45 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
color: "#FFFFFF" color: "#FFFFFF"
text: column2 text: column2
} }
@@ -240,14 +246,14 @@ Item {
Rectangle { Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
width: 3; height: 3 width: 3 * scaleRatio; height: 3 * scaleRatio
color: parent.color color: parent.color
} }
Rectangle { Rectangle {
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
width: 3; height: 3 width: 3 * scaleRatio; height: 3 * scaleRatio
color: parent.color color: parent.color
} }
@@ -258,6 +264,8 @@ Item {
onClicked: { onClicked: {
dropdown.expanded = false dropdown.expanded = false
column.currentIndex = index column.currentIndex = index
changed();
dropdown.update()
} }
} }
} }

View File

@@ -49,7 +49,7 @@ Item {
anchors.bottomMargin: 2 anchors.bottomMargin: 2
font.family: "Arial" font.family: "Arial"
font.bold: true font.bold: true
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
color: "#4A4949" color: "#4A4949"
text: { text: {
if(currentIndex === 0) return qsTr("Normal") + translationManager.emptyString if(currentIndex === 0) return qsTr("Normal") + translationManager.emptyString

View File

@@ -28,6 +28,7 @@
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Window 2.0 import QtQuick.Window 2.0
import QtQuick.Layouts 1.1
Rectangle { Rectangle {
id: titleBar id: titleBar
@@ -37,7 +38,7 @@ Rectangle {
property alias basicButtonVisible: goToBasicVersionButton.visible property alias basicButtonVisible: goToBasicVersionButton.visible
property bool customDecorations: true property bool customDecorations: true
signal goToBasicVersion(bool yes) signal goToBasicVersion(bool yes)
height: customDecorations ? 30 : 0 height: customDecorations && !isMobile ? 30 : 0
y: -height y: -height
property string title property string title
property alias maximizeButtonVisible: maximizeButton.visible property alias maximizeButtonVisible: maximizeButton.visible
@@ -53,21 +54,22 @@ Rectangle {
} }
Rectangle { Rectangle {
id: goToBasicVersionButton id: goToBasicVersionButton
property bool containsMouse: titleBar.mouseX >= x && titleBar.mouseX <= x + width property bool containsMouse: titleBar.mouseX >= x && titleBar.mouseX <= x + width
property bool checked: false property bool checked: false
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
color: basicMouseArea.containsMouse || !leftPanel.visible ? "#FFE00A" : "#000000" color: "#FFE00A"
height: 30 height: 30 * scaleRatio
width: height width: height
visible: isMobile visible: isMobile
Image { Image {
width: parent.width * 2/3;
height: width;
anchors.centerIn: parent anchors.centerIn: parent
rotation: !leftPanel.visible ? 180 : 0 source: "../images/menu.png"
source: parent.customDecorations || !leftPanel.visible ? "../images/goToBasicVersionHovered.png" :
"../images/gotoBasicVersion.png"
} }
MouseArea { MouseArea {
@@ -75,6 +77,7 @@ Rectangle {
hoverEnabled: true hoverEnabled: true
anchors.fill: parent anchors.fill: parent
onClicked: { onClicked: {
releaseFocus()
parent.checked = !parent.checked parent.checked = !parent.checked
titleBar.goToBasicVersion(leftPanel.visible) titleBar.goToBasicVersion(leftPanel.visible)
} }

View File

@@ -71,6 +71,12 @@ bool filter::eventFilter(QObject *obj, QEvent *ev) {
m_tabPressed = false; m_tabPressed = false;
QString sks; QString sks;
#ifdef Q_OS_ANDROID
if(ke->key() == Qt::Key_Back) {
qDebug() << "Android back hit";
sks = "android_back";
}
#endif
if(ke->key() == Qt::Key_Control) { if(ke->key() == Qt::Key_Control) {
sks = "Ctrl"; sks = "Ctrl";
#ifdef Q_OS_MAC #ifdef Q_OS_MAC

BIN
images/menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,4 +1,12 @@
#!/bin/bash -e #!/bin/bash -e
# 3 header files required by monero are missing from the IOS SDK. I copied them from iphoneSimulator SDK
# cd /Applications/XCode.app
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/sys/vmmeter.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/sys/
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/netinet/udp_var.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/netinet/
# sudo cp ./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/netinet/ip_var.h ./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/netinet/
if [ -z $BUILD_TYPE ]; then if [ -z $BUILD_TYPE ]; then
BUILD_TYPE=release BUILD_TYPE=release
fi fi
@@ -18,17 +26,17 @@ if [ -z $OPENSSL_ROOT_DIR ]; then
fi fi
echo "Building IOS armv7" echo "Building IOS armv7"
rm -r monero/build rm -r monero/build > /dev/null
mkdir -p monero/build/release mkdir -p monero/build/release
pushd monero/build/release pushd monero/build/release
cmake -D IOS=ON -D ARCH=armv7 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../.. cmake -D IOS=ON -D ARCH=armv7 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
make -j4 && make install make -j4 && make install
popd popd
echo "Building IOS arm64" echo "Building IOS arm64"
rm -r monero/build rm -r monero/build > /dev/null
mkdir -p monero/build/release mkdir -p monero/build/release
pushd monero/build/release pushd monero/build/release
cmake -D IOS=ON -D ARCH=arm64 -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../.. cmake -D IOS=ON -D ARCH=armv8-a -D BOOST_LIBRARYDIR=${BOOST_INCLUDEDIR} -D BOOST_INCLUDEDIR=${BOOST_INCLUDEDIR} -D OPENSSL_INCLUDE_DIR=${OPENSSL_INCLUDE_DIR} -D OPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -D CMAKE_BUILD_TYPE=debug -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="/Users/jacob/crypto/monero-core/monero" ../..
make -j4 && make install make -j4 && make install
popd popd

View File

@@ -32,6 +32,8 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QDebug> #include <QDebug>
#include <QObject> #include <QObject>
#include <QDesktopWidget>
#include <QScreen>
#include "clipboardAdapter.h" #include "clipboardAdapter.h"
#include "filter.h" #include "filter.h"
#include "oscursor.h" #include "oscursor.h"
@@ -168,6 +170,7 @@ int main(int argc, char *argv[])
bool isWindows = false; bool isWindows = false;
bool isIOS = false; bool isIOS = false;
bool isMac = false; bool isMac = false;
bool isAndroid = false;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
isWindows = true; isWindows = true;
QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); QStringList moneroAccountsRootDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
@@ -180,9 +183,42 @@ int main(int argc, char *argv[])
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
isMac = true; isMac = true;
#endif #endif
#ifdef Q_OS_ANDROID
isAndroid = true;
#endif
engine.rootContext()->setContextProperty("isWindows", isWindows); engine.rootContext()->setContextProperty("isWindows", isWindows);
engine.rootContext()->setContextProperty("isIOS", isIOS); engine.rootContext()->setContextProperty("isIOS", isIOS);
engine.rootContext()->setContextProperty("isAndroid", isAndroid);
// screen settings
// Mobile is designed on 128dpi
qreal ref_dpi = 128;
QRect geo = QApplication::desktop()->availableGeometry();
QRect rect = QGuiApplication::primaryScreen()->geometry();
qreal height = qMax(rect.width(), rect.height());
qreal width = qMin(rect.width(), rect.height());
qreal dpi = QGuiApplication::primaryScreen()->logicalDotsPerInch();
qreal physicalDpi = QGuiApplication::primaryScreen()->physicalDotsPerInch();
qreal calculated_ratio = physicalDpi/ref_dpi;
engine.rootContext()->setContextProperty("screenWidth", geo.width());
engine.rootContext()->setContextProperty("screenHeight", geo.height());
#ifdef Q_OS_ANDROID
engine.rootContext()->setContextProperty("scaleRatio", calculated_ratio);
#else
engine.rootContext()->setContextProperty("scaleRatio", 1);
#endif
qDebug() << "available width: " << geo.width();
qDebug() << "available height: " << geo.height();
qDebug() << "devicePixelRatio: " << app.devicePixelRatio();
qDebug() << "screen height: " << height;
qDebug() << "screen width: " << width;
qDebug() << "screen logical dpi: " << dpi;
qDebug() << "screen Physical dpi: " << physicalDpi;
qDebug() << "screen calculated ratio: " << calculated_ratio;
if (!moneroAccountsRootDir.empty()) { if (!moneroAccountsRootDir.empty()) {
QString moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets"; QString moneroAccountsDir = moneroAccountsRootDir.at(0) + "/Monero/wallets";

313
main.qml
View File

@@ -57,7 +57,7 @@ ApplicationWindow {
property bool isNewWallet: false property bool isNewWallet: false
property int restoreHeight:0 property int restoreHeight:0
property bool daemonSynced: false property bool daemonSynced: false
property int maxWindowHeight: (Screen.height < 900)? 720 : 800; property int maxWindowHeight: (isAndroid || isIOS)? screenHeight : (screenHeight < 900)? 720 : 800;
property bool daemonRunning: false property bool daemonRunning: false
property alias toolTip: toolTip property alias toolTip: toolTip
property string walletName property string walletName
@@ -66,8 +66,14 @@ ApplicationWindow {
property int timeToUnlock: 0 property int timeToUnlock: 0
property bool qrScannerEnabled: (typeof builtWithScanner != "undefined") && builtWithScanner property bool qrScannerEnabled: (typeof builtWithScanner != "undefined") && builtWithScanner
property int blocksToSync: 1 property int blocksToSync: 1
property var isMobile: (appWindow.width > 700) ? false : true property var isMobile: (appWindow.width > 700 && !isAndroid) ? false : true
property var cameraUi property var cameraUi
property bool remoteNodeConnected: false
property bool androidCloseTapped: false;
// Default daemon addresses
readonly property string localDaemonAddress : !persistentSettings.testnet ? "localhost:18081" : "localhost:28081"
property string currentDaemonAddress;
property bool startLocalNodeCancelled: false
// true if wallet ever synchronized // true if wallet ever synchronized
property bool walletInitialized : false property bool walletInitialized : false
@@ -164,7 +170,6 @@ ApplicationWindow {
function initialize() { function initialize() {
console.log("initializing..") console.log("initializing..")
walletInitialized = false;
// Use stored log level // Use stored log level
if (persistentSettings.logLevel == 5) if (persistentSettings.logLevel == 5)
@@ -186,7 +191,7 @@ ApplicationWindow {
console.log("Daemon change - closing " + currentWallet) console.log("Daemon change - closing " + currentWallet)
closeWallet(); closeWallet();
currentWallet = undefined currentWallet = undefined
} else { } else if (!walletInitialized) {
// set page to transfer if not changing daemon // set page to transfer if not changing daemon
middlePanel.state = "Transfer"; middlePanel.state = "Transfer";
@@ -194,9 +199,13 @@ ApplicationWindow {
} }
walletManager.setDaemonAddress(persistentSettings.daemon_address)
// Local daemon settings
walletManager.setDaemonAddress(localDaemonAddress)
// wallet already opened with wizard, we just need to initialize it // wallet already opened with wizard, we just need to initialize it
if (typeof wizard.settings['wallet'] !== 'undefined') { if (typeof wizard.m_wallet !== 'undefined') {
console.log("using wizard wallet") console.log("using wizard wallet")
//Set restoreHeight //Set restoreHeight
if(persistentSettings.restore_height > 0){ if(persistentSettings.restore_height > 0){
@@ -204,11 +213,11 @@ ApplicationWindow {
restoreHeight = persistentSettings.restore_height restoreHeight = persistentSettings.restore_height
} }
connectWallet(wizard.settings['wallet']) connectWallet(wizard.m_wallet)
isNewWallet = true isNewWallet = true
// We don't need the wizard wallet any more - delete to avoid conflict with daemon adress change // We don't need the wizard wallet any more - delete to avoid conflict with daemon adress change
delete wizard.settings['wallet'] delete wizard.m_wallet
} else { } else {
var wallet_path = walletPath(); var wallet_path = walletPath();
if(isIOS) if(isIOS)
@@ -236,12 +245,10 @@ ApplicationWindow {
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable); middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
middlePanel.checkPaymentClicked.disconnect(handleCheckPayment); middlePanel.checkPaymentClicked.disconnect(handleCheckPayment);
} }
currentWallet = undefined; currentWallet = undefined;
if (isIOS) { walletManager.closeWallet();
console.log("closing sync - ios")
walletManager.closeWallet();
} else
walletManager.closeWalletAsync();
} }
function connectWallet(wallet) { function connectWallet(wallet) {
@@ -270,14 +277,20 @@ ApplicationWindow {
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable); middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
middlePanel.checkPaymentClicked.connect(handleCheckPayment); middlePanel.checkPaymentClicked.connect(handleCheckPayment);
console.log("initializing with daemon address: ", persistentSettings.daemon_address)
console.log("Recovering from seed: ", persistentSettings.is_recovering) console.log("Recovering from seed: ", persistentSettings.is_recovering)
console.log("restore Height", persistentSettings.restore_height) console.log("restore Height", persistentSettings.restore_height)
// Use saved daemon rpc login settings // Use saved daemon rpc login settings
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword); currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword)
currentWallet.initAsync(persistentSettings.daemon_address, 0, persistentSettings.is_recovering, persistentSettings.restore_height); if(persistentSettings.useRemoteNode)
currentDaemonAddress = persistentSettings.remoteNodeAddress
else
currentDaemonAddress = localDaemonAddress
console.log("initializing with daemon address: ", currentDaemonAddress)
currentWallet.initAsync(currentDaemonAddress, 0, persistentSettings.is_recovering, persistentSettings.restore_height);
} }
function walletPath() { function walletPath() {
@@ -302,7 +315,7 @@ ApplicationWindow {
middlePanel.transferView.updatePriorityDropdown(); middlePanel.transferView.updatePriorityDropdown();
// If wallet isnt connected and no daemon is running - Ask // If wallet isnt connected and no daemon is running - Ask
if(isDaemonLocal() && !walletInitialized && status === Wallet.ConnectionStatus_Disconnected && !daemonManager.running(persistentSettings.testnet)){ if(!isMobile && isDaemonLocal() && !walletInitialized && status === Wallet.ConnectionStatus_Disconnected && !daemonManager.running(persistentSettings.testnet)){
daemonManagerDialog.open(); daemonManagerDialog.open();
} }
// initialize transaction history once wallet is initialized first time; // initialize transaction history once wallet is initialized first time;
@@ -358,10 +371,25 @@ ApplicationWindow {
console.log("New block found - updating history") console.log("New block found - updating history")
currentWallet.history.refresh() currentWallet.history.refresh()
timeToUnlock = currentWallet.history.minutesToUnlock timeToUnlock = currentWallet.history.minutesToUnlock
leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)").arg(timeToUnlock) : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance"); leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)") : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance");
} }
} }
function connectRemoteNode() {
console.log("connecting remote node");
persistentSettings.useRemoteNode = true;
currentWallet.initAsync(persistentSettings.remoteNodeAddress);
remoteNodeConnected = true;
}
function disconnectRemoteNode() {
console.log("disconnecting remote node");
persistentSettings.useRemoteNode = false;
currentDaemonAddress = localDaemonAddress
currentWallet.initAsync(currentDaemonAddress);
remoteNodeConnected = false;
}
function onWalletRefresh() { function onWalletRefresh() {
console.log(">>> wallet refreshed") console.log(">>> wallet refreshed")
@@ -383,6 +411,31 @@ ApplicationWindow {
// Update transfer page status // Update transfer page status
middlePanel.updateStatus(); middlePanel.updateStatus();
// Use remote node while local daemon is syncing
if (persistentSettings.useRemoteNode) {
var localNodeConnected = walletManager.connected;
var localNodeSynced = localNodeConnected && walletManager.localDaemonSynced()
if (!currentWallet.connected() || !localNodeSynced) {
console.log("Using remote node while local node is syncing")
// Connect to remote node if not already connected
if(!remoteNodeConnected) {
connectRemoteNode();
}
//update local daemon sync progress bar
if(localNodeConnected) {
leftPanel.progressBar.updateProgress(walletManager.blockchainHeight(),walletManager.blockchainTargetHeight(), 0, qsTr("Remaining blocks (local node):"));
leftPanel.progressBar.visible = true
} else if (persistentSettings.startLocalNode && !startLocalNodeCancelled) {
daemonManagerDialog.open()
}
// local daemon is synced - use it!
} else if (localNodeSynced && remoteNodeConnected) {
disconnectRemoteNode();
}
}
// Refresh is succesfull if blockchain height > 1 // Refresh is succesfull if blockchain height > 1
if (currentWallet.blockChainHeight() > 1){ if (currentWallet.blockChainHeight() > 1){
@@ -392,9 +445,6 @@ ApplicationWindow {
console.log("Saving wallet after first refresh"); console.log("Saving wallet after first refresh");
currentWallet.store() currentWallet.store()
isNewWallet = false isNewWallet = false
// Update History
currentWallet.history.refresh();
} }
// recovering from seed is finished after first refresh // recovering from seed is finished after first refresh
@@ -403,6 +453,10 @@ ApplicationWindow {
} }
} }
// Update history on every refresh if it's empty
if(currentWallet.history.count == 0)
currentWallet.history.refresh()
onWalletUpdate(); onWalletUpdate();
} }
@@ -462,7 +516,8 @@ ApplicationWindow {
function onWalletMoneyReceived(txId, amount) { function onWalletMoneyReceived(txId, amount) {
// refresh transaction history here // refresh transaction history here
currentWallet.refresh() currentWallet.refresh()
currentWallet.history.refresh() // this will refresh model console.log("Confirmed money found")
// history refresh is handled by walletUpdated
} }
function onWalletUnconfirmedMoneyReceived(txId, amount) { function onWalletUnconfirmedMoneyReceived(txId, amount) {
@@ -473,6 +528,7 @@ ApplicationWindow {
function onWalletMoneySent(txId, amount) { function onWalletMoneySent(txId, amount) {
// refresh transaction history here // refresh transaction history here
console.log("money sent found")
currentWallet.refresh() currentWallet.refresh()
currentWallet.history.refresh() // this will refresh model currentWallet.history.refresh() // this will refresh model
} }
@@ -706,7 +762,7 @@ ApplicationWindow {
", txid: ", txid, ", txid: ", txid,
", txkey: ", txkey); ", txkey: ", txkey);
var result = walletManager.checkPayment(address, txid, txkey, persistentSettings.daemon_address); var result = walletManager.checkPayment(address, txid, txkey, currentDaemonAddress);
var results = result.split("|"); var results = result.split("|");
if (results.length < 4) { if (results.length < 4) {
informationPopup.title = qsTr("Error") + translationManager.emptyString; informationPopup.title = qsTr("Error") + translationManager.emptyString;
@@ -797,7 +853,7 @@ ApplicationWindow {
objectName: "appWindow" objectName: "appWindow"
visible: true visible: true
// width: Screen.width //rightPanelExpanded ? 1269 : 1269 - 300 // width: screenWidth //rightPanelExpanded ? 1269 : 1269 - 300
// height: 900 //300//maxWindowHeight; // height: 900 //300//maxWindowHeight;
color: "#FFFFFF" color: "#FFFFFF"
flags: persistentSettings.customDecorations ? (Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint) : (Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint | Qt.WindowMaximizeButtonHint) flags: persistentSettings.customDecorations ? (Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint) : (Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint | Qt.WindowMaximizeButtonHint)
@@ -892,6 +948,9 @@ ApplicationWindow {
property string daemonPassword: "" property string daemonPassword: ""
property bool transferShowAdvanced: false property bool transferShowAdvanced: false
property string blockchainDataDir: "" property string blockchainDataDir: ""
property bool startLocalNode: true
property bool useRemoteNode: false
property string remoteNodeAddress: ""
} }
// Information dialog // Information dialog
@@ -899,6 +958,8 @@ ApplicationWindow {
// dynamically change onclose handler // dynamically change onclose handler
property var onCloseCallback property var onCloseCallback
id: informationPopup id: informationPopup
anchors.fill: parent
z: parent.z + 1
cancelVisible: false cancelVisible: false
onAccepted: { onAccepted: {
if (onCloseCallback) { if (onCloseCallback) {
@@ -909,6 +970,7 @@ ApplicationWindow {
// Confrirmation aka question dialog // Confrirmation aka question dialog
StandardDialog { StandardDialog {
z: parent.z + 1
id: transactionConfirmationPopup id: transactionConfirmationPopup
onAccepted: { onAccepted: {
close(); close();
@@ -935,7 +997,9 @@ ApplicationWindow {
} }
StandardDialog { StandardDialog {
z: parent.z + 1
id: confirmationDialog id: confirmationDialog
anchors.fill: parent
property var onAcceptedCallback property var onAcceptedCallback
property var onRejectedCallback property var onRejectedCallback
onAccepted: { onAccepted: {
@@ -955,9 +1019,17 @@ ApplicationWindow {
title: "Please choose a file" title: "Please choose a file"
folder: "file://" +moneroAccountsDir folder: "file://" +moneroAccountsDir
nameFilters: [ "Wallet files (*.keys)"] nameFilters: [ "Wallet files (*.keys)"]
sidebarVisible: false
onAccepted: { onAccepted: {
persistentSettings.wallet_path = walletManager.urlToLocalPath(fileDialog.fileUrl) persistentSettings.wallet_path = walletManager.urlToLocalPath(fileDialog.fileUrl)
if(isIOS)
persistentSettings.wallet_path = persistentSettings.wallet_path.replace(moneroAccountsDir,"")
console.log("ÖPPPPNA")
console.log(moneroAccountsDir)
console.log(fileDialog.fileUrl)
console.log(persistentSettings.wallet_path)
initialize(); initialize();
} }
onRejected: { onRejected: {
@@ -967,9 +1039,63 @@ ApplicationWindow {
} }
// Choose blockchain folder
FileDialog {
id: blockchainFileDialog
title: "Please choose a folder"
selectFolder: true
folder: "file://" + persistentSettings.blockchainDataDir
onAccepted: {
var dataDir = walletManager.urlToLocalPath(blockchainFileDialog.fileUrl)
var validator = daemonManager.validateDataDir(dataDir);
if(!validator.valid) {
confirmationDialog.title = qsTr("Warning") + translationManager.emptyString;
confirmationDialog.text = "";
if(validator.readOnly)
confirmationDialog.text += qsTr("Error: Filesystem is read only") + "\n\n"
if(validator.storageAvailable < 20)
confirmationDialog.text += qsTr("Warning: There's only %1 GB available on the device. Blockchain requires ~%30 GB of data.").arg(validator.storageAvailable).arg(15) + "\n\n"
else
confirmationDialog.text += qsTr("Note: There's %1 GB available on the device. Blockchain requires ~%30 GB of data.").arg(validator.storageAvailable).arg(15) + "\n\n"
if(!validator.lmdbExists)
confirmationDialog.text += qsTr("Note: lmdb folder not found. A new folder will be created.") + "\n\n"
confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel")
// Continue
confirmationDialog.onAcceptedCallback = function() {
persistentSettings.blockchainDataDir = dataDir
}
// Cancel
confirmationDialog.onRejectedCallback = function() {
};
confirmationDialog.open()
} else {
persistentSettings.blockchainDataDir = dataDir
}
delete validator;
}
onRejected: {
console.log("data dir selection canceled")
}
}
PasswordDialog { PasswordDialog {
id: passwordDialog id: passwordDialog
visible: false
z: parent.z + 1
anchors.fill: parent
onAccepted: { onAccepted: {
appWindow.initialize(); appWindow.initialize();
} }
@@ -989,10 +1115,42 @@ ApplicationWindow {
} }
} }
PasswordDialog {
id: settingsPasswordDialog
z: parent.z + 1
visible:false
anchors.fill: parent
onAccepted: {
if(appWindow.password === settingsPasswordDialog.password){
if(currentWallet.seedLanguage == "") {
console.log("No seed language set. Using English as default");
currentWallet.setSeedLanguage("English");
}
// Load keys page
middlePanel.state = "Keys"
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password");
informationPopup.open()
informationPopup.onCloseCallback = function() {
settingsPasswordDialog.open()
}
}
settingsPasswordDialog.password = ""
}
onRejected: {
appWindow.showPageRequest("Settings");
}
}
DaemonManagerDialog { DaemonManagerDialog {
id: daemonManagerDialog id: daemonManagerDialog
onRejected: { onRejected: {
loadPage("Settings"); loadPage("Settings");
startLocalNodeCancelled = true
} }
} }
@@ -1001,8 +1159,8 @@ ApplicationWindow {
id: splash id: splash
width: appWindow.width / 1.5 width: appWindow.width / 1.5
height: appWindow.height / 2 height: appWindow.height / 2
x: (appWindow.width - width) / 2 + appWindow.x x: (appWindow.width - width) / 2
y: (appWindow.height - height) / 2 + appWindow.y y: (appWindow.height - height) / 2
messageText: qsTr("Please wait...") messageText: qsTr("Please wait...")
} }
@@ -1020,14 +1178,15 @@ ApplicationWindow {
PropertyChanges { target: middlePanel; visible: false } PropertyChanges { target: middlePanel; visible: false }
PropertyChanges { target: titleBar; basicButtonVisible: false } PropertyChanges { target: titleBar; basicButtonVisible: false }
PropertyChanges { target: wizard; visible: true } PropertyChanges { target: wizard; visible: true }
PropertyChanges { target: appWindow; width: (Screen.width < 930)? Screen.width : 930; } PropertyChanges { target: appWindow; width: (screenWidth < 930 || isAndroid || isIOS)? screenWidth : 930; }
PropertyChanges { target: appWindow; height: maxWindowHeight; } PropertyChanges { target: appWindow; height: maxWindowHeight; }
PropertyChanges { target: resizeArea; visible: false } PropertyChanges { target: resizeArea; visible: true }
PropertyChanges { target: titleBar; maximizeButtonVisible: false } PropertyChanges { target: titleBar; maximizeButtonVisible: false }
// PropertyChanges { target: frameArea; blocked: true } // PropertyChanges { target: frameArea; blocked: true }
PropertyChanges { target: titleBar; visible: false } PropertyChanges { target: titleBar; visible: false }
PropertyChanges { target: titleBar; y: 0 } PropertyChanges { target: titleBar; y: 0 }
PropertyChanges { target: titleBar; title: qsTr("Program setup wizard") + translationManager.emptyString } PropertyChanges { target: titleBar; title: qsTr("Program setup wizard") + translationManager.emptyString }
PropertyChanges { target: mobileHeader; visible: false }
}, State { }, State {
name: "normal" name: "normal"
PropertyChanges { target: leftPanel; visible: (isMobile)? false : true } PropertyChanges { target: leftPanel; visible: (isMobile)? false : true }
@@ -1035,7 +1194,7 @@ ApplicationWindow {
PropertyChanges { target: middlePanel; visible: true } PropertyChanges { target: middlePanel; visible: true }
PropertyChanges { target: titleBar; basicButtonVisible: true } PropertyChanges { target: titleBar; basicButtonVisible: true }
PropertyChanges { target: wizard; visible: false } PropertyChanges { target: wizard; visible: false }
PropertyChanges { target: appWindow; width: (Screen.width < 969)? Screen.width : 969 } //rightPanelExpanded ? 1269 : 1269 - 300; PropertyChanges { target: appWindow; width: (screenWidth < 969 || isAndroid || isIOS)? screenWidth : 969 } //rightPanelExpanded ? 1269 : 1269 - 300;
PropertyChanges { target: appWindow; height: maxWindowHeight; } PropertyChanges { target: appWindow; height: maxWindowHeight; }
PropertyChanges { target: resizeArea; visible: true } PropertyChanges { target: resizeArea; visible: true }
PropertyChanges { target: titleBar; maximizeButtonVisible: true } PropertyChanges { target: titleBar; maximizeButtonVisible: true }
@@ -1043,6 +1202,7 @@ ApplicationWindow {
PropertyChanges { target: titleBar; visible: true } PropertyChanges { target: titleBar; visible: true }
// PropertyChanges { target: titleBar; y: 0 } // PropertyChanges { target: titleBar; y: 0 }
PropertyChanges { target: titleBar; title: qsTr("Monero") + translationManager.emptyString } PropertyChanges { target: titleBar; title: qsTr("Monero") + translationManager.emptyString }
PropertyChanges { target: mobileHeader; visible: isMobile ? true : false }
} }
] ]
@@ -1051,7 +1211,7 @@ ApplicationWindow {
visible: isMobile visible: isMobile
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
height: visible? 65 : 0 height: visible? 65 * scaleRatio : 0
} }
LeftPanel { LeftPanel {
@@ -1068,6 +1228,7 @@ ApplicationWindow {
onMiningClicked: {middlePanel.state = "Mining"; if(isMobile) hideMenu()} onMiningClicked: {middlePanel.state = "Mining"; if(isMobile) hideMenu()}
onSignClicked: {middlePanel.state = "Sign"; if(isMobile) hideMenu()} onSignClicked: {middlePanel.state = "Sign"; if(isMobile) hideMenu()}
onSettingsClicked: {middlePanel.state = "Settings"; if(isMobile) hideMenu()} onSettingsClicked: {middlePanel.state = "Settings"; if(isMobile) hideMenu()}
onKeysClicked: {settingsPasswordDialog.open(); if(isMobile) hideMenu()}
} }
RightPanel { RightPanel {
@@ -1094,22 +1255,6 @@ ApplicationWindow {
visible: false visible: false
} }
// MouseArea {
// id: frameArea
// property bool blocked: false
// anchors.top: parent.top
// anchors.left: parent.left
// anchors.right: parent.right
// height: 30
// z: 1
// hoverEnabled: true
// propagateComposedEvents: true
// onPressed: mouse.accepted = false
// onReleased: mouse.accepted = false
// onMouseXChanged: titleBar.mouseX = mouseX
// onContainsMouseChanged: titleBar.containsMouse = containsMouse
// }
SequentialAnimation { SequentialAnimation {
id: goToBasicAnimation id: goToBasicAnimation
// PropertyAction { // PropertyAction {
@@ -1324,7 +1469,7 @@ ApplicationWindow {
y: 6 y: 6
lineHeight: 0.7 lineHeight: 0.7
font.family: "Arial" font.family: "Arial"
font.pixelSize: 12 font.pixelSize: 12 * scaleRatio
color: "#FFFFFF" color: "#FFFFFF"
} }
} }
@@ -1335,11 +1480,70 @@ ApplicationWindow {
} }
} }
// TODO: Make the callback dynamic
Timer {
id: statusMessageTimer
interval: 5;
running: false;
repeat: false
onTriggered: resetAndroidClose()
triggeredOnStart: false
}
Rectangle {
id: statusMessage
z: 99
visible: false
property alias text: statusMessageText.text
anchors.bottom: parent.bottom
width: statusMessageText.contentWidth + 20 * scaleRatio
anchors.horizontalCenter: parent.horizontalCenter
color: "black"
height: 40 * scaleRatio
Text {
id: statusMessageText
anchors.fill: parent
anchors.margins: 10 * scaleRatio
font.pixelSize: 14 * scaleRatio
color: "white"
}
}
function resetAndroidClose() {
console.log("resetting android close");
androidCloseTapped = false;
statusMessage.visible = false
}
function showStatusMessage(msg,timeout) {
console.log("showing status message")
statusMessageTimer.interval = timeout * 1000;
statusMessageTimer.start()
statusMessageText.text = msg;
statusMessage.visible = true
}
onClosing: { onClosing: {
close.accepted = false;
console.log("blocking close event");
if(isAndroid) {
console.log("blocking android exit");
if(qrScannerEnabled)
cameraUi.state = "Stopped"
if(!androidCloseTapped) {
androidCloseTapped = true;
appWindow.showStatusMessage(qsTr("Tap again to close..."),3)
// first close
return;
}
}
// If daemon is running - prompt user before exiting // If daemon is running - prompt user before exiting
if(typeof daemonManager != "undefined" && daemonManager.running(persistentSettings.testnet)) { if(typeof daemonManager != "undefined" && daemonManager.running(persistentSettings.testnet)) {
close.accepted = false;
// Show confirmation dialog // Show confirmation dialog
confirmationDialog.title = qsTr("Daemon is running") + translationManager.emptyString; confirmationDialog.title = qsTr("Daemon is running") + translationManager.emptyString;
@@ -1363,6 +1567,7 @@ ApplicationWindow {
} }
function closeAccepted(){ function closeAccepted(){
console.log("close accepted");
// Close wallet non async on exit // Close wallet non async on exit
daemonManager.exit(); daemonManager.exit();
walletManager.closeWallet(); walletManager.closeWallet();
@@ -1407,4 +1612,14 @@ ApplicationWindow {
return false return false
} }
function releaseFocus() {
// Workaround to release focus from textfield when scrolling (https://bugreports.qt.io/browse/QTBUG-34867)
if(isAndroid) {
console.log("releasing focus")
middlePanel.focus = true
middlePanel.focus = false
}
}
} }

View File

@@ -86,7 +86,7 @@ ios:arm64 {
LIBS += \ LIBS += \
-L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \ -L$$PWD/../ofxiOSBoost/build/libs/boost/lib/arm64 \
} }
!ios { !ios:!android {
LIBS += -L$$WALLET_ROOT/lib \ LIBS += -L$$WALLET_ROOT/lib \
-lwallet_merged \ -lwallet_merged \
-lepee \ -lepee \
@@ -95,6 +95,17 @@ LIBS += -L$$WALLET_ROOT/lib \
-lreadline \ -lreadline \
} }
android {
message("Host is Android")
LIBS += -L$$WALLET_ROOT/lib \
-lwallet_merged \
-lepee \
-lunbound \
-leasylogging
}
ios { ios {
message("Host is IOS") message("Host is IOS")
@@ -105,7 +116,8 @@ ios {
LIBS += -L$$WALLET_ROOT/lib-ios \ LIBS += -L$$WALLET_ROOT/lib-ios \
-lwallet_merged \ -lwallet_merged \
-lepee \ -lepee \
-lunbound -lunbound \
-leasylogging
LIBS+= \ LIBS+= \
-L$$PWD/../OpenSSL-for-iPhone/lib \ -L$$PWD/../OpenSSL-for-iPhone/lib \

View File

@@ -33,167 +33,106 @@ import moneroComponents.AddressBook 1.0
import moneroComponents.AddressBookModel 1.0 import moneroComponents.AddressBookModel 1.0
Rectangle { Rectangle {
color: "#F0EEEE"
id: root id: root
color: "#F0EEEE"
property var model property var model
Text { ColumnLayout {
id: newEntryText anchors.margins: 17 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.leftMargin: 17 anchors.right: parent.right
anchors.topMargin: 17 spacing: 10 * scaleRatio
elide: Text.ElideRight Label {
font.family: "Arial" id: addressLabel
font.pixelSize: 18 anchors.left: parent.left
color: "#4A4949" text: qsTr("Address") + translationManager.emptyString
text: qsTr("Add new entry") + translationManager.emptyString
}
Label {
id: addressLabel
anchors.left: parent.left
anchors.top: newEntryText.bottom
anchors.leftMargin: 17
anchors.topMargin: 17
text: qsTr("Address") + translationManager.emptyString
fontSize: 14
}
StandardButton {
id: qrfinderButton
anchors.left: parent.left
anchors.leftMargin: 17
anchors.topMargin: 5
anchors.top: addressLabel.bottom
text: qsTr("QRCODE") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
visible : appWindow.qrScannerEnabled
enabled : visible
width: visible ? 60 : 0
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
} }
}
LineEdit { RowLayout {
id: addressLine StandardButton {
anchors.left: qrfinderButton.right id: qrfinderButton
anchors.right: parent.right text: qsTr("Qr Code") + translationManager.emptyString
anchors.top: addressLabel.bottom shadowReleasedColor: "#FF4304"
anchors.rightMargin: 17 shadowPressedColor: "#B32D00"
anchors.topMargin: 5 releasedColor: "#FF6C3C"
error: true; pressedColor: "#FF4304"
placeholderText: qsTr("4...") + translationManager.emptyString visible : appWindow.qrScannerEnabled
} enabled : visible
width: visible ? 60 * scaleRatio : 0
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
}
}
Label { LineEdit {
id: paymentIdLabel Layout.fillWidth: true;
anchors.left: parent.left id: addressLine
anchors.top: addressLine.bottom error: true;
anchors.leftMargin: 17 placeholderText: qsTr("4...") + translationManager.emptyString
anchors.topMargin: 17 }
text: qsTr("Payment ID <font size='2'>(Optional)</font>") + translationManager.emptyString }
fontSize: 14
}
LineEdit { Label {
id: paymentIdLine id: paymentIdLabel
anchors.left: parent.left text: qsTr("Payment ID <font size='2'>(Optional)</font>") + translationManager.emptyString
anchors.right: parent.right tipText: qsTr("<b>Payment ID</b><br/><br/>A unique user name used in<br/>the address book. It is not a<br/>transfer of information sent<br/>during the transfer")
anchors.top: paymentIdLabel.bottom + translationManager.emptyString
anchors.leftMargin: 17 }
anchors.rightMargin: 17
anchors.topMargin: 5
placeholderText: qsTr("Paste 64 hexadecimal characters") + translationManager.emptyString
}
Label { LineEdit {
id: descriptionLabel id: paymentIdLine
anchors.left: parent.left Layout.fillWidth: true;
anchors.top: paymentIdLine.bottom placeholderText: qsTr("Paste 64 hexadecimal characters") + translationManager.emptyString
anchors.leftMargin: 17 }
anchors.topMargin: 17
text: qsTr("Description <font size='2'>(Optional)</font>") + translationManager.emptyString
fontSize: 14
}
LineEdit { Label {
id: descriptionLine id: descriptionLabel
anchors.left: parent.left text: qsTr("Description <font size='2'>(Optional)</font>") + translationManager.emptyString
anchors.right: parent.right }
anchors.top: descriptionLabel.bottom
anchors.leftMargin: 17 LineEdit {
anchors.rightMargin: 17 id: descriptionLine
anchors.topMargin: 5 Layout.fillWidth: true;
placeholderText: qsTr("Give this entry a name or description") + translationManager.emptyString placeholderText: qsTr("Give this entry a name or description") + translationManager.emptyString
} }
RowLayout { RowLayout {
id: addButton id: addButton
anchors.left: parent.left Layout.bottomMargin: 17 * scaleRatio
anchors.top: descriptionLine.bottom StandardButton {
anchors.leftMargin: 17 shadowReleasedColor: "#FF4304"
anchors.topMargin: 17 shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Add") + translationManager.emptyString
enabled: checkInformation(addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
StandardButton { onClicked: {
shadowReleasedColor: "#FF4304" if (!currentWallet.addressBook.addRow(addressLine.text.trim(), paymentIdLine.text.trim(), descriptionLine.text)) {
shadowPressedColor: "#B32D00" informationPopup.title = qsTr("Error") + translationManager.emptyString;
releasedColor: "#FF6C3C" // TODO: check currentWallet.addressBook.errorString() instead.
pressedColor: "#FF4304" if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address)
text: qsTr("Add") + translationManager.emptyString informationPopup.text = qsTr("Invalid address") + translationManager.emptyString
enabled: checkInformation(addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet) else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id)
informationPopup.text = currentWallet.addressBook.errorString()
else
informationPopup.text = qsTr("Can't create entry") + translationManager.emptyString
onClicked: { informationPopup.onCloseCallback = null
if (!currentWallet.addressBook.addRow(addressLine.text.trim(), paymentIdLine.text.trim(), descriptionLine.text)) { informationPopup.open();
informationPopup.title = qsTr("Error") + translationManager.emptyString; } else {
// TODO: check currentWallet.addressBook.errorString() instead. addressLine.text = "";
if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address) paymentIdLine.text = "";
informationPopup.text = qsTr("Invalid address") + translationManager.emptyString descriptionLine.text = "";
else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id) }
informationPopup.text = currentWallet.addressBook.errorString()
else
informationPopup.text = qsTr("Can't create entry") + translationManager.emptyString
informationPopup.onCloseCallback = null
informationPopup.open();
} else {
addressLine.text = "";
paymentIdLine.text = "";
descriptionLine.text = "";
} }
} }
} }
}
Item {
id: expandItem
property bool expanded: false
anchors.right: parent.right
anchors.bottom: tableRect.top
width: 34
height: 34
Image {
anchors.centerIn: parent
source: "../images/expandTable.png"
rotation: parent.expanded ? 180 : 0
}
MouseArea {
anchors.fill: parent
onClicked: parent.expanded = !parent.expanded
}
} }
Rectangle { Rectangle {
@@ -201,8 +140,7 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
height: expandItem.expanded ? parent.height - newEntryText.y - newEntryText.height - 17 : height: parent.height - addButton.y - addButton.height - 36 * scaleRatio
parent.height - addButton.y - addButton.height - 17
color: "#FFFFFF" color: "#FFFFFF"
Behavior on height { Behavior on height {
@@ -217,44 +155,6 @@ Rectangle {
color: "#DBDBDB" color: "#DBDBDB"
} }
ListModel {
id: columnsModel
// ListElement { columnName: qsTr("Address") + translationManager.emptyString; columnWidth: 148 }
// ListElement { columnName: qsTr("Payment ID") + translationManager.emptyString; columnWidth: 148 }
// ListElement { columnName: qsTr("Description") + translationManager.emptyString; columnWidth: 148 }
//
}
TableHeader {
id: header
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 17
anchors.leftMargin: 14
anchors.rightMargin: 14
dataModel: columnsModel
onSortRequest: console.log("column: " + column + " desc: " + desc)
}
ListModel {
id: testModel
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: ""; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "Client from Australia" }
ListElement { paymentId: ""; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; description: "" }
}
Scroll { Scroll {
id: flickableScroll id: flickableScroll
anchors.right: table.right anchors.right: table.right
@@ -268,7 +168,7 @@ Rectangle {
id: table id: table
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: header.bottom anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.leftMargin: 14 anchors.leftMargin: 14
anchors.rightMargin: 14 anchors.rightMargin: 14

View File

@@ -80,7 +80,7 @@ Rectangle {
} }
onModelChanged: { onModelChanged: {
if (typeof model !== 'undefined') { if (typeof model !== 'undefined' && model != null) {
selectedAmount.text = getSelectedAmount() selectedAmount.text = getSelectedAmount()
@@ -146,30 +146,6 @@ Rectangle {
fontSize: 14 fontSize: 14
} }
// Filter by Address input (senseless, removing)
/*
Label {
id: addressLabel
anchors.left: parent.left
anchors.top: filterHeaderText.bottom
anchors.leftMargin: 17
anchors.topMargin: 17
text: qsTr("Address")
fontSize: 14
}
LineEdit {
id: addressLine
anchors.left: parent.left
anchors.right: parent.right
anchors.top: addressLabel.bottom
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 5
}
*/
// Filter by string // Filter by string
LineEdit { LineEdit {
visible: !isMobile visible: !isMobile
@@ -488,7 +464,7 @@ Rectangle {
ListModel { ListModel {
id: columnsModel id: columnsModel
property int pidWidth: 127 * scaleRatio
ListElement { columnName: "Payment ID"; columnWidth: 127 } ListElement { columnName: "Payment ID"; columnWidth: 127 }
ListElement { columnName: "Date"; columnWidth: 100 } ListElement { columnName: "Date"; columnWidth: 100 }
ListElement { columnName: "Block height"; columnWidth: 150 } ListElement { columnName: "Block height"; columnWidth: 150 }
@@ -498,12 +474,13 @@ Rectangle {
TableHeader { TableHeader {
id: header id: header
visible: !isMobile
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 17 anchors.topMargin: 17 * scaleRatio
anchors.leftMargin: 14 anchors.leftMargin: 14 * scaleRatio
anchors.rightMargin: 14 anchors.rightMargin: 14 * scaleRatio
dataModel: columnsModel dataModel: columnsModel
offset: 20 offset: 20
onSortRequest: { onSortRequest: {
@@ -532,8 +509,9 @@ Rectangle {
Scroll { Scroll {
id: flickableScroll id: flickableScroll
visible: !isMobile
anchors.right: table.right anchors.right: table.right
anchors.rightMargin: -14 anchors.rightMargin: !isMobile ? -14 * scaleRatio : 0
anchors.top: table.top anchors.top: table.top
anchors.bottom: table.bottom anchors.bottom: table.bottom
flickable: table flickable: table
@@ -541,19 +519,37 @@ Rectangle {
HistoryTable { HistoryTable {
id: table id: table
visible: !isMobile
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: header.bottom anchors.top: header.bottom
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.leftMargin: 14 anchors.leftMargin: 14 * scaleRatio
anchors.rightMargin: 14 anchors.rightMargin: 14 * scaleRatio
onContentYChanged: flickableScroll.flickableContentYChanged() onContentYChanged: flickableScroll.flickableContentYChanged()
model: root.model model: !isMobile ? root.model : null
addressBookModel: null
}
HistoryTableMobile {
id: tableMobile
visible: isMobile
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
onContentYChanged: flickableScroll.flickableContentYChanged()
model: isMobile ? root.model : null
addressBookModel: null addressBookModel: null
} }
} }
function onPageCompleted() { function onPageCompleted() {
table.addressBookModel = appWindow.currentWallet ? appWindow.currentWallet.addressBookModel : null if(currentWallet != null && typeof currentWallet.history !== "undefined" ) {
currentWallet.history.refresh()
table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null
transactionTypeDropdown.update()
}
} }
} }

221
pages/Keys.qml Normal file
View File

@@ -0,0 +1,221 @@
// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.2
import "../version.js" as Version
import "../components"
import moneroComponents.Clipboard 1.0
Rectangle {
property bool viewOnly: false
id: page
color: "#F0EEEE"
Clipboard { id: clipboard }
ColumnLayout {
id: mainLayout
anchors.margins: 17 * scaleRatio
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
spacing: 20 * scaleRatio
Layout.fillWidth: true
//! Manage wallet
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: qsTr("Mnemonic seed") + translationManager.emptyString
}
Rectangle {
Layout.fillWidth: true
height: 1
color: "#DEDEDE"
}
TextEdit {
id: seedText
wrapMode: TextEdit.Wrap
Layout.fillWidth: true;
font.pixelSize: 14 * scaleRatio
readOnly: true
MouseArea {
anchors.fill: parent
onClicked: {
appWindow.showStatusMessage(qsTr("Double tap to copy"),3)
}
onDoubleClicked: {
parent.selectAll()
parent.copy()
parent.deselect()
console.log("copied to clipboard");
appWindow.showStatusMessage(qsTr("Seed copied to clipboard"),3)
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: qsTr("Keys") + translationManager.emptyString
}
Rectangle {
Layout.fillWidth: true
height: 1
color: "#DEDEDE"
}
TextEdit {
id: keysText
wrapMode: TextEdit.Wrap
Layout.fillWidth: true;
font.pixelSize: 14 * scaleRatio
textFormat: TextEdit.RichText
readOnly: true
MouseArea {
anchors.fill: parent
onClicked: {
appWindow.showStatusMessage(qsTr("Double tap to copy"),3)
}
onDoubleClicked: {
parent.selectAll()
parent.copy()
parent.deselect()
console.log("copied to clipboard");
appWindow.showStatusMessage(qsTr("Keys copied to clipboard"),3)
}
}
}
}
ColumnLayout {
Layout.fillWidth: true
Label {
Layout.fillWidth: true
text: qsTr("Export wallet") + translationManager.emptyString
}
Rectangle {
Layout.fillWidth: true
height: 1
color: "#DEDEDE"
}
RowLayout {
StandardButton {
enabled: !fullWalletQRCode.visible
id: showFullQr
text: qsTr("Spendable Wallet") + translationManager.emptyString
onClicked: {
viewOnlyQRCode.visible = false
}
}
StandardButton {
enabled: fullWalletQRCode.visible
id: showViewOnlyQr
text: qsTr("View Only Wallet") + translationManager.emptyString
onClicked: {
viewOnlyQRCode.visible = true
}
}
Layout.bottomMargin: 30 * scaleRatio
}
Image {
visible: !viewOnlyQRCode.visible
id: fullWalletQRCode
Layout.fillWidth: true
Layout.minimumHeight: 180 * scaleRatio
smooth: false
fillMode: Image.PreserveAspectFit
}
Image {
visible: false
id: viewOnlyQRCode
Layout.fillWidth: true
Layout.minimumHeight: 180 * scaleRatio
smooth: false
fillMode: Image.PreserveAspectFit
}
Text {
Layout.fillWidth: true
font.bold: true
font.pixelSize: 16 * scaleRatio
text: (viewOnlyQRCode.visible) ? qsTr("View Only Wallet") + translationManager.emptyString : qsTr("Spendable Wallet") + translationManager.emptyString
horizontalAlignment: Text.AlignHCenter
}
}
}
// fires on every page load
function onPageCompleted() {
console.log("keys page loaded");
keysText.text = "<b>" + qsTr("Secret view key") + ":</b> " + currentWallet.secretViewKey
keysText.text += "<br><br><b>" + qsTr("Public view key") + ":</b> " + currentWallet.publicViewKey
keysText.text += (!currentWallet.viewOnly) ? "<br><br><b>" + qsTr("Secret spend key") + ":</b> " + currentWallet.secretSpendKey : ""
keysText.text += "<br><br><b>" + qsTr("Public spend key") + ":</b> " + currentWallet.publicSpendKey
seedText.text = currentWallet.seed
if(typeof currentWallet != "undefined") {
viewOnlyQRCode.source = "image://qrcode/monero:" + currentWallet.address+"?secret_view_key="+currentWallet.secretViewKey+"&restore_height="+currentWallet.restoreHeight
fullWalletQRCode.source = viewOnlyQRCode.source +"&secret_spend_key="+currentWallet.secretSpendKey
if(currentWallet.viewOnly) {
viewOnlyQRCode.visible = true
showFullQr.visible = false
showViewOnlyQr.visible = false
seedText.text = qsTr("(View Only Wallet - No mnemonic seed available)") + translationManager.emptyString
}
}
}
// fires only once
Component.onCompleted: {
}
}

View File

@@ -37,6 +37,15 @@ Rectangle {
color: "#F0EEEE" color: "#F0EEEE"
property var currentHashRate: 0 property var currentHashRate: 0
function isDaemonLocal() {
if (appWindow.currentDaemonAddress === "")
return false
var daemonHost = appWindow.currentDaemonAddress.split(":")[0]
if (daemonHost === "127.0.0.1" || daemonHost === "localhost")
return true
return false
}
/* main layout */ /* main layout */
ColumnLayout { ColumnLayout {
id: mainLayout id: mainLayout

View File

@@ -169,24 +169,23 @@ Rectangle {
ColumnLayout { ColumnLayout {
id: mainLayout id: mainLayout
anchors.margins: (isMobile)? 17 : 40 anchors.margins: (isMobile)? 17 : 40
anchors.topMargin: 40 anchors.topMargin: 40 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
spacing: 20 spacing: 20 * scaleRatio
property int labelWidth: 120 property int labelWidth: 120 * scaleRatio
property int editWidth: 400 property int editWidth: 400 * scaleRatio
property int lineEditFontSize: 12 property int lineEditFontSize: 12 * scaleRatio
property int qrCodeSize: 240 property int qrCodeSize: 240 * scaleRatio
ColumnLayout { ColumnLayout {
id: addressRow id: addressRow
Label { Label {
id: addressLabel id: addressLabel
fontSize: 14
text: qsTr("Address") + translationManager.emptyString text: qsTr("Address") + translationManager.emptyString
width: mainLayout.labelWidth width: mainLayout.labelWidth
} }
@@ -206,6 +205,7 @@ Rectangle {
if (addressLine.text.length > 0) { if (addressLine.text.length > 0) {
console.log(addressLine.text + " copied to clipboard") console.log(addressLine.text + " copied to clipboard")
clipboard.setText(addressLine.text) clipboard.setText(addressLine.text)
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3)
} }
} }
} }
@@ -218,7 +218,6 @@ Rectangle {
Label { Label {
Layout.columnSpan: 2 Layout.columnSpan: 2
id: paymentIdLabel id: paymentIdLabel
fontSize: 14
text: qsTr("Payment ID") + translationManager.emptyString text: qsTr("Payment ID") + translationManager.emptyString
width: mainLayout.labelWidth width: mainLayout.labelWidth
} }
@@ -239,6 +238,7 @@ Rectangle {
onClicked: { onClicked: {
if (paymentIdLine.text.length > 0) { if (paymentIdLine.text.length > 0) {
clipboard.setText(paymentIdLine.text) clipboard.setText(paymentIdLine.text)
appWindow.showStatusMessage(qsTr("Payment ID copied to clipboard"),3)
} }
} }
} }
@@ -246,7 +246,6 @@ Rectangle {
StandardButton { StandardButton {
id: generatePaymentId id: generatePaymentId
width: 80
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
@@ -258,7 +257,6 @@ Rectangle {
StandardButton { StandardButton {
id: clearPaymentId id: clearPaymentId
enabled: !!paymentIdLine.text enabled: !!paymentIdLine.text
width: 80
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
@@ -272,7 +270,6 @@ Rectangle {
id: integratedAddressRow id: integratedAddressRow
Label { Label {
id: integratedAddressLabel id: integratedAddressLabel
fontSize: 14
text: qsTr("Integrated address") + translationManager.emptyString text: qsTr("Integrated address") + translationManager.emptyString
width: mainLayout.labelWidth width: mainLayout.labelWidth
} }
@@ -294,6 +291,7 @@ Rectangle {
onClicked: { onClicked: {
if (integratedAddressLine.text.length > 0) { if (integratedAddressLine.text.length > 0) {
clipboard.setText(integratedAddressLine.text) clipboard.setText(integratedAddressLine.text)
appWindow.showStatusMessage(qsTr("Integrated address copied to clipboard"),3)
} }
} }
} }
@@ -305,7 +303,6 @@ Rectangle {
id: amountRow id: amountRow
Label { Label {
id: amountLabel id: amountLabel
fontSize: 14
text: qsTr("Amount") + translationManager.emptyString text: qsTr("Amount") + translationManager.emptyString
width: mainLayout.labelWidth width: mainLayout.labelWidth
} }
@@ -330,10 +327,9 @@ Rectangle {
RowLayout { RowLayout {
id: trackingRow id: trackingRow
visible: !isAndroid && !isIOS
Label { Label {
id: trackingLabel id: trackingLabel
fontSize: 14
textFormat: Text.RichText textFormat: Text.RichText
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\ text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
Tracking <font size='2'> (</font><a href='#'>help</a><font size='2'>)</font>") Tracking <font size='2'> (</font><a href='#'>help</a><font size='2'>)</font>")
@@ -392,33 +388,33 @@ Rectangle {
} }
} }
} }
ColumnLayout {
Menu { Menu {
id: qrMenu id: qrMenu
title: "QrCode" title: "QrCode"
MenuItem { MenuItem {
text: qsTr("Save As") + translationManager.emptyString; text: qsTr("Save As") + translationManager.emptyString;
onTriggered: qrFileDialog.open() onTriggered: qrFileDialog.open()
} }
} }
Image { Image {
id: qrCode id: qrCode
anchors.margins: 50 anchors.margins: 50 * scaleRatio
anchors.top: trackingRow.bottom Layout.fillWidth: true
Layout.fillWidth: true Layout.minimumHeight: mainLayout.qrCodeSize
Layout.minimumHeight: mainLayout.qrCodeSize smooth: false
smooth: false fillMode: Image.PreserveAspectFit
fillMode: Image.PreserveAspectFit source: "image://qrcode/" + makeQRCodeString()
source: "image://qrcode/" + makeQRCodeString() MouseArea {
MouseArea { anchors.fill: parent
anchors.fill: parent acceptedButtons: Qt.RightButton
acceptedButtons: Qt.RightButton onClicked: {
onClicked: { if (mouse.button == Qt.RightButton)
if (mouse.button == Qt.RightButton) qrMenu.popup()
qrMenu.popup() }
onPressAndHold: qrFileDialog.open()
} }
onPressAndHold: qrFileDialog.open()
} }
} }
} }

View File

@@ -38,7 +38,6 @@ import "../components"
import moneroComponents.Clipboard 1.0 import moneroComponents.Clipboard 1.0
Rectangle { Rectangle {
property var daemonAddress
property bool viewOnly: false property bool viewOnly: false
id: page id: page
@@ -48,20 +47,15 @@ Rectangle {
function initSettings() { function initSettings() {
//runs on every page load //runs on every page load
// Daemon settings
daemonAddress = persistentSettings.daemon_address.split(":");
console.log("address: " + persistentSettings.daemon_address)
// try connecting to daemon
} }
ColumnLayout { ColumnLayout {
id: mainLayout id: mainLayout
anchors.margins: 17 anchors.margins: 17 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
spacing: 10 spacing: 10 * scaleRatio
//! Manage wallet //! Manage wallet
RowLayout { RowLayout {
@@ -70,8 +64,7 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
color: "#4A4949" color: "#4A4949"
text: qsTr("Manage wallet") + translationManager.emptyString text: qsTr("Manage wallet") + translationManager.emptyString
fontSize: 16 Layout.topMargin: 10 * scaleRatio
Layout.topMargin: 10
} }
} }
@@ -82,7 +75,7 @@ Rectangle {
} }
GridLayout { GridLayout {
columns: (isMobile)? 2 : 4 columns: (isMobile)? 1 : 4
StandardButton { StandardButton {
id: closeWalletButton id: closeWalletButton
text: qsTr("Close wallet") + translationManager.emptyString text: qsTr("Close wallet") + translationManager.emptyString
@@ -111,18 +104,6 @@ Rectangle {
} }
} }
StandardButton {
id: showSeedButton
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Show seed & keys") + translationManager.emptyString
onClicked: {
settingsPasswordDialog.open();
}
}
/* Rescan cache - Disabled until we know it's needed /* Rescan cache - Disabled until we know it's needed
StandardButton { StandardButton {
@@ -160,6 +141,7 @@ Rectangle {
*/ */
StandardButton { StandardButton {
id: rescanSpentButton id: rescanSpentButton
enabled: !persistentSettings.useRemoteNode
text: qsTr("Rescan wallet balance") + translationManager.emptyString text: qsTr("Rescan wallet balance") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -184,16 +166,53 @@ Rectangle {
} }
} }
RowLayout {
StandardButton {
id: remoteDisconnect
enabled: persistentSettings.useRemoteNode
Layout.fillWidth: false
text: qsTr("Local Node") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
onClicked: {
appWindow.disconnectRemoteNode();
}
}
StandardButton {
id: remoteConnect
enabled: !persistentSettings.useRemoteNode
Layout.fillWidth: false
text: qsTr("Remote Node") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
onClicked: {
appWindow.connectRemoteNode();
}
}
}
//! Manage daemon //! Manage daemon
RowLayout { RowLayout {
visible: !isMobile
Layout.topMargin: 20
Label { Label {
id: manageDaemonLabel id: manageDaemonLabel
Layout.fillWidth: true
color: "#4A4949" color: "#4A4949"
text: qsTr("Manage daemon") + translationManager.emptyString text: qsTr("Manage Daemon") + translationManager.emptyString
fontSize: 16 }
anchors.topMargin: 30
Layout.topMargin: 30 CheckBox {
id: daemonAdvanced
Layout.leftMargin: 15
text: qsTr("Show advanced") + translationManager.emptyString
checkedIcon: "../images/checkedVioletIcon.png"
uncheckedIcon: "../images/uncheckedIcon.png"
} }
} }
Rectangle { Rectangle {
@@ -203,27 +222,28 @@ Rectangle {
} }
GridLayout { GridLayout {
visible: !isMobile
id: daemonStatusRow id: daemonStatusRow
columns: (isMobile) ? 2 : 4 columns: (isMobile) ? 2 : 4
StandardButton { StandardButton {
visible: true visible: !appWindow.daemonRunning
enabled: !appWindow.daemonRunning
id: startDaemonButton id: startDaemonButton
text: qsTr("Start daemon") + translationManager.emptyString text: qsTr("Start Local Node") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
pressedColor: "#FF4304" pressedColor: "#FF4304"
onClicked: { onClicked: {
// Set current daemon address to local
appWindow.currentDaemonAddress = appWindow.localDaemonAddress
appWindow.startDaemon(daemonFlags.text) appWindow.startDaemon(daemonFlags.text)
} }
} }
StandardButton { StandardButton {
visible: true visible: appWindow.daemonRunning
enabled: appWindow.daemonRunning
id: stopDaemonButton id: stopDaemonButton
text: qsTr("Stop daemon") + translationManager.emptyString text: qsTr("Stop Local Node") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
@@ -246,16 +266,15 @@ Rectangle {
daemonConsolePopup.open(); daemonConsolePopup.open();
} }
} }
} }
RowLayout { ColumnLayout {
id: blockchainFolderRow id: blockchainFolderRow
visible: !isMobile
Label { Label {
id: blockchainFolderLabel id: blockchainFolderLabel
color: "#4A4949" color: "#4A4949"
text: qsTr("Blockchain location") + translationManager.emptyString text: qsTr("Blockchain location") + translationManager.emptyString
fontSize: 16
} }
LineEdit { LineEdit {
id: blockchainFolder id: blockchainFolder
@@ -278,13 +297,14 @@ Rectangle {
} }
} }
RowLayout { RowLayout {
visible: daemonAdvanced.checked && !isMobile
id: daemonFlagsRow id: daemonFlagsRow
Label { Label {
id: daemonFlagsLabel id: daemonFlagsLabel
color: "#4A4949" color: "#4A4949"
text: qsTr("Daemon startup flags") + translationManager.emptyString text: qsTr("Local daemon startup flags") + translationManager.emptyString
fontSize: 16
} }
LineEdit { LineEdit {
id: daemonFlags id: daemonFlags
@@ -297,59 +317,21 @@ Rectangle {
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: 10 visible: daemonAdvanced.checked || isMobile
Label {
id: daemonAddrLabel
Layout.fillWidth: true
color: "#4A4949"
text: qsTr("Daemon address") + translationManager.emptyString
fontSize: 16
}
}
GridLayout {
id: daemonAddrRow
Layout.fillWidth: true
columnSpacing: 10
columns: (isMobile) ? 2 : 3
LineEdit {
id: daemonAddr
Layout.preferredWidth: 100
Layout.fillWidth: true
text: (daemonAddress !== undefined) ? daemonAddress[0] : ""
placeholderText: qsTr("Hostname / IP") + translationManager.emptyString
}
LineEdit {
id: daemonPort
Layout.preferredWidth: 100
Layout.fillWidth: true
text: (daemonAddress !== undefined) ? daemonAddress[1] : "18081"
placeholderText: qsTr("Port") + translationManager.emptyString
}
}
RowLayout {
Layout.fillWidth: true
spacing: 10
Label { Label {
id: daemonLoginLabel id: daemonLoginLabel
Layout.fillWidth: true Layout.fillWidth: true
color: "#4A4949" color: "#4A4949"
text: qsTr("Login (optional)") + translationManager.emptyString text: qsTr("Node login (optional)") + translationManager.emptyString
fontSize: 16
} }
} }
RowLayout { ColumnLayout {
visible: daemonAdvanced.checked || isMobile
LineEdit { LineEdit {
id: daemonUsername id: daemonUsername
Layout.preferredWidth: 100 Layout.preferredWidth: 100 * scaleRatio
Layout.fillWidth: true Layout.fillWidth: true
text: persistentSettings.daemonUsername text: persistentSettings.daemonUsername
placeholderText: qsTr("Username") + translationManager.emptyString placeholderText: qsTr("Username") + translationManager.emptyString
@@ -358,50 +340,65 @@ Rectangle {
LineEdit { LineEdit {
id: daemonPassword id: daemonPassword
Layout.preferredWidth: 100 Layout.preferredWidth: 100 * scaleRatio
Layout.fillWidth: true Layout.fillWidth: true
text: persistentSettings.daemonPassword text: persistentSettings.daemonPassword
placeholderText: qsTr("Password") + translationManager.emptyString placeholderText: qsTr("Password") + translationManager.emptyString
echoMode: TextInput.Password echoMode: TextInput.Password
} }
}
StandardButton { RowLayout {
id: daemonAddrSave visible: persistentSettings.useRemoteNode
Layout.fillWidth: false ColumnLayout {
Layout.leftMargin: 30 Label {
text: qsTr("Connect") + translationManager.emptyString color: "#4A4949"
shadowReleasedColor: "#FF4304" text: qsTr("Remote node") + translationManager.emptyString
shadowPressedColor: "#B32D00" }
releasedColor: "#FF6C3C" RemoteNodeEdit {
pressedColor: "#FF4304" id: remoteNodeEdit
onClicked: { Layout.minimumWidth: 100 * scaleRatio
console.log("saving daemon adress settings") daemonAddrText: persistentSettings.remoteNodeAddress.split(":")[0].trim()
var newDaemon = daemonAddr.text.trim() + ":" + daemonPort.text.trim() daemonPortText: (persistentSettings.remoteNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1]
if(persistentSettings.daemon_address != newDaemon) { onEditingFinished: {
persistentSettings.daemon_address = newDaemon persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
console.log("setting remote node to " + persistentSettings.remoteNodeAddress)
} }
}
// Update daemon login StandardButton {
persistentSettings.daemonUsername = daemonUsername.text; id: remoteNodeSave
persistentSettings.daemonPassword = daemonPassword.text; text: qsTr("Connect") + translationManager.emptyString
currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword); shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
onClicked: {
// Update daemon login
persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
persistentSettings.daemonUsername = daemonUsername.text;
persistentSettings.daemonPassword = daemonPassword.text;
persistentSettings.useRemoteNode = true
//Reinit wallet currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword);
currentWallet.initAsync(newDaemon);
appWindow.connectRemoteNode()
}
} }
} }
} }
RowLayout { RowLayout {
visible: !isMobile
Label { Label {
color: "#4A4949" color: "#4A4949"
text: qsTr("Layout settings") + translationManager.emptyString text: qsTr("Layout settings") + translationManager.emptyString
fontSize: 16 anchors.topMargin: 30 * scaleRatio
anchors.topMargin: 30 Layout.topMargin: 30 * scaleRatio
Layout.topMargin: 30
} }
} }
Rectangle { Rectangle {
visible: !isMobile
Layout.fillWidth: true Layout.fillWidth: true
height: 1 height: 1
color: "#DEDEDE" color: "#DEDEDE"
@@ -409,6 +406,7 @@ Rectangle {
RowLayout { RowLayout {
CheckBox { CheckBox {
visible: !isMobile
id: customDecorationsCheckBox id: customDecorationsCheckBox
checked: persistentSettings.customDecorations checked: persistentSettings.customDecorations
onClicked: appWindow.setCustomWindowDecorations(checked) onClicked: appWindow.setCustomWindowDecorations(checked)
@@ -424,9 +422,8 @@ Rectangle {
Label { Label {
color: "#4A4949" color: "#4A4949"
text: qsTr("Log level") + translationManager.emptyString text: qsTr("Log level") + translationManager.emptyString
fontSize: 16 anchors.topMargin: 30 * scaleRatio
anchors.topMargin: 30 Layout.topMargin: 30 * scaleRatio
Layout.topMargin: 30
} }
} }
Rectangle { Rectangle {
@@ -454,7 +451,6 @@ Rectangle {
LineEdit { LineEdit {
id: logCategories id: logCategories
Layout.preferredWidth: 200
Layout.fillWidth: true Layout.fillWidth: true
text: appWindow.persistentSettings.logCategories text: appWindow.persistentSettings.logCategories
placeholderText: qsTr("(e.g. *:WARNING,net.p2p:DEBUG)") + translationManager.emptyString placeholderText: qsTr("(e.g. *:WARNING,net.p2p:DEBUG)") + translationManager.emptyString
@@ -475,8 +471,8 @@ Rectangle {
color: "#4A4949" color: "#4A4949"
text: qsTr("Debug info") + translationManager.emptyString text: qsTr("Debug info") + translationManager.emptyString
fontSize: 16 fontSize: 16
anchors.topMargin: 30 anchors.topMargin: 30 * scaleRatio
Layout.topMargin: 30 Layout.topMargin: 30 * scaleRatio
} }
} }
Rectangle { Rectangle {
@@ -484,13 +480,11 @@ Rectangle {
height: 1 height: 1
color: "#DEDEDE" color: "#DEDEDE"
} }
TextBlock { TextBlock {
Layout.topMargin: 8 Layout.topMargin: 8
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("GUI version: ") + Version.GUI_VERSION + translationManager.emptyString text: qsTr("GUI version: ") + Version.GUI_VERSION + translationManager.emptyString
} }
TextBlock { TextBlock {
id: guiMoneroVersion id: guiMoneroVersion
Layout.fillWidth: true Layout.fillWidth: true
@@ -588,61 +582,6 @@ Rectangle {
} }
} }
PasswordDialog {
id: settingsPasswordDialog
onAccepted: {
if(appWindow.password === settingsPasswordDialog.password){
if(currentWallet.seedLanguage == "") {
console.log("No seed language set. Using English as default");
currentWallet.setSeedLanguage("English");
}
seedPopup.title = qsTr("Wallet seed & keys") + translationManager.emptyString;
seedPopup.text = "<b>Wallet Mnemonic seed</b> <br>" + currentWallet.seed
+ "<br><br> <b>" + qsTr("Secret view key") + ":</b> " + currentWallet.secretViewKey
+ "<br><b>" + qsTr("Public view key") + ":</b> " + currentWallet.publicViewKey
+ "<br><b>" + qsTr("Secret spend key") + ":</b> " + currentWallet.secretSpendKey
+ "<br><b>" + qsTr("Public spend key") + ":</b> " + currentWallet.publicSpendKey
seedPopup.open()
seedPopup.width = 600
seedPopup.height = 300
seedPopup.onCloseCallback = function() {
seedPopup.text = ""
}
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password");
informationPopup.open()
informationPopup.onCloseCallback = function() {
settingsPasswordDialog.open()
}
}
settingsPasswordDialog.password = ""
}
onRejected: {
}
}
StandardDialog {
id: seedPopup
cancelVisible: false
okVisible: true
width:600
height:400
property var onCloseCallback
onAccepted: {
if (onCloseCallback) {
onCloseCallback()
}
}
}
// Choose blockchain folder // Choose blockchain folder
FileDialog { FileDialog {
id: blockchainFileDialog id: blockchainFileDialog
@@ -671,7 +610,6 @@ Rectangle {
confirmationDialog.text += qsTr("Note: lmdb folder not found. A new folder will be created.") + "\n\n" confirmationDialog.text += qsTr("Note: lmdb folder not found. A new folder will be created.") + "\n\n"
} }
confirmationDialog.icon = StandardIcon.Question confirmationDialog.icon = StandardIcon.Question
confirmationDialog.cancelText = qsTr("Cancel") confirmationDialog.cancelText = qsTr("Cancel")
@@ -703,7 +641,7 @@ Rectangle {
function onPageCompleted() { function onPageCompleted() {
console.log("Settings page loaded"); console.log("Settings page loaded");
initSettings(); initSettings();
viewOnly = currentWallet.viewOnly;
if(typeof daemonManager != "undefined") if(typeof daemonManager != "undefined")
appWindow.daemonRunning = daemonManager.running(persistentSettings.testnet) appWindow.daemonRunning = daemonManager.running(persistentSettings.testnet)
@@ -713,8 +651,6 @@ Rectangle {
Component.onCompleted: { Component.onCompleted: {
if(typeof daemonManager != "undefined") if(typeof daemonManager != "undefined")
daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated) daemonManager.daemonConsoleUpdated.connect(onDaemonConsoleUpdated)
} }
function onDaemonConsoleUpdated(message){ function onDaemonConsoleUpdated(message){

View File

@@ -39,10 +39,6 @@ import moneroComponents.WalletManager 1.0
Rectangle { Rectangle {
id: mainLayout id: mainLayout
property int labelWidth: 120
// property int editWidth: 400
property int lineEditFontSize: 12
color: "#F0EEEE" color: "#F0EEEE"
Clipboard { id: clipboard } Clipboard { id: clipboard }
@@ -92,35 +88,31 @@ Rectangle {
// sign / verify // sign / verify
ColumnLayout { ColumnLayout {
anchors.margins: 17 anchors.margins: 17 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
spacing: 20 spacing: 20 * scaleRatio
// sign // sign
ColumnLayout { ColumnLayout {
id: signBox id: signBox
RowLayout { RowLayout {
ColumnLayout {
spacing: 8 Text {
Label { text: qsTr("Sign a message or file contents with your address:") + translationManager.emptyString
text: qsTr("Sign a message or file contents with your address:") + translationManager.emptyString wrapMode: Text.Wrap
fontSize: 16 font.pixelSize: 14 * scaleRatio
wrapMode: Text.Wrap Layout.fillWidth: true
}
Label {}
} }
} }
Label { Label {
id: signMessageLabel id: signMessageLabel
fontSize: 14
text: qsTr("Either message:") + translationManager.emptyString text: qsTr("Either message:") + translationManager.emptyString
width: mainLayout.labelWidth
} }
RowLayout { RowLayout {
@@ -133,10 +125,8 @@ Rectangle {
id: signMessageLine id: signMessageLine
anchors.left: parent.left anchors.left: parent.left
anchors.right: signMessageButton.left anchors.right: signMessageButton.left
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Message to sign") + translationManager.emptyString; placeholderText: qsTr("Message to sign") + translationManager.emptyString;
readOnly: false readOnly: false
// Layout.fillWidth: true
onTextChanged: signSignatureLine.text = "" onTextChanged: signSignatureLine.text = ""
IconButton { IconButton {
@@ -152,7 +142,6 @@ Rectangle {
StandardButton { StandardButton {
id: signMessageButton id: signMessageButton
anchors.right: parent.right anchors.right: parent.right
width: 60
text: qsTr("Sign") + translationManager.emptyString text: qsTr("Sign") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -168,9 +157,7 @@ Rectangle {
Label { Label {
id: signMessageFileLabel id: signMessageFileLabel
fontSize: 14
text: qsTr("Or file:") + translationManager.emptyString text: qsTr("Or file:") + translationManager.emptyString
width: mainLayout.labelWidth
} }
RowLayout { RowLayout {
@@ -192,8 +179,7 @@ Rectangle {
StandardButton { StandardButton {
id: loadFileToSignButton id: loadFileToSignButton
anchors.rightMargin: 17 anchors.rightMargin: 17 * scaleRatio
width: 60
text: qsTr("Select") + translationManager.emptyString text: qsTr("Select") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -208,7 +194,6 @@ Rectangle {
id: signFileLine id: signFileLine
anchors.left: loadFileToSignButton.right anchors.left: loadFileToSignButton.right
anchors.right: signFileButton.left anchors.right: signFileButton.left
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Filename with message to sign") + translationManager.emptyString; placeholderText: qsTr("Filename with message to sign") + translationManager.emptyString;
readOnly: false readOnly: false
Layout.fillWidth: true Layout.fillWidth: true
@@ -227,7 +212,6 @@ Rectangle {
StandardButton { StandardButton {
id: signFileButton id: signFileButton
anchors.right: parent.right anchors.right: parent.right
width: 60
text: qsTr("Sign") + translationManager.emptyString text: qsTr("Sign") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -241,19 +225,17 @@ Rectangle {
} }
} }
RowLayout { ColumnLayout {
id: signSignatureRow id: signSignatureRow
anchors.topMargin: 17 anchors.topMargin: 17 * scaleRatio
Label { Label {
id: signSignatureLabel id: signSignatureLabel
fontSize: 14
text: qsTr("Signature") + translationManager.emptyString text: qsTr("Signature") + translationManager.emptyString
} }
LineEdit { LineEdit {
id: signSignatureLine id: signSignatureLine
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Signature") + translationManager.emptyString; placeholderText: qsTr("Signature") + translationManager.emptyString;
readOnly: true readOnly: true
Layout.fillWidth: true Layout.fillWidth: true
@@ -276,28 +258,23 @@ Rectangle {
id: verifyBox id: verifyBox
RowLayout { RowLayout {
ColumnLayout { Text {
spacing: 8 text: qsTr("Verify a message or file signature from an address:") + translationManager.emptyString
Label { wrapMode: Text.Wrap
text: qsTr("Verify a message or file signature from an address:") + translationManager.emptyString font.pixelSize: 14 * scaleRatio
fontSize: 16 Layout.fillWidth: true
// Layout.fillWidth: true
wrapMode: Text.Wrap
}
Label {}
} }
} }
Label { Label {
id: verifyMessageLabel id: verifyMessageLabel
fontSize: 14
text: qsTr("Either message:") + translationManager.emptyString text: qsTr("Either message:") + translationManager.emptyString
width: mainLayout.labelWidth
} }
RowLayout { RowLayout {
id: verifyMessageRow id: verifyMessageRow
anchors.topMargin: 17 anchors.topMargin: 17 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@@ -305,7 +282,6 @@ Rectangle {
id: verifyMessageLine id: verifyMessageLine
anchors.left: parent.left anchors.left: parent.left
anchors.right: verifyMessageButton.left anchors.right: verifyMessageButton.left
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Message to verify") + translationManager.emptyString; placeholderText: qsTr("Message to verify") + translationManager.emptyString;
readOnly: false readOnly: false
Layout.fillWidth: true Layout.fillWidth: true
@@ -323,7 +299,6 @@ Rectangle {
StandardButton { StandardButton {
id: verifyMessageButton id: verifyMessageButton
anchors.right: parent.right anchors.right: parent.right
width: 60
text: qsTr("Verify") + translationManager.emptyString text: qsTr("Verify") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -339,16 +314,14 @@ Rectangle {
Label { Label {
id: verifyMessageFileLabel id: verifyMessageFileLabel
fontSize: 14
text: qsTr("Or file:") + translationManager.emptyString text: qsTr("Or file:") + translationManager.emptyString
width: mainLayout.labelWidth
} }
RowLayout { RowLayout {
id: verifyFileRow id: verifyFileRow
anchors.topMargin: 17 anchors.topMargin: 17 * scaleRatio
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
FileDialog { FileDialog {
id: verifyFileDialog id: verifyFileDialog
@@ -363,8 +336,7 @@ Rectangle {
StandardButton { StandardButton {
id: loadFileToVerifyButton id: loadFileToVerifyButton
anchors.rightMargin: 17 anchors.rightMargin: 17 * scaleRatio
width: 60
text: qsTr("Select") + translationManager.emptyString text: qsTr("Select") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -379,7 +351,6 @@ Rectangle {
id: verifyFileLine id: verifyFileLine
anchors.left: loadFileToVerifyButton.right anchors.left: loadFileToVerifyButton.right
anchors.right: verifyFileButton.left anchors.right: verifyFileButton.left
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Filename with message to verify") + translationManager.emptyString; placeholderText: qsTr("Filename with message to verify") + translationManager.emptyString;
readOnly: false readOnly: false
Layout.fillWidth: true Layout.fillWidth: true
@@ -397,7 +368,6 @@ Rectangle {
StandardButton { StandardButton {
id: verifyFileButton id: verifyFileButton
anchors.right: parent.right anchors.right: parent.right
width: 60
text: qsTr("Verify") + translationManager.emptyString text: qsTr("Verify") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -411,18 +381,16 @@ Rectangle {
} }
} }
Label { Text {
id: verifyAddressLabel id: verifyAddressLabel
fontSize: 14 text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: %1px;}</style>\
width: mainLayout.labelWidth Signing address <font size='%2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='%3'> )</font>").arg(14 * scaleRatio).arg(2 * scaleRatio).arg(2 * scaleRatio)
textFormat: Text.RichText
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
Signing address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>")
+ translationManager.emptyString + translationManager.emptyString
// Layout.fillWidth: true
wrapMode: Text.Wrap wrapMode: Text.Wrap
font.pixelSize: 14 * scaleRatio
onLinkActivated: appWindow.showPageRequest("AddressBook") Layout.fillWidth: true
textFormat: Text.RichText
onLinkActivated: appWindow.showPageRequest("AddressBook")
} }
LineEdit { LineEdit {
@@ -430,24 +398,22 @@ Rectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: verifyAddressLabel.bottom anchors.top: verifyAddressLabel.bottom
anchors.topMargin: 5 anchors.topMargin: 5 * scaleRatio
placeholderText: "4..." placeholderText: "4..."
// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
} }
RowLayout { ColumnLayout {
id: verifySignatureRow id: verifySignatureRow
anchors.topMargin: 17 anchors.topMargin: 17 * scaleRatio
Label { Label {
id: verifySignatureLabel id: verifySignatureLabel
fontSize: 14
text: qsTr("Signature") + translationManager.emptyString text: qsTr("Signature") + translationManager.emptyString
} }
LineEdit { LineEdit {
id: verifySignatureLine id: verifySignatureLine
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Signature") + translationManager.emptyString; placeholderText: qsTr("Signature") + translationManager.emptyString;
Layout.fillWidth: true Layout.fillWidth: true

View File

@@ -71,10 +71,10 @@ Rectangle {
} }
function updateMixin() { function updateMixin() {
var fillLevel = privacyLevelItem.fillLevel var fillLevel = (isMobile) ? privacyLevelItemSmall.fillLevel : privacyLevelItem.fillLevel
var mixin = scaleValueToMixinCount(fillLevel) var mixin = scaleValueToMixinCount(fillLevel)
print ("PrivacyLevel changed:" + fillLevel) console.log("PrivacyLevel changed:" + fillLevel)
print ("mixin count: " + mixin) console.log("mixin count: " + mixin)
privacyLabel.text = qsTr("Privacy level (ringsize %1)").arg(mixin+1) + translationManager.emptyString privacyLabel.text = qsTr("Privacy level (ringsize %1)").arg(mixin+1) + translationManager.emptyString
} }
@@ -107,297 +107,226 @@ Rectangle {
} }
} }
Item { ColumnLayout {
id: pageRoot id: pageRoot
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.margins: 17 * scaleRatio
height: 400 spacing: 0
Label { GridLayout {
id: amountLabel columns: (isMobile)? 1 : 2
anchors.left: parent.left Layout.fillWidth: true
anchors.top: parent.top
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 17
text: qsTr("Amount") + translationManager.emptyString
fontSize: 14
}
Label { ColumnLayout {
id: transactionPriority Layout.fillWidth: true
anchors.top: parent.top Label {
anchors.topMargin: 17 id: amountLabel
fontSize: 14 text: qsTr("Amount") + translationManager.emptyString
x: (parent.width - 17) / 2 + 17 }
text: qsTr("Transaction priority") + translationManager.emptyString
} RowLayout {
Layout.fillWidth: true
id: amountRow
Layout.minimumWidth: 200
Item {
visible: !isMobile
width: 37 * scaleRatio
height: 37 * scaleRatio
Image {
anchors.centerIn: parent
source: "../images/moneroIcon.png"
}
}
// Amount input
LineEdit {
Layout.fillWidth: true
id: amountLine
placeholderText: qsTr("") + translationManager.emptyString
width:100
validator: DoubleValidator {
bottom: 0.0
top: 18446744.073709551615
decimals: 12
notation: DoubleValidator.StandardNotation
locale: "C"
}
}
StandardButton {
id: amountAllButton
width: 60 * scaleRatio
text: qsTr("All") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
enabled : true
onClicked: amountLine.text = "(all)"
}
}
Row { }
id: amountRow
anchors.top: amountLabel.bottom
anchors.topMargin: 5
anchors.left: parent.left
anchors.leftMargin: 7
width: (parent.width - 17) / 2 + 10
Item {
width: 37
height: 37
Image { ColumnLayout {
anchors.centerIn: parent Layout.fillWidth: true
source: "../images/moneroIcon.png" Label {
id: transactionPriority
text: qsTr("Transaction priority") + translationManager.emptyString
}
// Note: workaround for translations in listElements
// ListElement: cannot use script for property value, so
// code like this wont work:
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
// For translations to work, the strings need to be listed in
// the file components/StandardDropdown.qml too.
// Priorities before v5
ListModel {
id: priorityModel
ListElement { column1: qsTr("Low (x1 fee)") ; column2: ""; priority: PendingTransaction.Priority_Low }
ListElement { column1: qsTr("Medium (x20 fee)") ; column2: ""; priority: PendingTransaction.Priority_Medium }
ListElement { column1: qsTr("High (x166 fee)") ; column2: ""; priority: PendingTransaction.Priority_High }
}
// Priorites after v5
ListModel {
id: priorityModelV5
ListElement { column1: qsTr("Slow (x0.25 fee)") ; column2: ""; priority: 1}
ListElement { column1: qsTr("Default (x1 fee)") ; column2: ""; priority: 2 }
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
ListElement { column1: qsTr("Fastest (x41.5 fee)") ; column2: ""; priority: 4 }
}
StandardDropdown {
Layout.fillWidth: true
id: priorityDropdown
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
} }
} }
// Amount input // Make sure dropdown is on top
LineEdit { z: parent.z + 1
id: amountLine }
placeholderText: qsTr("") + translationManager.emptyString
width: parent.width - 37 - 17 - 60 ColumnLayout {
validator: DoubleValidator { Layout.fillWidth: true
bottom: 0.0 Label {
top: 18446744.073709551615 id: addressLabel
decimals: 12 textFormat: Text.RichText
notation: DoubleValidator.StandardNotation text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
locale: "C" Address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>")
+ translationManager.emptyString
onLinkActivated: appWindow.showPageRequest("AddressBook")
Layout.fillWidth: true
}
// recipient address input
RowLayout {
id: addressLineRow
Layout.fillWidth: true
StandardButton {
id: qrfinderButton
text: qsTr("QR Code") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
visible : appWindow.qrScannerEnabled
enabled : visible
width: visible ? 60 * scaleRatio : 0
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
}
} }
} LineEdit {
id: addressLine
StandardButton { Layout.fillWidth: true
id: amountAllButton anchors.topMargin: 5 * scaleRatio
//anchors.left: amountLine.right placeholderText: "4..."
//anchors.top: amountLine.top // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
//anchors.bottom: amountLine.bottom
width: 60
text: qsTr("All") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
enabled : true
onClicked: amountLine.text = "(all)"
}
}
// Note: workaround for translations in listElements
// ListElement: cannot use script for property value, so
// code like this wont work:
// ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low }
// For translations to work, the strings need to be listed in
// the file components/StandardDropdown.qml too.
// Priorities before v5
ListModel {
id: priorityModel
ListElement { column1: qsTr("Low (x1 fee)") ; column2: ""; priority: PendingTransaction.Priority_Low }
ListElement { column1: qsTr("Medium (x20 fee)") ; column2: ""; priority: PendingTransaction.Priority_Medium }
ListElement { column1: qsTr("High (x166 fee)") ; column2: ""; priority: PendingTransaction.Priority_High }
}
// Priorites after v5
ListModel {
id: priorityModelV5
ListElement { column1: qsTr("Slow (x0.25 fee)") ; column2: ""; priority: 1}
ListElement { column1: qsTr("Default (x1 fee)") ; column2: ""; priority: 2 }
ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 }
ListElement { column1: qsTr("Fastest (x41.5 fee)") ; column2: ""; priority: 4 }
}
StandardDropdown {
id: priorityDropdown
anchors.top: transactionPriority.bottom
anchors.right: parent.right
anchors.rightMargin: 17
anchors.topMargin: 5
anchors.left: transactionPriority.left
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
z: 1
}
Label {
id: addressLabel
anchors.left: parent.left
anchors.right: parent.right
anchors.top: amountRow.bottom
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 30
fontSize: 14
textFormat: Text.RichText
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\
Address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>")
+ translationManager.emptyString
onLinkActivated: appWindow.showPageRequest("AddressBook")
}
// recipient address input
RowLayout {
id: addressLineRow
anchors.left: parent.left
anchors.right: parent.right
anchors.top: addressLabel.bottom
StandardButton {
id: qrfinderButton
anchors.left: parent.left
anchors.leftMargin: 17
anchors.topMargin: 5
text: qsTr("QR Code") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
visible : appWindow.qrScannerEnabled
enabled : visible
width: visible ? 60 : 0
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
} }
}
LineEdit {
id: addressLine
anchors.left: qrfinderButton.right
anchors.right: resolveButton.left
//anchors.leftMargin: 17
anchors.topMargin: 5
placeholderText: "4..."
// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
}
StandardButton { StandardButton {
id: resolveButton id: resolveButton
anchors.right: parent.right width: 60 * scaleRatio
anchors.leftMargin: 17 text: qsTr("Resolve") + translationManager.emptyString
anchors.topMargin: 17 shadowReleasedColor: "#FF4304"
anchors.rightMargin: 17 shadowPressedColor: "#B32D00"
width: 60 releasedColor: "#FF6C3C"
text: qsTr("Resolve") + translationManager.emptyString pressedColor: "#FF4304"
shadowReleasedColor: "#FF4304" enabled : isValidOpenAliasAddress(addressLine.text)
shadowPressedColor: "#B32D00" onClicked: {
releasedColor: "#FF6C3C" var result = walletManager.resolveOpenAlias(addressLine.text)
pressedColor: "#FF4304" if (result) {
enabled : isValidOpenAliasAddress(addressLine.text) var parts = result.split("|")
onClicked: { if (parts.length == 2) {
var result = walletManager.resolveOpenAlias(addressLine.text) var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.testnet)
if (result) { if (parts[0] === "true") {
var parts = result.split("|") if (address_ok) {
if (parts.length == 2) { addressLine.text = parts[1]
var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.testnet) addressLine.cursorPosition = 0
if (parts[0] === "true") { }
if (address_ok) { else
addressLine.text = parts[1] oa_message(qsTr("No valid address found at this OpenAlias address"))
addressLine.cursorPosition = 0 } else if (parts[0] === "false") {
} if (address_ok) {
else addressLine.text = parts[1]
oa_message(qsTr("No valid address found at this OpenAlias address")) addressLine.cursorPosition = 0
} else if (parts[0] === "false") { oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed"))
if (address_ok) { } else {
addressLine.text = parts[1] oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed"))
addressLine.cursorPosition = 0 }
oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed")) } else {
oa_message(qsTr("Internal error"))
}
} else { } else {
oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed")) oa_message(qsTr("Internal error"))
} }
} else { } else {
oa_message(qsTr("Internal error")) oa_message(qsTr("No address found"))
} }
} else {
oa_message(qsTr("Internal error"))
}
} else {
oa_message(qsTr("No address found"))
} }
} }
} }
}
Label { Label {
id: paymentIdLabel id: paymentIdLabel
anchors.left: parent.left text: qsTr("Payment ID <font size='2'>( Optional )</font>") + translationManager.emptyString
anchors.right: parent.right }
anchors.top: addressLineRow.bottom
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 17
fontSize: 14
text: qsTr("Payment ID <font size='2'>( Optional )</font>") + translationManager.emptyString
}
// payment id input // payment id input
LineEdit { LineEdit {
id: paymentIdLine id: paymentIdLine
anchors.left: parent.left placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString
anchors.right: parent.right Layout.fillWidth: true
anchors.top: paymentIdLabel.bottom }
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 5
placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString
// validator: DoubleValidator { top: 0.0 }
}
Label { Label {
id: descriptionLabel text: qsTr("Description <font size='2'>( Optional )</font>")
anchors.left: parent.left + translationManager.emptyString
anchors.right: parent.right }
anchors.top: paymentIdLine.bottom
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 17
fontSize: 14
text: qsTr("Description <font size='2'>( Optional )</font>")
+ translationManager.emptyString
}
LineEdit { LineEdit {
id: descriptionLine id: descriptionLine
anchors.left: parent.left placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString
anchors.right: parent.right Layout.fillWidth: true
anchors.top: descriptionLabel.bottom }
anchors.leftMargin: 17
anchors.rightMargin: 17
anchors.topMargin: 5
placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString
}
function checkInformation(amount, address, payment_id, testnet) {
address = address.trim()
payment_id = payment_id.trim()
var amount_ok = amount.length > 0
var address_ok = walletManager.addressValid(address, testnet)
var payment_id_ok = payment_id.length == 0 || walletManager.paymentIdValid(payment_id)
var ipid = walletManager.paymentIdFromAddress(address, testnet)
if (ipid.length > 0 && payment_id.length > 0)
payment_id_ok = false
addressLine.error = !address_ok
amountLine.error = !amount_ok
paymentIdLine.error = !payment_id_ok
return amount_ok && address_ok && payment_id_ok
}
RowLayout {
anchors.left: parent.left
anchors.top: descriptionLine.bottom
anchors.leftMargin: 17
anchors.topMargin: 17
StandardButton { StandardButton {
id: sendButton id: sendButton
Layout.bottomMargin: 17 * scaleRatio
Layout.topMargin: 17 * scaleRatio
text: qsTr("Send") + translationManager.emptyString text: qsTr("Send") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -418,6 +347,23 @@ Rectangle {
} }
} }
function checkInformation(amount, address, payment_id, testnet) {
address = address.trim()
payment_id = payment_id.trim()
var amount_ok = amount.length > 0
var address_ok = walletManager.addressValid(address, testnet)
var payment_id_ok = payment_id.length == 0 || walletManager.paymentIdValid(payment_id)
var ipid = walletManager.paymentIdFromAddress(address, testnet)
if (ipid.length > 0 && payment_id.length > 0)
payment_id_ok = false
addressLine.error = !address_ok
amountLine.error = !amount_ok
paymentIdLine.error = !payment_id_ok
return amount_ok && address_ok && payment_id_ok
}
} // pageRoot } // pageRoot
@@ -433,8 +379,10 @@ Rectangle {
anchors.top: pageRoot.bottom anchors.top: pageRoot.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.margins: 17 anchors.leftMargin: 17 * scaleRatio
spacing:10 anchors.topMargin: 17 * scaleRatio
anchors.bottomMargin: 17 * scaleRatio
spacing: 10 * scaleRatio
enabled: !viewOnly || pageRoot.enabled enabled: !viewOnly || pageRoot.enabled
RowLayout { RowLayout {
@@ -455,13 +403,14 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
height: 1 height: 1
color: "#DEDEDE" color: "#DEDEDE"
Layout.bottomMargin: 30 Layout.bottomMargin: 30 * scaleRatio
} }
RowLayout { RowLayout {
visible: persistentSettings.transferShowAdvanced visible: persistentSettings.transferShowAdvanced
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
Layout.fillWidth: true
Label { Label {
id: privacyLabel id: privacyLabel
fontSize: 14 fontSize: 14
@@ -479,17 +428,27 @@ Rectangle {
PrivacyLevel { PrivacyLevel {
visible: persistentSettings.transferShowAdvanced visible: persistentSettings.transferShowAdvanced && !isMobile
id: privacyLevelItem id: privacyLevelItem
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 17 * scaleRatio
onFillLevelChanged: updateMixin()
}
PrivacyLevelSmall {
visible: persistentSettings.transferShowAdvanced && isMobile
id: privacyLevelItemSmall
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: 17 * scaleRatio
onFillLevelChanged: updateMixin() onFillLevelChanged: updateMixin()
} }
GridLayout { GridLayout {
visible: persistentSettings.transferShowAdvanced visible: persistentSettings.transferShowAdvanced
Layout.topMargin: 50 Layout.topMargin: 50 * scaleRatio
columns: (isMobile) ? 2 : 6 columns: (isMobile) ? 2 : 6
@@ -657,8 +616,8 @@ Rectangle {
Rectangle { Rectangle {
x: root.width/2 - width/2 x: root.width/2 - width/2
y: root.height/2 - height/2 y: root.height/2 - height/2
height:statusText.paintedHeight + 50 height:statusText.paintedHeight + 50 * scaleRatio
width:statusText.paintedWidth + 40 width:statusText.paintedWidth + 40 * scaleRatio
visible: statusText.text != "" visible: statusText.text != ""
opacity: 0.9 opacity: 0.9
@@ -719,6 +678,7 @@ Rectangle {
statusText.text = qsTr("Waiting on daemon synchronization to finish") statusText.text = qsTr("Waiting on daemon synchronization to finish")
} else { } else {
// everything OK, enable transfer page // everything OK, enable transfer page
// Light wallet is always ready
pageRoot.enabled = true; pageRoot.enabled = true;
statusText.text = ""; statusText.text = "";
} }

View File

@@ -72,6 +72,7 @@
<file>images/expandTable.png</file> <file>images/expandTable.png</file>
<file>images/dropdownDel.png</file> <file>images/dropdownDel.png</file>
<file>components/HistoryTable.qml</file> <file>components/HistoryTable.qml</file>
<file>components/HistoryTableMobile.qml</file>
<file>images/gotoBasicVersion.png</file> <file>images/gotoBasicVersion.png</file>
<file>images/goToBasicVersionHovered.png</file> <file>images/goToBasicVersionHovered.png</file>
<file>BasicPanel.qml</file> <file>BasicPanel.qml</file>
@@ -143,5 +144,9 @@
<file>components/Notifier.qml</file> <file>components/Notifier.qml</file>
<file>components/MobileHeader.qml</file> <file>components/MobileHeader.qml</file>
<file>components/TextBlock.qml</file> <file>components/TextBlock.qml</file>
<file>wizard/WizardDaemonSettings.qml</file>
<file>components/RemoteNodeEdit.qml</file>
<file>pages/Keys.qml</file>
<file>images/menu.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -61,15 +61,23 @@ void QrCodeScanner::processCode(int type, const QString &data)
emit notifyError(error); emit notifyError(error);
return; return;
} }
QVariantMap parsed_unknown_parameters;
if(unknown_parameters.size() > 0) if(unknown_parameters.size() > 0)
{ {
qDebug() << "unknown parameters " << unknown_parameters; qDebug() << "unknown parameters " << unknown_parameters;
foreach(const QString &item, unknown_parameters )
{
QStringList parsed_item = item.split("=");
if(parsed_item.size() == 2) {
parsed_unknown_parameters.insert(parsed_item[0], parsed_item[1]);
}
}
emit notifyError(error, true); emit notifyError(error, true);
} }
qDebug() << "Parsed URI : " << address << " " << payment_id << " " << amount << " " << tx_description << " " << recipient_name << " " << error; qDebug() << "Parsed URI : " << address << " " << payment_id << " " << amount << " " << tx_description << " " << recipient_name << " " << error;
QString s_amount = WalletManager::instance()->displayAmount(amount); QString s_amount = WalletManager::instance()->displayAmount(amount);
qDebug() << "Amount passed " << s_amount ; qDebug() << "Amount passed " << s_amount ;
emit decoded(address, payment_id, s_amount, tx_description, recipient_name); emit decoded(address, payment_id, s_amount, tx_description, recipient_name, parsed_unknown_parameters);
} }
void QrCodeScanner::processFrame(QVideoFrame frame) void QrCodeScanner::processFrame(QVideoFrame frame)
{ {
@@ -102,3 +110,15 @@ void QrCodeScanner::timerEvent(QTimerEvent *event)
} }
} }
QrCodeScanner::~QrCodeScanner()
{
m_thread->stop();
m_thread->quit();
if(!m_thread->wait(5000))
{
m_thread->terminate();
m_thread->wait();
}
}

View File

@@ -44,7 +44,7 @@ class QrCodeScanner : public QObject
public: public:
QrCodeScanner(QObject *parent = Q_NULLPTR); QrCodeScanner(QObject *parent = Q_NULLPTR);
~QrCodeScanner();
void setSource(QCamera*); void setSource(QCamera*);
bool enabled() const; bool enabled() const;
@@ -57,7 +57,7 @@ public Q_SLOTS:
Q_SIGNALS: Q_SIGNALS:
void enabledChanged(); void enabledChanged();
void decoded(const QString &address, const QString &payment_id, const QString &amount, const QString &tx_description, const QString &recipient_name); void decoded(const QString &address, const QString &payment_id, const QString &amount, const QString &tx_description, const QString &recipient_name, const QVariantMap &extra_parameters);
void decode(int type, const QString &data); void decode(int type, const QString &data);
void notifyError(const QString &error, bool warning = false); void notifyError(const QString &error, bool warning = false);

View File

@@ -110,6 +110,7 @@ void QrScanThread::processVideoFrame(const QVideoFrame &frame)
void QrScanThread::stop() void QrScanThread::stop()
{ {
m_running = false; m_running = false;
m_waitCondition.wakeOne();
} }
void QrScanThread::addFrame(const QVideoFrame &frame) void QrScanThread::addFrame(const QVideoFrame &frame)
@@ -124,9 +125,10 @@ void QrScanThread::run()
QVideoFrame frame; QVideoFrame frame;
while(m_running) { while(m_running) {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
while(m_queue.isEmpty()) while(m_queue.isEmpty() && m_running)
m_waitCondition.wait(&m_mutex); m_waitCondition.wait(&m_mutex);
processVideoFrame(m_queue.takeFirst()); if(!m_queue.isEmpty())
processVideoFrame(m_queue.takeFirst());
} }
} }

View File

@@ -44,6 +44,7 @@ class QrScanThread : public QThread, public zbar::Image::Handler
public: public:
QrScanThread(QObject *parent = Q_NULLPTR); QrScanThread(QObject *parent = Q_NULLPTR);
void addFrame(const QVideoFrame &frame); void addFrame(const QVideoFrame &frame);
virtual void stop();
Q_SIGNALS: Q_SIGNALS:
void decoded(int type, const QString &data); void decoded(int type, const QString &data);
@@ -51,7 +52,6 @@ Q_SIGNALS:
protected: protected:
virtual void run(); virtual void run();
virtual void stop();
void processVideoFrame(const QVideoFrame &); void processVideoFrame(const QVideoFrame &);
void processQImage(const QImage &); void processQImage(const QImage &);
void processZImage(zbar::Image &image); void processZImage(zbar::Image &image);

View File

@@ -38,6 +38,8 @@ QString TransactionInfo::displayAmount() const
QString TransactionInfo::fee() const QString TransactionInfo::fee() const
{ {
if(m_pimpl->fee() == 0)
return "";
return WalletManager::instance()->displayAmount(m_pimpl->fee()); return WalletManager::instance()->displayAmount(m_pimpl->fee());
} }

View File

@@ -646,6 +646,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
Wallet::~Wallet() Wallet::~Wallet()
{ {
qDebug("~Wallet: Closing wallet"); qDebug("~Wallet: Closing wallet");
delete m_addressBook;
m_addressBook = NULL;
delete m_history; delete m_history;
m_history = NULL; m_history = NULL;

View File

@@ -275,6 +275,11 @@ bool WalletManager::stopMining()
return m_pimpl->stopMining(); return m_pimpl->stopMining();
} }
bool WalletManager::localDaemonSynced() const
{
return blockchainHeight() > 1 && blockchainHeight() >= blockchainTargetHeight();
}
QString WalletManager::resolveOpenAlias(const QString &address) const QString WalletManager::resolveOpenAlias(const QString &address) const
{ {
bool dnssec_valid = false; bool dnssec_valid = false;

View File

@@ -112,6 +112,7 @@ public:
Q_INVOKABLE quint64 blockchainHeight() const; Q_INVOKABLE quint64 blockchainHeight() const;
Q_INVOKABLE quint64 blockchainTargetHeight() const; Q_INVOKABLE quint64 blockchainTargetHeight() const;
Q_INVOKABLE double miningHashRate() const; Q_INVOKABLE double miningHashRate() const;
Q_INVOKABLE bool localDaemonSynced() const;
Q_INVOKABLE bool isMining() const; Q_INVOKABLE bool isMining() const;
Q_INVOKABLE bool startMining(const QString &address, quint32 threads, bool backgroundMining, bool ignoreBattery); Q_INVOKABLE bool startMining(const QString &address, quint32 threads, bool backgroundMining, bool ignoreBattery);

View File

@@ -78,7 +78,7 @@ ColumnLayout {
// page submitted or b) delete it when program closed before reaching final page // page submitted or b) delete it when program closed before reaching final page
// Always delete the wallet object before creating new - we could be stepping back from recovering wallet // Always delete the wallet object before creating new - we could be stepping back from recovering wallet
if (typeof settingsObject.wallet !== 'undefined') { if (typeof m_wallet !== 'undefined') {
walletManager.closeWallet() walletManager.closeWallet()
console.log("deleting wallet") console.log("deleting wallet")
} }
@@ -91,8 +91,8 @@ ColumnLayout {
uiItem.wordsTextItem.memoText = wallet.seed uiItem.wordsTextItem.memoText = wallet.seed
// saving wallet in "global" settings object // saving wallet in "global" settings object
// TODO: wallet should have a property pointing to the file where it stored or loaded from // TODO: wallet should have a property pointing to the file where it stored or loaded from
settingsObject.wallet = wallet m_wallet = wallet;
settingsObject.tmp_wallet_filename = tmp_wallet_filename settingsObject['tmp_wallet_filename'] = tmp_wallet_filename
} }
WizardManageWalletUI { WizardManageWalletUI {

View File

@@ -0,0 +1,198 @@
// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import moneroComponents.WalletManager 1.0
import QtQuick 2.2
import QtQuick.Layouts 1.1
import "../components"
import "utils.js" as Utils
ColumnLayout {
Layout.leftMargin: wizardLeftMargin
Layout.rightMargin: wizardRightMargin
id: passwordPage
opacity: 0
visible: false
property alias titleText: titleText.text
Behavior on opacity {
NumberAnimation { duration: 100; easing.type: Easing.InQuad }
}
onOpacityChanged: visible = opacity !== 0
function onPageOpened(settingsObject) {
}
function onWizardRestarted(){
}
function onPageClosed(settingsObject) {
appWindow.persistentSettings.useRemoteNode = remoteNode.checked
appWindow.persistentSettings.startLocalNode = localNode.checked
appWindow.persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress();
return true
}
RowLayout {
id: dotsRow
Layout.alignment: Qt.AlignRight
ListModel {
id: dotsModel
ListElement { dotColor: "#36B05B" }
ListElement { dotColor: "#36B05B" }
ListElement { dotColor: "#FFE00A" }
ListElement { dotColor: "#DBDBDB" }
}
Repeater {
model: dotsModel
delegate: Rectangle {
// Password page is last page when creating view only wallet
// TODO: make this dynamic for all pages in wizard
visible: (wizard.currentPath != "create_view_only_wallet" || index < 2)
width: 12; height: 12
radius: 6
color: dotColor
}
}
}
ColumnLayout {
id: headerColumn
Text {
Layout.fillWidth: true
id: titleText
font.family: "Arial"
font.pixelSize: 28 * scaleRatio
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
//renderType: Text.NativeRendering
color: "#3F3F3F"
text: "Daemon settings"
}
Text {
Layout.fillWidth: true
Layout.topMargin: 30 * scaleRatio
Layout.bottomMargin: 30 * scaleRatio
font.family: "Arial"
font.pixelSize: 18 * scaleRatio
wrapMode: Text.Wrap
//renderType: Text.NativeRendering
color: "#4A4646"
textFormat: Text.RichText
// horizontalAlignment: Text.AlignHCenter
text: qsTr("To be able to communicate with the Monero network your wallet needs to be connected to a Monero node. For best privacy it's recommended to run your own node. \
<br><br> \
If you don't have the option to run an own node there's an option to connect to a remote node.")
+ translationManager.emptyString
}
}
ColumnLayout {
RowLayout {
CheckBox {
id: localNode
text: qsTr("Start a node automatically in background (recommended)") + translationManager.emptyString
background: "#FFFFFF"
fontColor: "#4A4646"
fontSize: 16 * scaleRatio
checkedIcon: "../images/checkedVioletIcon.png"
uncheckedIcon: "../images/uncheckedIcon.png"
checked: appWindow.persistentSettings.startLocalNode && !isAndroid && !isIOS
visible: !isAndroid && !isIOS
}
}
ColumnLayout {
visible: localNode.checked
id: blockchainFolderRow
Label {
Layout.fillWidth: true
Layout.topMargin: 20 * scaleRatio
fontSize: 14 * scaleRatio
text: qsTr("Blockchain location") + translationManager.emptyString
}
LineEdit {
id: blockchainFolder
Layout.preferredWidth: 200 * scaleRatio
Layout.fillWidth: true
text: persistentSettings.blockchainDataDir
placeholderText: qsTr("(optional)") + translationManager.emptyString
MouseArea {
anchors.fill: parent
onClicked: {
mouse.accepted = false
if(persistentSettings.blockchainDataDir != "")
blockchainFileDialog.folder = "file://" + persistentSettings.blockchainDataDir
blockchainFileDialog.open()
blockchainFolder.focus = true
}
}
}
}
RowLayout {
CheckBox {
id: remoteNode
text: (localNode.checked) ? qsTr("Connect to a remote node until my own node has finished syncing") + translationManager.emptyString
: qsTr("Connect to a remote node") + translationManager.emptyString
Layout.topMargin: 20 * scaleRatio
background: "#FFFFFF"
fontColor: "#4A4646"
fontSize: 16 * scaleRatio
checkedIcon: "../images/checkedVioletIcon.png"
uncheckedIcon: "../images/uncheckedIcon.png"
checked: appWindow.persistentSettings.useRemoteNode
}
}
RowLayout {
RemoteNodeEdit {
Layout.minimumWidth: 300 * scaleRatio
opacity: remoteNode.checked
id: remoteNodeEdit
daemonAddrText: persistentSettings.remoteNodeAddress.split(":")[0].trim()
daemonPortText: (persistentSettings.remoteNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1]
}
}
}
Component.onCompleted: {
parent.wizardRestarted.connect(onWizardRestarted)
}
}

View File

@@ -100,7 +100,7 @@ ColumnLayout {
ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#36B05B" }
ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#36B05B" }
ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#36B05B" }
//ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#FFE00A" }
} }
Repeater { Repeater {
@@ -120,7 +120,7 @@ ColumnLayout {
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
font.family: "Arial" font.family: "Arial"
font.pixelSize: 28 font.pixelSize: 28 * scaleRatio
wrapMode: Text.Wrap wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
//renderType: Text.NativeRendering //renderType: Text.NativeRendering
@@ -132,7 +132,7 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
id: settingsText id: settingsText
font.family: "Arial" font.family: "Arial"
font.pixelSize: 16 font.pixelSize: 16 * scaleRatio
wrapMode: Text.Wrap wrapMode: Text.Wrap
textFormat: Text.RichText textFormat: Text.RichText
horizontalAlignment: Text.AlignHLeft horizontalAlignment: Text.AlignHLeft

View File

@@ -40,17 +40,19 @@ ColumnLayout {
property alias nextButton : nextButton property alias nextButton : nextButton
property var settings : ({}) property var settings : ({})
property int currentPage: 0 property int currentPage: 0
property int wizardLeftMargin: (!isMobile) ? 150 : 25 property int wizardLeftMargin: (!isMobile) ? 150 : 25 * scaleRatio
property int wizardRightMargin: (!isMobile) ? 150 : 25 property int wizardRightMargin: (!isMobile) ? 150 : 25 * scaleRatio
property int wizardBottomMargin: (isMobile) ? 150 : 25 property int wizardBottomMargin: (isMobile) ? 150 : 25 * scaleRatio
property int wizardTopMargin: (isMobile) ? 15 : 50 property int wizardTopMargin: (isMobile) ? 15 * scaleRatio : 50
// Storing wallet in Settings object doesn't work in qt 5.8 on android
property var m_wallet;
property var paths: { property var paths: {
// "create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, donationPage, finishPage ], // "create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, donationPage, finishPage ],
// "recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, donationPage, finishPage ], // "recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, donationPage, finishPage ],
// disable donation page // disable donation page
"create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, finishPage ], "create_wallet" : [welcomePage, optionsPage, createWalletPage, passwordPage, daemonSettingsPage, finishPage ],
"recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, finishPage ], "recovery_wallet" : [welcomePage, optionsPage, recoveryWalletPage, passwordPage, daemonSettingsPage, finishPage ],
"create_view_only_wallet" : [ createViewOnlyWalletPage, passwordPage ], "create_view_only_wallet" : [ createViewOnlyWalletPage, passwordPage ],
} }
@@ -81,6 +83,10 @@ ColumnLayout {
} }
function switchPage(next) { function switchPage(next) {
// Android focus workaround
releaseFocus();
// save settings for current page; // save settings for current page;
if (next && typeof pages[currentPage].onPageClosed !== 'undefined') { if (next && typeof pages[currentPage].onPageClosed !== 'undefined') {
if (pages[currentPage].onPageClosed(settings) !== true) { if (pages[currentPage].onPageClosed(settings) !== true) {
@@ -130,6 +136,8 @@ ColumnLayout {
print ("show recovery wallet page"); print ("show recovery wallet page");
currentPath = "recovery_wallet" currentPath = "recovery_wallet"
pages = paths[currentPath] pages = paths[currentPath]
// Create temporary wallet
createWalletPage.createWallet(settings)
wizard.nextButton.visible = true wizard.nextButton.visible = true
// goto next page // goto next page
switchPage(true); switchPage(true);
@@ -137,9 +145,8 @@ ColumnLayout {
function openOpenWalletPage() { function openOpenWalletPage() {
console.log("open wallet from file page"); console.log("open wallet from file page");
if (typeof wizard.settings['wallet'] !== 'undefined') { if (typeof m_wallet !== 'undefined' && m_wallet != null) {
settings.wallet.destroy(); walletManager.closeWallet()
delete wizard.settings['wallet'];
} }
optionsPage.onPageClosed(settings) optionsPage.onPageClosed(settings)
wizard.openWalletFromFileClicked(); wizard.openWalletFromFileClicked();
@@ -203,11 +210,10 @@ ColumnLayout {
var new_wallet_filename = createWalletPath(settings.wallet_path,settings.account_name) var new_wallet_filename = createWalletPath(settings.wallet_path,settings.account_name)
if(isIOS) { if(isIOS) {
console.log("saving in ios: "+ moneroAccountsDir + new_wallet_filename) console.log("saving in ios: "+ moneroAccountsDir + new_wallet_filename)
settings.wallet.store(moneroAccountsDir + new_wallet_filename); m_wallet.store(moneroAccountsDir + new_wallet_filename);
} else { } else {
console.log("saving in wizard: "+ new_wallet_filename) console.log("saving in wizard: "+ new_wallet_filename)
settings.wallet.store(new_wallet_filename); m_wallet.store(new_wallet_filename);
} }
@@ -217,7 +223,7 @@ ColumnLayout {
oshelper.removeTemporaryWallet(settings.tmp_wallet_filename) oshelper.removeTemporaryWallet(settings.tmp_wallet_filename)
// protecting wallet with password // protecting wallet with password
settings.wallet.setPassword(settings.wallet_password); m_wallet.setPassword(settings.wallet_password);
// Store password in session to be able to use password protected functions (e.g show seed) // Store password in session to be able to use password protected functions (e.g show seed)
appWindow.password = settings.wallet_password appWindow.password = settings.wallet_password
@@ -291,6 +297,12 @@ ColumnLayout {
Layout.topMargin: wizardTopMargin Layout.topMargin: wizardTopMargin
} }
WizardDaemonSettings {
id: daemonSettingsPage
Layout.bottomMargin: wizardBottomMargin
Layout.topMargin: wizardTopMargin
}
WizardDonation { WizardDonation {
id: donationPage id: donationPage
Layout.bottomMargin: wizardBottomMargin Layout.bottomMargin: wizardBottomMargin
@@ -308,10 +320,10 @@ ColumnLayout {
anchors.verticalCenter: wizard.verticalCenter anchors.verticalCenter: wizard.verticalCenter
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: isMobile ? 20 : 50 anchors.leftMargin: isMobile ? 20 : 50
anchors.bottomMargin: isMobile ? 20 : 50 anchors.bottomMargin: isMobile ? 20 * scaleRatio : 50
visible: parent.currentPage > 0 visible: parent.currentPage > 0
width: 50; height: 50 width: 50 * scaleRatio; height: 50 * scaleRatio
radius: 25 radius: 25
color: prevArea.containsMouse ? "#FF4304" : "#FF6C3C" color: prevArea.containsMouse ? "#FF4304" : "#FF6C3C"
@@ -333,10 +345,10 @@ ColumnLayout {
id: nextButton id: nextButton
anchors.verticalCenter: wizard.verticalCenter anchors.verticalCenter: wizard.verticalCenter
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: isMobile ? 20 : 50 anchors.rightMargin: isMobile ? 20 * scaleRatio : 50
anchors.bottomMargin: isMobile ? 20 : 50 anchors.bottomMargin: isMobile ? 20 * scaleRatio : 50
visible: currentPage > 1 && currentPage < pages.length - 1 visible: currentPage > 1 && currentPage < pages.length - 1
width: 50; height: 50 width: 50 * scaleRatio; height: 50 * scaleRatio
radius: 25 radius: 25
color: enabled ? nextArea.containsMouse ? "#FF4304" : "#FF6C3C" : "#DBDBDB" color: enabled ? nextArea.containsMouse ? "#FF4304" : "#FF6C3C" : "#DBDBDB"
@@ -359,7 +371,7 @@ ColumnLayout {
id: sendButton id: sendButton
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.margins: (isMobile) ? 20 : 50 anchors.margins: (isMobile) ? 20 * scaleRatio : 50 * scaleRatio
text: qsTr("USE MONERO") + translationManager.emptyString text: qsTr("USE MONERO") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -376,7 +388,7 @@ ColumnLayout {
id: createViewOnlyWalletButton id: createViewOnlyWalletButton
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.margins: (isMobile) ? 20 : 50 anchors.margins: (isMobile) ? 20 * scaleRatio : 50
text: qsTr("Create wallet") + translationManager.emptyString text: qsTr("Create wallet") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
@@ -408,7 +420,7 @@ ColumnLayout {
id: abortViewOnlyButton id: abortViewOnlyButton
anchors.right: createViewOnlyWalletButton.left anchors.right: createViewOnlyWalletButton.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.margins: (isMobile) ? 20 : 50 anchors.margins: (isMobile) ? 20 * scaleRatio : 50
text: qsTr("Abort") + translationManager.emptyString text: qsTr("Abort") + translationManager.emptyString
shadowReleasedColor: "#FF4304" shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"

View File

@@ -86,6 +86,31 @@ ColumnLayout {
return wordsArray.length === 25 return wordsArray.length === 25
} }
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name, extra_parameters) {
// Switch to recover from keys
recoverFromSeedMode = false
spendKeyLine.text = ""
viewKeyLine.text = ""
restoreHeightItem.text = ""
if(typeof extra_parameters.secret_view_key != "undefined") {
viewKeyLine.text = extra_parameters.secret_view_key
}
if(typeof extra_parameters.secret_spend_key != "undefined") {
spendKeyLine.text = extra_parameters.secret_spend_key
}
if(typeof extra_parameters.restore_height != "undefined") {
restoreHeightItem.text = extra_parameters.restore_height
}
addressLine.text = address
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
// Check if keys are correct
checkNextButton();
}
RowLayout { RowLayout {
id: dotsRow id: dotsRow
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
@@ -93,8 +118,8 @@ ColumnLayout {
ListModel { ListModel {
id: dotsModel id: dotsModel
ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#FFE00A" }
//ListElement { dotColor: "#DBDBDB" } ListElement { dotColor: "#DBDBDB" }
ListElement { dotColor: "#DBDBDB" } ListElement { dotColor: "#DBDBDB" }
ListElement { dotColor: "#DBDBDB" } ListElement { dotColor: "#DBDBDB" }
} }
@@ -118,7 +143,7 @@ ColumnLayout {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
id: titleText id: titleText
font.family: "Arial" font.family: "Arial"
font.pixelSize: 28 font.pixelSize: 28 * scaleRatio
wrapMode: Text.Wrap wrapMode: Text.Wrap
color: "#3F3F3F" color: "#3F3F3F"
} }
@@ -128,8 +153,8 @@ ColumnLayout {
Layout.bottomMargin: rowSpacing Layout.bottomMargin: rowSpacing
Label { Label {
Layout.topMargin: 20 Layout.topMargin: 20 * scaleRatio
fontSize: 14 fontSize: 14 * scaleRatio
text: qsTr("Wallet name") text: qsTr("Wallet name")
+ translationManager.emptyString + translationManager.emptyString
} }
@@ -137,16 +162,17 @@ ColumnLayout {
LineEdit { LineEdit {
id: accountName id: accountName
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
text: defaultAccountName text: defaultAccountName
onTextUpdated: checkNextButton() onTextUpdated: checkNextButton()
} }
} }
RowLayout{ GridLayout{
columns: (isMobile)? 2 : 4
visible: recoverMode visible: recoverMode
spacing: 0
StandardButton { StandardButton {
id: recoverFromSeedButton id: recoverFromSeedButton
text: qsTr("Restore from seed") + translationManager.emptyString text: qsTr("Restore from seed") + translationManager.emptyString
@@ -174,6 +200,22 @@ ColumnLayout {
checkNextButton(); checkNextButton();
} }
} }
StandardButton {
id: qrfinderButton
text: qsTr("From QR Code") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
visible : true //appWindow.qrScannerEnabled
enabled : visible
onClicked: {
cameraUi.state = "Capture"
cameraUi.qrcode_decoded.connect(updateFromQrCode)
}
}
} }
// Recover from seed // Recover from seed
@@ -183,8 +225,8 @@ ColumnLayout {
WizardMemoTextInput { WizardMemoTextInput {
id : memoTextItem id : memoTextItem
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
} }
} }
@@ -198,24 +240,24 @@ ColumnLayout {
LineEdit { LineEdit {
Layout.fillWidth: true Layout.fillWidth: true
id: addressLine id: addressLine
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
placeholderText: qsTr("Account address (public)") + translationManager.emptyString placeholderText: qsTr("Account address (public)") + translationManager.emptyString
onTextUpdated: checkNextButton() onTextUpdated: checkNextButton()
} }
LineEdit { LineEdit {
Layout.fillWidth: true Layout.fillWidth: true
id: viewKeyLine id: viewKeyLine
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
placeholderText: qsTr("View key (private)") + translationManager.emptyString placeholderText: qsTr("View key (private)") + translationManager.emptyString
onTextUpdated: checkNextButton() onTextUpdated: checkNextButton()
} }
LineEdit { LineEdit {
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
id: spendKeyLine id: spendKeyLine
placeholderText: qsTr("Spend key (private)") + translationManager.emptyString placeholderText: qsTr("Spend key (private)") + translationManager.emptyString
onTextUpdated: checkNextButton() onTextUpdated: checkNextButton()
@@ -227,8 +269,8 @@ ColumnLayout {
LineEdit { LineEdit {
id: restoreHeightItem id: restoreHeightItem
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
placeholderText: qsTr("Restore height (optional)") + translationManager.emptyString placeholderText: qsTr("Restore height (optional)") + translationManager.emptyString
validator: IntValidator { validator: IntValidator {
bottom:0 bottom:0
@@ -240,15 +282,15 @@ ColumnLayout {
ColumnLayout { ColumnLayout {
Label { Label {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 20 Layout.topMargin: 20 * scaleRatio
fontSize: 14 fontSize: 14
text: qsTr("Your wallet is stored in") + ": " + fileUrlInput.text; text: qsTr("Your wallet is stored in") + ": " + fileUrlInput.text;
} }
LineEdit { LineEdit {
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 600 Layout.maximumWidth: 600 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
id: fileUrlInput id: fileUrlInput
text: moneroAccountsDir + "/" text: moneroAccountsDir + "/"

View File

@@ -25,21 +25,21 @@ Column {
TextEdit { TextEdit {
id: memoTextInput id: memoTextInput
property alias placeholderText: memoTextPlaceholder.text property alias placeholderText: memoTextPlaceholder.text
textMargin: 8 textMargin: 8 * scaleRatio
text: "" text: ""
font.family: "Arial" font.family: "Arial"
font.pixelSize: 16 font.pixelSize: 16 * scaleRatio
wrapMode: TextInput.Wrap wrapMode: TextInput.Wrap
width: parent.width width: parent.width
selectByMouse: true selectByMouse: true
property int minimumHeight: 100 property int minimumHeight: 100 * scaleRatio
height: contentHeight > minimumHeight ? contentHeight : minimumHeight height: contentHeight > minimumHeight ? contentHeight : minimumHeight
Text { Text {
id: memoTextPlaceholder id: memoTextPlaceholder
anchors.fill:parent anchors.fill:parent
font.pixelSize: 16 font.pixelSize: 16 * scaleRatio
anchors.margins: 8 anchors.margins: 8 * scaleRatio
font.bold:true font.bold:true
text: qsTr("Enter your 25 word mnemonic seed") + translationManager.emptyString text: qsTr("Enter your 25 word mnemonic seed") + translationManager.emptyString
color: "#BABABA" color: "#BABABA"
@@ -59,7 +59,11 @@ Column {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: clipboard.setText(memoTextInput.text) onClicked: {
clipboard.setText(memoTextInput.text)
appWindow.showStatusMessage(qsTr("Seed copied to clipboard"),3)
}
} }
} }
Rectangle { Rectangle {
@@ -75,14 +79,14 @@ Column {
Text { Text {
id: wordsTipText id: wordsTipText
anchors.fill: parent anchors.fill: parent
anchors.topMargin : 16 anchors.topMargin : 16 * scaleRatio
anchors.bottomMargin: 16 anchors.bottomMargin: 16 * scaleRatio
anchors.leftMargin: 16 anchors.leftMargin: 16 * scaleRatio
anchors.rightMargin: 16 anchors.rightMargin: 16 * scaleRatio
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
font.family: "Arial" font.family: "Arial"
font.pixelSize: 15 font.pixelSize: 15 * scaleRatio
color: "#4A4646" color: "#4A4646"
wrapMode: Text.Wrap wrapMode: Text.Wrap
text: qsTr("This seed is <b>very</b> important to write down and keep secret. It is all you need to backup and restore your wallet.") text: qsTr("This seed is <b>very</b> important to write down and keep secret. It is all you need to backup and restore your wallet.")

View File

@@ -38,8 +38,8 @@ ColumnLayout {
signal openWalletClicked() signal openWalletClicked()
opacity: 0 opacity: 0
visible: false visible: false
property int buttonSize: (isMobile) ? 80 : 190 property int buttonSize: (isMobile) ? 80 * scaleRatio : 190 * scaleRatio
property int buttonImageSize: (isMobile) ? buttonSize - 10 : buttonSize - 30 property int buttonImageSize: (isMobile) ? buttonSize - 10 * scaleRatio : buttonSize - 30 * scaleRatio
function onPageClosed() { function onPageClosed() {
// Save settings used in open from file. // Save settings used in open from file.
@@ -60,13 +60,13 @@ ColumnLayout {
id: headerColumn id: headerColumn
Layout.leftMargin: wizardLeftMargin Layout.leftMargin: wizardLeftMargin
Layout.rightMargin: wizardRightMargin Layout.rightMargin: wizardRightMargin
Layout.bottomMargin: (!isMobile) ? 40 : 20 Layout.bottomMargin: (!isMobile) ? 40 * scaleRatio : 20
spacing: 30 spacing: 30 * scaleRatio
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
font.family: "Arial" font.family: "Arial"
font.pixelSize: 28 font.pixelSize: 28 * scaleRatio
//renderType: Text.NativeRendering //renderType: Text.NativeRendering
color: "#3F3F3F" color: "#3F3F3F"
wrapMode: Text.Wrap wrapMode: Text.Wrap
@@ -77,7 +77,7 @@ ColumnLayout {
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18 * scaleRatio
//renderType: Text.NativeRendering //renderType: Text.NativeRendering
color: "#4A4646" color: "#4A4646"
wrapMode: Text.Wrap wrapMode: Text.Wrap
@@ -91,8 +91,8 @@ ColumnLayout {
Layout.rightMargin: wizardRightMargin Layout.rightMargin: wizardRightMargin
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
id: actionButtons id: actionButtons
columnSpacing: 40 columnSpacing: 40 * scaleRatio
rowSpacing: 10 rowSpacing: 10 * scaleRatio
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
flow: isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight flow: isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight
@@ -101,8 +101,8 @@ ColumnLayout {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight
rowSpacing: 20 rowSpacing: 20 * scaleRatio
columnSpacing: 10 columnSpacing: 10 * scaleRatio
Rectangle { Rectangle {
Layout.preferredHeight: page.buttonSize Layout.preferredHeight: page.buttonSize
@@ -132,9 +132,9 @@ ColumnLayout {
} }
Text { Text {
Layout.preferredWidth: 190 Layout.preferredWidth: page.buttonSize
font.family: "Arial" font.family: "Arial"
font.pixelSize: 16 font.pixelSize: 16 * scaleRatio
color: "#4A4949" color: "#4A4949"
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
@@ -146,8 +146,8 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight
rowSpacing: 20 rowSpacing: 20 * scaleRatio
columnSpacing: 10 columnSpacing: 10 * scaleRatio
Rectangle { Rectangle {
Layout.preferredHeight: page.buttonSize Layout.preferredHeight: page.buttonSize
@@ -156,7 +156,7 @@ ColumnLayout {
color: recoverWalletArea.containsMouse ? "#DBDBDB" : "#FFFFFF" color: recoverWalletArea.containsMouse ? "#DBDBDB" : "#FFFFFF"
Image { Image {
width: page.buttomImageSize width: page.buttonImageSize
height: page.buttonImageSize height: page.buttonImageSize
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
anchors.centerIn: parent anchors.centerIn: parent
@@ -174,9 +174,9 @@ ColumnLayout {
} }
Text { Text {
Layout.preferredWidth: 190 Layout.preferredWidth: page.buttonSize
font.family: "Arial" font.family: "Arial"
font.pixelSize: 16 font.pixelSize: 16 * scaleRatio
color: "#4A4949" color: "#4A4949"
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: qsTr("Restore wallet from keys or mnemonic seed") + translationManager.emptyString text: qsTr("Restore wallet from keys or mnemonic seed") + translationManager.emptyString
@@ -189,8 +189,8 @@ ColumnLayout {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight flow: !isMobile ? GridLayout.TopToBottom : GridLayout.LeftToRight
rowSpacing: 20 rowSpacing: 20 * scaleRatio
columnSpacing: 10 columnSpacing: 10 * scaleRatio
Rectangle { Rectangle {
Layout.preferredHeight: page.buttonSize Layout.preferredHeight: page.buttonSize
@@ -217,9 +217,9 @@ ColumnLayout {
} }
Text { Text {
Layout.preferredWidth: 190 Layout.preferredWidth: page.buttonSize
font.family: "Arial" font.family: "Arial"
font.pixelSize: 16 font.pixelSize: 16 * scaleRatio
color: "#4A4949" color: "#4A4949"
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: qsTr("Open a wallet from file") + translationManager.emptyString text: qsTr("Open a wallet from file") + translationManager.emptyString
@@ -234,18 +234,18 @@ ColumnLayout {
RowLayout { RowLayout {
Layout.leftMargin: wizardLeftMargin Layout.leftMargin: wizardLeftMargin
Layout.rightMargin: wizardRightMargin Layout.rightMargin: wizardRightMargin
Layout.topMargin: 30 Layout.topMargin: 30 * scaleRatio
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
Layout.fillWidth: true Layout.fillWidth: true
Rectangle { Rectangle {
width: 100 width: 100 * scaleRatio
CheckBox { CheckBox {
id: testNet id: testNet
text: qsTr("Testnet") + translationManager.emptyString text: qsTr("Testnet") + translationManager.emptyString
background: "#FFFFFF" background: "#FFFFFF"
fontColor: "#4A4646" fontColor: "#4A4646"
fontSize: 16 fontSize: 16 * scaleRatio
checkedIcon: "../images/checkedVioletIcon.png" checkedIcon: "../images/checkedVioletIcon.png"
uncheckedIcon: "../images/uncheckedIcon.png" uncheckedIcon: "../images/uncheckedIcon.png"
checked: appWindow.persistentSettings.testnet; checked: appWindow.persistentSettings.testnet;

View File

@@ -64,7 +64,6 @@ ColumnLayout {
function onPageClosed(settingsObject) { function onPageClosed(settingsObject) {
// TODO: set password on the final page // TODO: set password on the final page
// settingsObject.wallet.setPassword(passwordItem.password)
settingsObject['wallet_password'] = passwordUI.password settingsObject['wallet_password'] = passwordUI.password
return true return true
} }
@@ -82,8 +81,8 @@ ColumnLayout {
ListModel { ListModel {
id: dotsModel id: dotsModel
ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#36B05B" }
ListElement { dotColor: "#36B05B" } ListElement { dotColor: "#FFE00A" }
//ListElement { dotColor: "#FFE00A" } ListElement { dotColor: "#DBDBDB" }
ListElement { dotColor: "#DBDBDB" } ListElement { dotColor: "#DBDBDB" }
} }
@@ -107,7 +106,7 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
id: titleText id: titleText
font.family: "Arial" font.family: "Arial"
font.pixelSize: 28 font.pixelSize: 28 * scaleRatio
wrapMode: Text.Wrap wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
//renderType: Text.NativeRendering //renderType: Text.NativeRendering
@@ -117,9 +116,9 @@ ColumnLayout {
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
Layout.bottomMargin: 30 Layout.bottomMargin: 30 * scaleRatio
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18 * scaleRatio
wrapMode: Text.Wrap wrapMode: Text.Wrap
//renderType: Text.NativeRendering //renderType: Text.NativeRendering
color: "#4A4646" color: "#4A4646"

View File

@@ -42,7 +42,7 @@ ColumnLayout {
id : password id : password
focus:true focus:true
font.family: "Arial" font.family: "Arial"
font.pixelSize: (isMobile) ? 25 : 26 font.pixelSize: (isMobile) ? 25 * scaleRatio : 26 * scaleRatio
echoMode: TextInput.Password echoMode: TextInput.Password
style: TextFieldStyle { style: TextFieldStyle {
renderType: Text.NativeRendering renderType: Text.NativeRendering

View File

@@ -42,19 +42,22 @@ ColumnLayout {
wizard.nextButton.enabled = passwordItem.password === retypePasswordItem.password wizard.nextButton.enabled = passwordItem.password === retypePasswordItem.password
// scorePassword returns value from 0 to... lots // TODO: password strength meter segfaults on Android.
var strength = walletManager.getPasswordStrength(passwordItem.password); if (!isAndroid) {
// consider anything below 10 bits as dire // scorePassword returns value from 0 to... lots
strength -= 10 var strength = walletManager.getPasswordStrength(passwordItem.password);
if (strength < 0) // consider anything below 10 bits as dire
strength = 0 strength -= 10
// use a slight parabola to discourage short passwords if (strength < 0)
strength = strength ^ 1.2 / 3 strength = 0
// mapScope does not clamp // use a slight parabola to discourage short passwords
if (strength > 100) strength = strength ^ 1.2 / 3
strength = 100 // mapScope does not clamp
// privacyLevel component uses 1..13 scale if (strength > 100)
privacyLevel.fillLevel = Utils.mapScope(1, 100, 1, 13, strength) strength = 100
// privacyLevel component uses 1..13 scale
privacyLevel.fillLevel = Utils.mapScope(1, 100, 1, 13, strength)
}
} }
function resetFocus() { function resetFocus() {
@@ -64,8 +67,8 @@ ColumnLayout {
WizardPasswordInput { WizardPasswordInput {
id: passwordItem id: passwordItem
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 300 Layout.maximumWidth: 300 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
placeholderText : qsTr("Password") + translationManager.emptyString; placeholderText : qsTr("Password") + translationManager.emptyString;
KeyNavigation.tab: retypePasswordItem KeyNavigation.tab: retypePasswordItem
@@ -76,8 +79,8 @@ ColumnLayout {
WizardPasswordInput { WizardPasswordInput {
id: retypePasswordItem id: retypePasswordItem
Layout.fillWidth: true Layout.fillWidth: true
Layout.maximumWidth: 300 Layout.maximumWidth: 300 * scaleRatio
Layout.minimumWidth: 200 Layout.minimumWidth: 200 * scaleRatio
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
placeholderText : qsTr("Confirm password") + translationManager.emptyString; placeholderText : qsTr("Confirm password") + translationManager.emptyString;
KeyNavigation.tab: passwordItem KeyNavigation.tab: passwordItem
@@ -85,7 +88,8 @@ ColumnLayout {
} }
PrivacyLevelSmall { PrivacyLevelSmall {
Layout.topMargin: isMobile ? 20 : 40 visible: !isAndroid //TODO: strength meter doesnt work on Android
Layout.topMargin: isAndroid ? 20 * scaleRatio : 40 * scaleRatio
Layout.fillWidth: true Layout.fillWidth: true
id: privacyLevel id: privacyLevel
background: "#F0EEEE" background: "#F0EEEE"

View File

@@ -81,6 +81,12 @@ ColumnLayout {
var tmp_wallet_filename = oshelper.temporaryFilename() var tmp_wallet_filename = oshelper.temporaryFilename()
console.log("Creating temporary wallet", tmp_wallet_filename) console.log("Creating temporary wallet", tmp_wallet_filename)
// delete the temporary wallet object before creating new
if (typeof m_wallet !== 'undefined') {
walletManager.closeWallet()
console.log("deleting temporary wallet")
}
// From seed or keys // From seed or keys
if(fromSeed) if(fromSeed)
var wallet = walletManager.recoveryWallet(tmp_wallet_filename, settingsObject.words, testnet, restoreHeight) var wallet = walletManager.recoveryWallet(tmp_wallet_filename, settingsObject.words, testnet, restoreHeight)
@@ -92,7 +98,7 @@ ColumnLayout {
var success = wallet.status === Wallet.Status_Ok; var success = wallet.status === Wallet.Status_Ok;
if (success) { if (success) {
settingsObject['wallet'] = wallet; m_wallet = wallet;
settingsObject['is_recovering'] = true; settingsObject['is_recovering'] = true;
settingsObject['tmp_wallet_filename'] = tmp_wallet_filename settingsObject['tmp_wallet_filename'] = tmp_wallet_filename
} else { } else {

View File

@@ -60,13 +60,13 @@ ColumnLayout {
id: headerColumn id: headerColumn
Layout.leftMargin: wizardLeftMargin Layout.leftMargin: wizardLeftMargin
Layout.rightMargin: wizardRightMargin Layout.rightMargin: wizardRightMargin
Layout.bottomMargin: 40 Layout.bottomMargin: 40 * scaleRatio
spacing: 20 spacing: 20 * scaleRatio
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
font.family: "Arial" font.family: "Arial"
font.pixelSize: 28 font.pixelSize: 28 * scaleRatio
color: "#3F3F3F" color: "#3F3F3F"
wrapMode: Text.Wrap wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
@@ -76,7 +76,7 @@ ColumnLayout {
Text { Text {
Layout.fillWidth: true Layout.fillWidth: true
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18 * scaleRatio
color: "#4A4646" color: "#4A4646"
wrapMode: Text.Wrap wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
@@ -116,17 +116,16 @@ ColumnLayout {
property int margin: (isMobile) ? 0 : Math.floor(appWindow.width/12); property int margin: (isMobile) ? 0 : Math.floor(appWindow.width/12);
id: gridView id: gridView
cellWidth: 140 cellWidth: 140 * scaleRatio
cellHeight: 120 cellHeight: 120 * scaleRatio
model: languagesModel model: languagesModel
// Hack to center the flag grid // Hack to center the flag grid
property int columns: Math.floor(appWindow.width/140) property int columns: Math.floor(appWindow.width/cellWidth)
Layout.leftMargin: margin + (appWindow.width - cellWidth*columns) /2 Layout.leftMargin: margin + (appWindow.width - cellWidth*columns) /2
Layout.rightMargin: margin Layout.rightMargin: margin
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
clip: true clip: true
delegate: ColumnLayout { delegate: ColumnLayout {
@@ -136,9 +135,9 @@ ColumnLayout {
// Layout.alignment: Qt.AlignHCenter // Layout.alignment: Qt.AlignHCenter
Rectangle { Rectangle {
id: flagRect id: flagRect
width: 60; height: 60 width: 60 * scaleRatio; height: 60 * scaleRatio
// anchors.centerIn: parent // anchors.centerIn: parent
radius: 30 radius: 30 * scaleRatio
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
color: gridView.currentIndex === index ? "#DBDBDB" : "#FFFFFF" color: gridView.currentIndex === index ? "#DBDBDB" : "#FFFFFF"
Image { Image {
@@ -149,7 +148,7 @@ ColumnLayout {
Text { Text {
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18 * scaleRatio
// anchors.horizontalCenter: parent.horizontalCenter // anchors.horizontalCenter: parent.horizontalCenter
font.bold: gridView.currentIndex === index font.bold: gridView.currentIndex === index
// elide: Text.ElideRight // elide: Text.ElideRight