mirror of
https://github.com/monero-project/monero-gui.git
synced 2025-01-14 23:04:37 +00:00
Merge pull request #41
b1454c6
removed duplicated-by-mistake code (Ilya Kitaev)be135e3
Processing splash formatting improved (Ilya Kitaev)54b22d2
Wizard: finish page: restore height hidden if not set (Ilya Kitaev)d67071a
Settings page: layout items vertically (Ilya Kitaev)4f4cc9c
Settings page: small renaming and formatting (Ilya Kitaev)da552a0
History: Fixed filter collapse (Ilya Kitaev)7ed623e
Basic mode: updating balance properly (Ilya Kitaev)eafcf71
Minimized aka basic mode (Ilya Kitaev)a032c84
History: fee color (Ilya Kitaev)60b2d90
History: display "fee" for sent transactions (Ilya Kitaev)0ac27e1
History: filter by amount (Ilya Kitaev)10c2786
added restore height to wizardFinish (Jacob Brydolf)883762c
removed daemon-blockchain-progress rests (Jacob Brydolf)38d9034
Wizard: added restore-height (Jacob Brydolf)7f0d6c4
persistentSettings: added restoreHeight (Jacob Brydolf)9f336a5
libwalletqt: added restore-height parameter to recoveryWallet(); (Jacob Brydolf)0e0b0be
removed moneroComponets dependency (Jacob Brydolf)38db5a4
Integrate splash counter with restore-height (Jacob Brydolf)868610c
fix conflict (Jacob Brydolf)4901839
added comma/locale separation to sync counter (Jacob Brydolf)8b748bf
History: filter by amount (Ilya Kitaev)9b09e83
History: filtering by paymentId and date (Ilya Kitaev)e3cea85
TransactionHistory: firstDateTime and lastDateTime properties (Ilya Kitaev)9927182
Fix: unused dummy property removed (Ilya Kitaev)fd9ed56
Fix: DatePicker component doesn't update the date (Ilya Kitaev)612c497
TransactionHistory sorting (Ilya Kitaev)e7e6c58
Adding sort-filter-proxy model (Ilya Kitaev)0498c3b
Transaction history is not crashing and refreshing properly (Ilya Kitaev)defc2a4
build: get_libwallet_api.sh accepts build type ("Debug" or "Release", release is default); extra build script that skips cmake invocations (Ilya Kitaev)2966b0d
settings page: daemon change + password prompt on seed view (Jacob Brydolf)9700944
close wallet before reopen (Jacob Brydolf)522b067
Simple transaction history (Ilya Kitaev)9cc92bf
added onPageCompleted (Jacob Brydolf)53d3bc4
Receive page: display long address from the beginning in TextField (Ilya Kitaev)5814c19
Fixed overlapping clipboard icons on recieve page (Jacob Brydolf)cd1247c
Added option to show seed on settings-page (Jacob Brydolf)af70c81
Added daemon BC sync progress bar depends on https://github.com/monero-project/monero/pull/1173 (Jacob Brydolf)6a50951
Removed hardcoded height from PasswordDialog (Ilya Kitaev)819be91
Integrating TransactionHistoryModel (Ilya Kitaev)56c3579
Replaced Loader with StackView; Fixed payment id generation (Ilya Kitaev)0ff3fd3
added TransactionHistoryModel; renamings (Ilya Kitaev)bd8646d
UX improvements in wizard - password page styling - tab navigation / focus on load - click language loads next page (Jacob Brydolf)
This commit is contained in:
commit
053e7c7cda
42 changed files with 1705 additions and 262 deletions
|
@ -31,6 +31,8 @@ import QtGraphicalEffects 1.0
|
||||||
import "components"
|
import "components"
|
||||||
import "pages"
|
import "pages"
|
||||||
|
|
||||||
|
// mbg033 @ 2016-10-08: Not used anymore, to be deleted
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
width: 470
|
width: 470
|
||||||
|
|
|
@ -36,6 +36,7 @@ Rectangle {
|
||||||
property alias unlockedBalanceText: unlockedBalanceText.text
|
property alias unlockedBalanceText: unlockedBalanceText.text
|
||||||
property alias balanceText: balanceText.text
|
property alias balanceText: balanceText.text
|
||||||
property alias networkStatus : networkStatus
|
property alias networkStatus : networkStatus
|
||||||
|
property alias daemonProgress : daemonProgress
|
||||||
|
|
||||||
signal dashboardClicked()
|
signal dashboardClicked()
|
||||||
signal historyClicked()
|
signal historyClicked()
|
||||||
|
@ -252,17 +253,17 @@ Rectangle {
|
||||||
panel.receiveClicked()
|
panel.receiveClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
color: transferButton.checked || historyButton.checked ? "#1C1C1C" : "#505050"
|
color: transferButton.checked || historyButton.checked ? "#1C1C1C" : "#505050"
|
||||||
height: 1
|
height: 1
|
||||||
}*/
|
}
|
||||||
|
|
||||||
// ------------- History tab ---------------
|
// ------------- History tab ---------------
|
||||||
/*
|
|
||||||
MenuButton {
|
MenuButton {
|
||||||
id: historyButton
|
id: historyButton
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -276,7 +277,7 @@ Rectangle {
|
||||||
panel.historyClicked()
|
panel.historyClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
@ -330,7 +331,7 @@ Rectangle {
|
||||||
color: miningButton.checked || settingsButton.checked ? "#1C1C1C" : "#505050"
|
color: miningButton.checked || settingsButton.checked ? "#1C1C1C" : "#505050"
|
||||||
height: 1
|
height: 1
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// ------------- Settings tab ---------------
|
// ------------- Settings tab ---------------
|
||||||
MenuButton {
|
MenuButton {
|
||||||
id: settingsButton
|
id: settingsButton
|
||||||
|
@ -345,16 +346,23 @@ Rectangle {
|
||||||
panel.settingsClicked()
|
panel.settingsClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkStatusItem {
|
NetworkStatusItem {
|
||||||
id: networkStatus
|
id: networkStatus
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: (daemonProgress.visible)? daemonProgress.top : parent.bottom;
|
||||||
connected: false
|
connected: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DaemonProgress {
|
||||||
|
id: daemonProgress
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// indicate disabled state
|
// indicate disabled state
|
||||||
Desaturate {
|
Desaturate {
|
||||||
|
|
261
MiddlePanel.qml
261
MiddlePanel.qml
|
@ -27,44 +27,103 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
|
import QtQml 2.0
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
import QtGraphicalEffects 1.0
|
import QtGraphicalEffects 1.0
|
||||||
|
import "pages"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: root
|
id: root
|
||||||
color: "#F0EEEE"
|
|
||||||
|
property Item currentView
|
||||||
|
property bool basicMode : false
|
||||||
|
property string balanceText
|
||||||
|
property string unlockedBalanceText
|
||||||
|
|
||||||
|
property Transfer transferView: Transfer { }
|
||||||
|
property Receive receiveView: Receive { }
|
||||||
|
property History historyView: History { }
|
||||||
|
property Settings settingsView: Settings { }
|
||||||
|
|
||||||
|
|
||||||
signal paymentClicked(string address, string paymentId, double amount, int mixinCount, int priority)
|
signal paymentClicked(string address, string paymentId, double amount, int mixinCount, int priority)
|
||||||
signal generatePaymentIdInvoked()
|
signal generatePaymentIdInvoked()
|
||||||
|
|
||||||
states: [
|
color: "#F0EEEE"
|
||||||
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" }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
onCurrentViewChanged: {
|
||||||
|
if (currentView) {
|
||||||
|
stackView.replace(currentView)
|
||||||
|
|
||||||
|
// Component.onCompleted is called before wallet is initilized
|
||||||
|
if (typeof currentView.onPageCompleted === "function") {
|
||||||
|
currentView.onPageCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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: [
|
||||||
|
State {
|
||||||
|
name: "Dashboard"
|
||||||
|
PropertyChanges { }
|
||||||
|
}, State {
|
||||||
|
name: "History"
|
||||||
|
PropertyChanges { target: root; currentView: historyView }
|
||||||
|
PropertyChanges { target: historyView; model: appWindow.currentWallet.historyModel }
|
||||||
|
}, State {
|
||||||
|
name: "Transfer"
|
||||||
|
PropertyChanges { target: root; currentView: transferView }
|
||||||
|
}, State {
|
||||||
|
name: "Receive"
|
||||||
|
PropertyChanges { target: root; currentView: receiveView }
|
||||||
|
}, State {
|
||||||
|
name: "AddressBook"
|
||||||
|
PropertyChanges { /*TODO*/ }
|
||||||
|
}, State {
|
||||||
|
name: "Settings"
|
||||||
|
PropertyChanges { target: root; currentView: settingsView }
|
||||||
|
}, State {
|
||||||
|
name: "Mining"
|
||||||
|
PropertyChanges { /*TODO*/ }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// color stripe at the top
|
||||||
Row {
|
Row {
|
||||||
id: styledRow
|
id: styledRow
|
||||||
|
height: 4
|
||||||
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
|
||||||
|
|
||||||
Rectangle { height: 4; width: parent.width / 5; color: "#FFE00A" }
|
Rectangle { height: 4; width: parent.width / 5; color: "#FFE00A" }
|
||||||
Rectangle { height: 4; width: parent.width / 5; color: "#6B0072" }
|
Rectangle { height: 4; width: parent.width / 5; color: "#6B0072" }
|
||||||
|
@ -73,28 +132,127 @@ Rectangle {
|
||||||
Rectangle { height: 4; width: parent.width / 5; color: "#FF4F41" }
|
Rectangle { height: 4; width: parent.width / 5; color: "#FF4F41" }
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
ColumnLayout {
|
||||||
id: loader
|
anchors.fill: parent
|
||||||
anchors.left: parent.left
|
anchors.margins: 2
|
||||||
anchors.right: parent.right
|
anchors.topMargin: 30
|
||||||
anchors.top: styledRow.bottom
|
spacing: 0
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
onLoaded: {
|
|
||||||
console.log("Loaded " + item);
|
// BasicPanel header
|
||||||
|
Rectangle {
|
||||||
|
id: header
|
||||||
|
anchors.leftMargin: 1
|
||||||
|
anchors.rightMargin: 1
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 64
|
||||||
|
color: "#FFFFFF"
|
||||||
|
visible: basicMode
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: logo
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.verticalCenterOffset: -5
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 20
|
||||||
|
source: "images/moneroLogo2.png"
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
width: 256
|
||||||
|
columns: 3
|
||||||
|
|
||||||
|
Text {
|
||||||
|
|
||||||
|
width: 116
|
||||||
|
height: 20
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 12
|
||||||
|
font.letterSpacing: -1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
verticalAlignment: Text.AlignBottom
|
||||||
|
color: "#535353"
|
||||||
|
text: qsTr("Balance:")
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: balanceText
|
||||||
|
width: 110
|
||||||
|
height: 20
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 18
|
||||||
|
font.letterSpacing: -1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
verticalAlignment: Text.AlignBottom
|
||||||
|
color: "#000000"
|
||||||
|
text: root.balanceText
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
height: 20
|
||||||
|
width: 20
|
||||||
|
|
||||||
|
Image {
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
source: "images/lockIcon.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
width: 116
|
||||||
|
height: 20
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 12
|
||||||
|
font.letterSpacing: -1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
verticalAlignment: Text.AlignBottom
|
||||||
|
color: "#535353"
|
||||||
|
text: qsTr("Unlocked Balance:")
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: availableBalanceText
|
||||||
|
width: 110
|
||||||
|
height: 20
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 14
|
||||||
|
font.letterSpacing: -1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
verticalAlignment: Text.AlignBottom
|
||||||
|
color: "#000000"
|
||||||
|
text: root.unlockedBalanceText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
height: 1
|
||||||
|
color: "#DBDBDB"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// Views container
|
||||||
|
StackView {
|
||||||
/* connect "payment" click */
|
id: stackView
|
||||||
Connections {
|
initialItem: transferView
|
||||||
ignoreUnknownSignals: false
|
anchors.topMargin: 30
|
||||||
target: loader.item
|
Layout.fillWidth: true
|
||||||
onPaymentClicked : {
|
Layout.fillHeight: true
|
||||||
console.log("MiddlePanel: paymentClicked")
|
anchors.top: styledRow.bottom
|
||||||
paymentClicked(address, paymentId, amount, mixinCount, priority)
|
anchors.margins: 4
|
||||||
|
clip: true // otherwise animation will affect left panel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// border
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.top: styledRow.bottom
|
anchors.top: styledRow.bottom
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
@ -117,12 +275,25 @@ Rectangle {
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
height: 1
|
height: 1
|
||||||
color: "#DBDBDB"
|
color: "#DBDBDB"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// indicate disabled state
|
|
||||||
|
// indicates disabled state
|
||||||
Desaturate {
|
Desaturate {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
source: parent
|
source: parent
|
||||||
desaturation: root.enabled ? 0.0 : 1.0
|
desaturation: root.enabled ? 0.0 : 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* connect "payment" click */
|
||||||
|
Connections {
|
||||||
|
ignoreUnknownSignals: false
|
||||||
|
target: transferView
|
||||||
|
onPaymentClicked : {
|
||||||
|
console.log("MiddlePanel: paymentClicked")
|
||||||
|
paymentClicked(address, paymentId, amount, mixinCount, priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
52
build_libwallet_api.sh
Executable file
52
build_libwallet_api.sh
Executable file
|
@ -0,0 +1,52 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
# MONERO_URL=https://github.com/monero-project/monero.git
|
||||||
|
# MONERO_BRANCH=master
|
||||||
|
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
|
||||||
|
pushd $(pwd)
|
||||||
|
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source $ROOT_DIR/utils.sh
|
||||||
|
|
||||||
|
|
||||||
|
INSTALL_DIR=$ROOT_DIR/wallet
|
||||||
|
MONERO_DIR=$ROOT_DIR/monero
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p $MONERO_DIR/build/release
|
||||||
|
pushd $MONERO_DIR/build/release
|
||||||
|
|
||||||
|
# reusing function from "utils.sh"
|
||||||
|
platform=$(get_platform)
|
||||||
|
|
||||||
|
pushd $MONERO_DIR/build/release/src/wallet
|
||||||
|
make -j$CPU_CORE_COUNT
|
||||||
|
make install -j$CPU_CORE_COUNT
|
||||||
|
popd
|
||||||
|
|
||||||
|
# unbound is one more dependency. can't be merged to the wallet_merged
|
||||||
|
# since filename conflict (random.c.obj)
|
||||||
|
# for Linux, we use libunbound shipped with the system, so we don't need to build it
|
||||||
|
|
||||||
|
if [ "$platform" != "linux" ]; then
|
||||||
|
echo "Building libunbound..."
|
||||||
|
pushd $MONERO_DIR/build/release/external/unbound
|
||||||
|
# no need to make, it was already built as dependency for libwallet
|
||||||
|
# make -j$CPU_CORE_COUNT
|
||||||
|
make install -j$CPU_CORE_COUNT
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import moneroComponents 1.0
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listView
|
id: listView
|
||||||
|
|
90
components/DaemonProgress.qml
Normal file
90
components/DaemonProgress.qml
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright (c) 2014-2015, 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
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: item
|
||||||
|
property int fillLevel: 0
|
||||||
|
height: 44
|
||||||
|
anchors.margins: 10
|
||||||
|
visible: false
|
||||||
|
//clip: true
|
||||||
|
|
||||||
|
function updateProgress(currentBlock,targetBlock){
|
||||||
|
if(targetBlock > 0) {
|
||||||
|
var progressLevel = ((currentBlock/targetBlock) * 100).toFixed(0);
|
||||||
|
fillLevel = progressLevel
|
||||||
|
console.log("target block: ",progressLevel)
|
||||||
|
progressText.text = qsTr("Synchronizing blocks %1/%2").arg(currentBlock.toFixed(0)).arg(targetBlock.toFixed(0));
|
||||||
|
console.log("Progress text: " + progressText.text);
|
||||||
|
|
||||||
|
// TODO: lower daemon block height cache, ttl and refresh interval?
|
||||||
|
|
||||||
|
item.visible = (currentBlock < targetBlock)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bar
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
height: 18
|
||||||
|
//radius: 4
|
||||||
|
color: "#FFFFFF"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: fillRect
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.margins: 2
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id:progressText
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: "#545454"
|
||||||
|
text: qsTr("Synchronizing blocks")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,7 +27,7 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import moneroComponents 1.0
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listView
|
id: listView
|
||||||
|
|
|
@ -33,12 +33,13 @@ import QtQuick.Controls.Styles 1.2
|
||||||
Item {
|
Item {
|
||||||
id: datePicker
|
id: datePicker
|
||||||
property bool expanded: false
|
property bool expanded: false
|
||||||
property var currentDate: new Date()
|
property date currentDate
|
||||||
property bool showCurrentDate: true
|
property bool showCurrentDate: true
|
||||||
height: 37
|
height: 37
|
||||||
width: 156
|
width: 156
|
||||||
|
|
||||||
onExpandedChanged: if(expanded) appWindow.currentItem = datePicker
|
onExpandedChanged: if(expanded) appWindow.currentItem = datePicker
|
||||||
|
|
||||||
function hide() { datePicker.expanded = false }
|
function hide() { datePicker.expanded = false }
|
||||||
function containsPoint(px, py) {
|
function containsPoint(px, py) {
|
||||||
if(px < 0)
|
if(px < 0)
|
||||||
|
@ -121,12 +122,29 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
|
id: dateInput
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 10
|
anchors.leftMargin: 10
|
||||||
|
|
||||||
|
function setDate(date) {
|
||||||
|
var day = date.getDate()
|
||||||
|
var month = date.getMonth() + 1
|
||||||
|
dayInput.text = day < 10 ? "0" + day : day
|
||||||
|
monthInput.text = month < 10 ? "0" + month : month
|
||||||
|
yearInput.text = date.getFullYear()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: datePicker
|
||||||
|
onCurrentDateChanged: {
|
||||||
|
dateInput.setDate(datePicker.currentDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextInput {
|
TextInput {
|
||||||
id: dayInput
|
id: dayInput
|
||||||
|
readOnly: true
|
||||||
width: 22
|
width: 22
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
font.pixelSize: 18
|
font.pixelSize: 18
|
||||||
|
@ -135,6 +153,7 @@ Item {
|
||||||
horizontalAlignment: TextInput.AlignHCenter
|
horizontalAlignment: TextInput.AlignHCenter
|
||||||
validator: IntValidator{bottom: 01; top: 31;}
|
validator: IntValidator{bottom: 01; top: 31;}
|
||||||
KeyNavigation.tab: monthInput
|
KeyNavigation.tab: monthInput
|
||||||
|
|
||||||
text: {
|
text: {
|
||||||
if(datePicker.showCurrentDate) {
|
if(datePicker.showCurrentDate) {
|
||||||
var day = datePicker.currentDate.getDate()
|
var day = datePicker.currentDate.getDate()
|
||||||
|
@ -158,6 +177,7 @@ Item {
|
||||||
|
|
||||||
TextInput {
|
TextInput {
|
||||||
id: monthInput
|
id: monthInput
|
||||||
|
readOnly: true
|
||||||
width: 22
|
width: 22
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
font.pixelSize: 18
|
font.pixelSize: 18
|
||||||
|
@ -277,12 +297,7 @@ Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if(styleData.visibleMonth) {
|
if(styleData.visibleMonth) {
|
||||||
var date = styleData.date
|
currentDate = styleData.date
|
||||||
var day = date.getDate()
|
|
||||||
var month = date.getMonth() + 1
|
|
||||||
dayInput.text = day < 10 ? "0" + day : day
|
|
||||||
monthInput.text = month < 10 ? "0" + month : month
|
|
||||||
yearInput.text = date.getFullYear()
|
|
||||||
datePicker.expanded = false
|
datePicker.expanded = false
|
||||||
} else {
|
} else {
|
||||||
var date = styleData.date
|
var date = styleData.date
|
||||||
|
|
|
@ -27,12 +27,14 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import moneroComponents 1.0
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listView
|
id: listView
|
||||||
clip: true
|
clip: true
|
||||||
boundsBehavior: ListView.StopAtBounds
|
boundsBehavior: ListView.StopAtBounds
|
||||||
|
property var previousItem
|
||||||
|
|
||||||
footer: Rectangle {
|
footer: Rectangle {
|
||||||
height: 127
|
height: 127
|
||||||
|
@ -48,7 +50,7 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property var previousItem
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
id: delegate
|
id: delegate
|
||||||
height: 114
|
height: 114
|
||||||
|
@ -63,13 +65,13 @@ ListView {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.topMargin: 14
|
anchors.topMargin: 14
|
||||||
|
// -- direction indicator
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: dot
|
id: dot
|
||||||
width: 14
|
width: 14
|
||||||
height: width
|
height: width
|
||||||
radius: width / 2
|
radius: width / 2
|
||||||
color: out ? "#FF4F41" : "#36B05B"
|
color: isOut ? "#FF4F41" : "#36B05B"
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { //separator
|
Item { //separator
|
||||||
|
@ -77,6 +79,8 @@ ListView {
|
||||||
height: 14
|
height: 14
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- description aka recepient name from address book (TODO)
|
||||||
|
/*
|
||||||
Text {
|
Text {
|
||||||
id: descriptionText
|
id: descriptionText
|
||||||
width: text.length ? (descriptionArea.containsMouse ? parent.width - x - 12 : 120) : 0
|
width: text.length ? (descriptionArea.containsMouse ? parent.width - x - 12 : 120) : 0
|
||||||
|
@ -94,13 +98,15 @@ ListView {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
Item { //separator
|
Item { //separator
|
||||||
width: descriptionText.width ? 12 : 0
|
width: descriptionText.width ? 12 : 0
|
||||||
height: 14
|
height: 14
|
||||||
visible: !descriptionArea.containsMouse
|
visible: !descriptionArea.containsMouse
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
// -- address (in case outgoing transaction) - N/A in case of incoming
|
||||||
Text {
|
Text {
|
||||||
id: addressText
|
id: addressText
|
||||||
anchors.verticalCenter: dot.verticalCenter
|
anchors.verticalCenter: dot.verticalCenter
|
||||||
|
@ -109,11 +115,11 @@ ListView {
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
color: "#545454"
|
color: "#545454"
|
||||||
text: address
|
text: hash
|
||||||
visible: !descriptionArea.containsMouse
|
// visible: !descriptionArea.containsMouse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// -- "PaymentID" title
|
||||||
Text {
|
Text {
|
||||||
id: paymentLabel
|
id: paymentLabel
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -128,7 +134,7 @@ ListView {
|
||||||
color: "#535353"
|
color: "#535353"
|
||||||
text: paymentId !== "" ? qsTr("Payment ID:") + translationManager.emptyString : ""
|
text: paymentId !== "" ? qsTr("Payment ID:") + translationManager.emptyString : ""
|
||||||
}
|
}
|
||||||
|
// -- "PaymentID" value
|
||||||
Text {
|
Text {
|
||||||
anchors.bottom: paymentLabel.bottom
|
anchors.bottom: paymentLabel.bottom
|
||||||
anchors.left: paymentLabel.right
|
anchors.left: paymentLabel.right
|
||||||
|
@ -143,7 +149,7 @@ ListView {
|
||||||
color: "#545454"
|
color: "#545454"
|
||||||
text: paymentId
|
text: paymentId
|
||||||
}
|
}
|
||||||
|
// -- "Date", "Balance" and "Amound" section
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
@ -155,6 +161,7 @@ ListView {
|
||||||
height: 14
|
height: 14
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- "Date" column
|
||||||
Column {
|
Column {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: 215
|
width: 215
|
||||||
|
@ -189,10 +196,13 @@ ListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// -- "Balance" column
|
||||||
|
// XXX: we don't have a balance
|
||||||
|
/*
|
||||||
Column {
|
Column {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: 148
|
width: 148
|
||||||
|
visible: false
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -210,7 +220,9 @@ ListView {
|
||||||
text: balance
|
text: balance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -- "Amount column
|
||||||
Column {
|
Column {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: 148
|
width: 148
|
||||||
|
@ -230,8 +242,8 @@ ListView {
|
||||||
anchors.bottomMargin: 3
|
anchors.bottomMargin: 3
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
color: out ? "#FF4F41" : "#36B05B"
|
color: isOut ? "#FF4F41" : "#36B05B"
|
||||||
text: out ? "↓" : "↑"
|
text: isOut ? "↓" : "↑"
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
@ -239,22 +251,44 @@ ListView {
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
font.pixelSize: 18
|
font.pixelSize: 18
|
||||||
font.letterSpacing: -1
|
font.letterSpacing: -1
|
||||||
color: out ? "#FF4F41" : "#36B05B"
|
color: isOut ? "#FF4F41" : "#36B05B"
|
||||||
text: amount
|
text: displayAmount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- "Fee column
|
||||||
|
Column {
|
||||||
|
anchors.top: parent.top
|
||||||
|
width: 148
|
||||||
|
visible: isOut
|
||||||
|
Text {
|
||||||
|
anchors.left: parent.left
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: "#545454"
|
||||||
|
text: qsTr("Fee") + translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
spacing: 2
|
||||||
|
Text {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 18
|
||||||
|
font.letterSpacing: -1
|
||||||
|
color: "#FF4F41"
|
||||||
|
text: fee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 same destination</b>"; icon: "../images/dropdownSend.png" }
|
|
||||||
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
|
|
||||||
}
|
|
||||||
|
|
||||||
Clipboard { id: clipboard }
|
|
||||||
|
/*
|
||||||
|
// Transaction dropdown menu.
|
||||||
|
// Disable for now until AddressBook implemented
|
||||||
TableDropdown {
|
TableDropdown {
|
||||||
id: dropdown
|
id: dropdown
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
@ -282,5 +316,16 @@ ListView {
|
||||||
height: 1
|
height: 1
|
||||||
color: "#DBDBDB"
|
color: "#DBDBDB"
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 same destination</b>"; icon: "../images/dropdownSend.png" }
|
||||||
|
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
|
||||||
|
}
|
||||||
|
|
||||||
|
Clipboard { id: clipboard }
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ Item {
|
||||||
property alias text: input.text
|
property alias text: input.text
|
||||||
property alias validator: input.validator
|
property alias validator: input.validator
|
||||||
property alias readOnly : input.readOnly
|
property alias readOnly : input.readOnly
|
||||||
|
property alias cursorPosition: input.cursorPosition
|
||||||
property int fontSize: 18
|
property int fontSize: 18
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ Item {
|
||||||
id: input
|
id: input
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: 4
|
anchors.leftMargin: 4
|
||||||
anchors.rightMargin: 4
|
anchors.rightMargin: 30
|
||||||
font.pixelSize: parent.fontSize
|
font.pixelSize: parent.fontSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ Dialog {
|
||||||
standardButtons: StandardButton.Ok + StandardButton.Cancel
|
standardButtons: StandardButton.Ok + StandardButton.Cancel
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: column
|
id: column
|
||||||
height: 40
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
|
|
@ -43,8 +43,13 @@ Window {
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
id: rootLayout
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: 30
|
||||||
|
anchors.rightMargin: 30
|
||||||
|
|
||||||
BusyIndicator {
|
BusyIndicator {
|
||||||
running: parent.visible
|
running: parent.visible
|
||||||
|
@ -59,6 +64,7 @@ Window {
|
||||||
}
|
}
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +75,7 @@ Window {
|
||||||
}
|
}
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@ MONERO_URL=https://github.com/monero-project/monero.git
|
||||||
MONERO_BRANCH=master
|
MONERO_BRANCH=master
|
||||||
# MONERO_URL=https://github.com/mbg033/monero.git
|
# MONERO_URL=https://github.com/mbg033/monero.git
|
||||||
# MONERO_BRANCH=develop
|
# MONERO_BRANCH=develop
|
||||||
|
# Buidling "debug" build optionally
|
||||||
|
BUILD_TYPE=$1
|
||||||
|
if [ -z $BUILD_TYPE ]; then
|
||||||
|
BUILD_TYPE=Release
|
||||||
|
fi
|
||||||
# thanks to SO: http://stackoverflow.com/a/20283965/4118915
|
# thanks to SO: http://stackoverflow.com/a/20283965/4118915
|
||||||
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
|
CPU_CORE_COUNT=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu)
|
||||||
pushd $(pwd)
|
pushd $(pwd)
|
||||||
|
@ -39,19 +44,19 @@ platform=$(get_platform)
|
||||||
if [ "$platform" == "darwin" ]; then
|
if [ "$platform" == "darwin" ]; then
|
||||||
# Do something under Mac OS X platform
|
# Do something under Mac OS X platform
|
||||||
echo "Configuring build for MacOS.."
|
echo "Configuring build for MacOS.."
|
||||||
cmake -D CMAKE_BUILD_TYPE=Release -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||||
elif [ "$platform" == "linux" ]; then
|
elif [ "$platform" == "linux" ]; then
|
||||||
# Do something under GNU/Linux platform
|
# Do something under GNU/Linux platform
|
||||||
echo "Configuring build for Linux.."
|
echo "Configuring build for Linux.."
|
||||||
cmake -D CMAKE_BUILD_TYPE=Release -D STATIC=ON -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" ../..
|
||||||
elif [ "$platform" == "mingw64" ]; then
|
elif [ "$platform" == "mingw64" ]; then
|
||||||
# Do something under Windows NT platform
|
# Do something under Windows NT platform
|
||||||
echo "Configuring build for MINGW64.."
|
echo "Configuring build for MINGW64.."
|
||||||
cmake -D CMAKE_BUILD_TYPE=Release -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
||||||
elif [ "$platform" == "mingw32" ]; then
|
elif [ "$platform" == "mingw32" ]; then
|
||||||
# Do something under Windows NT platform
|
# Do something under Windows NT platform
|
||||||
echo "Configuring build for MINGW32.."
|
echo "Configuring build for MINGW32.."
|
||||||
cmake -D CMAKE_BUILD_TYPE=Release -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
cmake -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D STATIC=ON -D BUILD_GUI_DEPS=ON -D INSTALL_VENDORED_LIBUNBOUND=ON -D CMAKE_INSTALL_PREFIX="$MONERO_DIR" -G "MSYS Makefiles" ../..
|
||||||
else
|
else
|
||||||
echo "Unsupported platform: $platform"
|
echo "Unsupported platform: $platform"
|
||||||
popd
|
popd
|
||||||
|
|
37
main.cpp
37
main.cpp
|
@ -39,8 +39,10 @@
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include "PendingTransaction.h"
|
#include "PendingTransaction.h"
|
||||||
#include "TranslationManager.h"
|
#include "TranslationManager.h"
|
||||||
|
#include "TransactionInfo.h"
|
||||||
|
#include "TransactionHistory.h"
|
||||||
|
#include "model/TransactionHistoryModel.h"
|
||||||
|
#include "model/TransactionHistorySortFilterModel.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -56,23 +58,38 @@ int main(int argc, char *argv[])
|
||||||
filter *eventFilter = new filter;
|
filter *eventFilter = new filter;
|
||||||
app.installEventFilter(eventFilter);
|
app.installEventFilter(eventFilter);
|
||||||
|
|
||||||
qmlRegisterType<clipboardAdapter>("moneroComponents", 1, 0, "Clipboard");
|
// registering types for QML
|
||||||
|
qmlRegisterType<clipboardAdapter>("moneroComponents.Clipboard", 1, 0, "Clipboard");
|
||||||
|
|
||||||
qmlRegisterUncreatableType<Wallet>("Bitmonero.Wallet", 1, 0, "Wallet", "Wallet can't be instantiated directly");
|
qmlRegisterUncreatableType<Wallet>("moneroComponents.Wallet", 1, 0, "Wallet", "Wallet can't be instantiated directly");
|
||||||
|
|
||||||
qmlRegisterUncreatableType<PendingTransaction>("Bitmonero.PendingTransaction", 1, 0, "PendingTransaction",
|
|
||||||
|
qmlRegisterUncreatableType<PendingTransaction>("moneroComponents.PendingTransaction", 1, 0, "PendingTransaction",
|
||||||
"PendingTransaction can't be instantiated directly");
|
"PendingTransaction can't be instantiated directly");
|
||||||
|
|
||||||
qmlRegisterUncreatableType<WalletManager>("Bitmonero.WalletManager", 1, 0, "WalletManager",
|
qmlRegisterUncreatableType<WalletManager>("moneroComponents.WalletManager", 1, 0, "WalletManager",
|
||||||
"WalletManager can't be instantiated directly");
|
"WalletManager can't be instantiated directly");
|
||||||
|
|
||||||
qmlRegisterUncreatableType<TranslationManager>("moneroComponents", 1, 0, "TranslationManager",
|
qmlRegisterUncreatableType<TranslationManager>("moneroComponents.TranslationManager", 1, 0, "TranslationManager",
|
||||||
"TranslationManager can't be instantiated directly");
|
"TranslationManager can't be instantiated directly");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<TransactionHistoryModel>("moneroComponents.TransactionHistoryModel", 1, 0, "TransactionHistoryModel",
|
||||||
|
"TransactionHistoryModel can't be instantiated directly");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<TransactionHistorySortFilterModel>("moneroComponents.TransactionHistorySortFilterModel", 1, 0, "TransactionHistorySortFilterModel",
|
||||||
|
"TransactionHistorySortFilterModel can't be instantiated directly");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<TransactionHistory>("moneroComponents.TransactionHistory", 1, 0, "TransactionHistory",
|
||||||
|
"TransactionHistory can't be instantiated directly");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<TransactionInfo>("moneroComponents.TransactionInfo", 1, 0, "TransactionInfo",
|
||||||
|
"TransactionHistory can't be instantiated directly");
|
||||||
|
|
||||||
qRegisterMetaType<PendingTransaction::Priority>();
|
qRegisterMetaType<PendingTransaction::Priority>();
|
||||||
|
qRegisterMetaType<TransactionInfo::Direction>();
|
||||||
|
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||||
|
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
|
|
||||||
|
|
114
main.qml
114
main.qml
|
@ -32,8 +32,9 @@ import QtQuick.Controls 1.1
|
||||||
import QtQuick.Controls.Styles 1.1
|
import QtQuick.Controls.Styles 1.1
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
import Bitmonero.Wallet 1.0
|
|
||||||
import Bitmonero.PendingTransaction 1.0
|
import moneroComponents.Wallet 1.0
|
||||||
|
import moneroComponents.PendingTransaction 1.0
|
||||||
|
|
||||||
|
|
||||||
import "components"
|
import "components"
|
||||||
|
@ -54,6 +55,10 @@ ApplicationWindow {
|
||||||
property alias password : passwordDialog.password
|
property alias password : passwordDialog.password
|
||||||
property int splashCounter: 0
|
property int splashCounter: 0
|
||||||
property bool isNewWallet: false
|
property bool isNewWallet: false
|
||||||
|
property int restoreHeight:0
|
||||||
|
|
||||||
|
// true if wallet ever synchronized
|
||||||
|
property bool walletInitialized : false
|
||||||
|
|
||||||
function altKeyReleased() { ctrlPressed = false; }
|
function altKeyReleased() { ctrlPressed = false; }
|
||||||
|
|
||||||
|
@ -138,15 +143,31 @@ ApplicationWindow {
|
||||||
middlePanel.paymentClicked.connect(handlePayment);
|
middlePanel.paymentClicked.connect(handlePayment);
|
||||||
// basicPanel.paymentClicked.connect(handlePayment);
|
// basicPanel.paymentClicked.connect(handlePayment);
|
||||||
|
|
||||||
|
// currentWallet is defined on daemon address change - close/reopen
|
||||||
|
if (currentWallet !== undefined) {
|
||||||
|
console.log("closing currentWallet")
|
||||||
|
walletManager.closeWallet(currentWallet);
|
||||||
|
}
|
||||||
|
|
||||||
// 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.settings['wallet'] !== 'undefined') {
|
||||||
|
console.log("using wizard wallet")
|
||||||
|
//Set restoreHeight
|
||||||
|
if(persistentSettings.restoreHeight > 0){
|
||||||
|
restoreHeight = persistentSettings.restoreHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("using wizard wallet")
|
||||||
|
|
||||||
connectWallet(wizard.settings['wallet'])
|
connectWallet(wizard.settings['wallet'])
|
||||||
|
|
||||||
isNewWallet = true
|
isNewWallet = true
|
||||||
|
// We don't need the wizard wallet any more - delete to avoid conflict with daemon adress change
|
||||||
|
delete wizard.settings['wallet']
|
||||||
} else {
|
} else {
|
||||||
var wallet_path = walletPath();
|
var wallet_path = walletPath();
|
||||||
// console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.password);
|
// console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.password);
|
||||||
console.log("opening wallet at: ", wallet_path);
|
console.log("opening wallet at: ", wallet_path, ", testnet: ", persistentSettings.testnet);
|
||||||
walletManager.openWalletAsync(wallet_path, appWindow.password,
|
walletManager.openWalletAsync(wallet_path, appWindow.password,
|
||||||
persistentSettings.testnet);
|
persistentSettings.testnet);
|
||||||
}
|
}
|
||||||
|
@ -159,11 +180,10 @@ ApplicationWindow {
|
||||||
currentWallet.refreshed.connect(onWalletRefresh)
|
currentWallet.refreshed.connect(onWalletRefresh)
|
||||||
currentWallet.updated.connect(onWalletUpdate)
|
currentWallet.updated.connect(onWalletUpdate)
|
||||||
currentWallet.newBlock.connect(onWalletNewBlock)
|
currentWallet.newBlock.connect(onWalletNewBlock)
|
||||||
|
currentWallet.moneySpent.connect(onWalletMoneySent)
|
||||||
|
currentWallet.moneyReceived.connect(onWalletMoneyReceived)
|
||||||
console.log("initializing with daemon address: ", persistentSettings.daemon_address)
|
console.log("initializing with daemon address: ", persistentSettings.daemon_address)
|
||||||
|
|
||||||
currentWallet.initAsync(persistentSettings.daemon_address, 0);
|
currentWallet.initAsync(persistentSettings.daemon_address, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function walletPath() {
|
function walletPath() {
|
||||||
|
@ -210,9 +230,8 @@ ApplicationWindow {
|
||||||
|
|
||||||
function onWalletUpdate() {
|
function onWalletUpdate() {
|
||||||
console.log(">>> wallet updated")
|
console.log(">>> wallet updated")
|
||||||
basicPanel.unlockedBalanceText = leftPanel.unlockedBalanceText =
|
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance);
|
||||||
walletManager.displayAmount(currentWallet.unlockedBalance);
|
middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance);
|
||||||
basicPanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletRefresh() {
|
function onWalletRefresh() {
|
||||||
|
@ -220,6 +239,9 @@ ApplicationWindow {
|
||||||
if (splash.visible) {
|
if (splash.visible) {
|
||||||
hideProcessingSplash()
|
hideProcessingSplash()
|
||||||
}
|
}
|
||||||
|
var dCurrentBlock = currentWallet.daemonBlockChainHeight();
|
||||||
|
var dTargetBlock = currentWallet.daemonBlockChainTargetHeight();
|
||||||
|
leftPanel.daemonProgress.updateProgress(dCurrentBlock,dTargetBlock);
|
||||||
|
|
||||||
// Store wallet after first refresh. To prevent broken wallet after a crash
|
// Store wallet after first refresh. To prevent broken wallet after a crash
|
||||||
// TODO: Move this to libwallet?
|
// TODO: Move this to libwallet?
|
||||||
|
@ -229,22 +251,49 @@ ApplicationWindow {
|
||||||
console.log("wallet stored after first successfull refresh")
|
console.log("wallet stored after first successfull refresh")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize transaction history once wallet is initializef first time;
|
||||||
|
if (!walletInitialized) {
|
||||||
|
currentWallet.history.refresh()
|
||||||
|
walletInitialized = true
|
||||||
|
}
|
||||||
|
|
||||||
leftPanel.networkStatus.connected = currentWallet.connected
|
leftPanel.networkStatus.connected = currentWallet.connected
|
||||||
|
|
||||||
onWalletUpdate();
|
onWalletUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletNewBlock(blockHeight) {
|
function onWalletNewBlock(blockHeight) {
|
||||||
if (splash.visible) {
|
if (splash.visible) {
|
||||||
var currHeight = blockHeight.toFixed(0)
|
var currHeight = blockHeight
|
||||||
if(currHeight > splashCounter + 1000){
|
|
||||||
|
//fast refresh until restoreHeight is reached
|
||||||
|
var increment = ((restoreHeight == 0) || currHeight < restoreHeight)? 1000 : 10
|
||||||
|
|
||||||
|
if(currHeight > splashCounter + increment){
|
||||||
splashCounter = currHeight
|
splashCounter = currHeight
|
||||||
var progressText = qsTr("Synchronizing blocks %1/%2").arg(currHeight).arg(currentWallet.daemonBlockChainHeight().toFixed(0));
|
var locale = Qt.locale()
|
||||||
|
var currHeightString = currHeight.toLocaleString(locale,"f",0)
|
||||||
|
var targetHeightString = currentWallet.daemonBlockChainHeight().toLocaleString(locale,"f",0)
|
||||||
|
var progressText = qsTr("Synchronizing blocks %1 / %2").arg(currHeightString).arg(targetHeightString);
|
||||||
console.log("Progress text: " + progressText);
|
console.log("Progress text: " + progressText);
|
||||||
splash.heightProgressText = progressText
|
splash.heightProgressText = progressText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onWalletMoneyReceived(txId, amount) {
|
||||||
|
// refresh transaction history here
|
||||||
|
currentWallet.refresh()
|
||||||
|
currentWallet.history.refresh() // this will refresh model
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWalletMoneySent(txId, amount) {
|
||||||
|
// refresh transaction history here
|
||||||
|
currentWallet.refresh()
|
||||||
|
currentWallet.history.refresh() // this will refresh model
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function walletsFound() {
|
function walletsFound() {
|
||||||
var wallets = walletManager.findWallets(moneroAccountsDir);
|
var wallets = walletManager.findWallets(moneroAccountsDir);
|
||||||
|
@ -338,7 +387,7 @@ ApplicationWindow {
|
||||||
middlePanel.enabled = enable;
|
middlePanel.enabled = enable;
|
||||||
leftPanel.enabled = enable;
|
leftPanel.enabled = enable;
|
||||||
rightPanel.enabled = enable;
|
rightPanel.enabled = enable;
|
||||||
basicPanel.enabled = enable;
|
// basicPanel.enabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showProcessingSplash(message) {
|
function showProcessingSplash(message) {
|
||||||
|
@ -396,6 +445,7 @@ ApplicationWindow {
|
||||||
property bool testnet: true
|
property bool testnet: true
|
||||||
property string daemon_address: "localhost:38081"
|
property string daemon_address: "localhost:38081"
|
||||||
property string payment_id
|
property string payment_id
|
||||||
|
property int restoreHeight:0
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace with customized popups
|
// TODO: replace with customized popups
|
||||||
|
@ -440,7 +490,7 @@ ApplicationWindow {
|
||||||
|
|
||||||
ProcessingSplash {
|
ProcessingSplash {
|
||||||
id: splash
|
id: splash
|
||||||
width: appWindow.width / 2
|
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 + appWindow.x
|
||||||
y: (appWindow.height - height) / 2 + appWindow.y
|
y: (appWindow.height - height) / 2 + appWindow.y
|
||||||
|
@ -514,7 +564,7 @@ ApplicationWindow {
|
||||||
MiddlePanel {
|
MiddlePanel {
|
||||||
id: middlePanel
|
id: middlePanel
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: leftPanel.right
|
anchors.left: leftPanel.visible ? leftPanel.right : parent.left
|
||||||
anchors.right: rightPanel.left
|
anchors.right: rightPanel.left
|
||||||
height: parent.height
|
height: parent.height
|
||||||
state: "Transfer"
|
state: "Transfer"
|
||||||
|
@ -526,16 +576,6 @@ ApplicationWindow {
|
||||||
visible: false
|
visible: false
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicPanel {
|
|
||||||
id: basicPanel
|
|
||||||
x: 0
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
visible: false
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: frameArea
|
id: frameArea
|
||||||
property bool blocked: false
|
property bool blocked: false
|
||||||
|
@ -591,25 +631,26 @@ ApplicationWindow {
|
||||||
duration: 200
|
duration: 200
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
targets: [leftPanel, middlePanel, rightPanel]
|
targets: [leftPanel, rightPanel]
|
||||||
properties: "visible"
|
properties: "visible"
|
||||||
value: false
|
value: false
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
target: basicPanel
|
target: middlePanel
|
||||||
properties: "visible"
|
properties: "basicMode"
|
||||||
value: true
|
value: true
|
||||||
}
|
}
|
||||||
|
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
target: appWindow
|
target: appWindow
|
||||||
properties: "height"
|
properties: "height"
|
||||||
to: basicPanel.height
|
to: middlePanel.height
|
||||||
easing.type: Easing.InCubic
|
easing.type: Easing.InCubic
|
||||||
duration: 200
|
duration: 200
|
||||||
}
|
}
|
||||||
|
|
||||||
onStopped: {
|
onStopped: {
|
||||||
middlePanel.visible = false
|
// middlePanel.visible = false
|
||||||
rightPanel.visible = false
|
rightPanel.visible = false
|
||||||
leftPanel.visible = false
|
leftPanel.visible = false
|
||||||
}
|
}
|
||||||
|
@ -625,8 +666,8 @@ ApplicationWindow {
|
||||||
duration: 200
|
duration: 200
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
target: basicPanel
|
target: middlePanel
|
||||||
properties: "visible"
|
properties: "basicMode"
|
||||||
value: false
|
value: false
|
||||||
}
|
}
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
|
@ -719,8 +760,13 @@ ApplicationWindow {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
onGoToBasicVersion: {
|
onGoToBasicVersion: {
|
||||||
if(yes) goToBasicAnimation.start()
|
if (yes) {
|
||||||
else goToProAnimation.start()
|
// basicPanel.currentView = middlePanel.currentView
|
||||||
|
goToBasicAnimation.start()
|
||||||
|
} else {
|
||||||
|
// middlePanel.currentView = basicPanel.currentView
|
||||||
|
goToProAnimation.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
|
@ -10,7 +10,8 @@ CONFIG += c++11
|
||||||
QMAKE_DISTCLEAN += -r $$WALLET_ROOT
|
QMAKE_DISTCLEAN += -r $$WALLET_ROOT
|
||||||
|
|
||||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
INCLUDEPATH += $$WALLET_ROOT/include \
|
||||||
$$PWD/src/libwalletqt
|
$$PWD/src/libwalletqt \
|
||||||
|
$$PWD/src
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
filter.h \
|
filter.h \
|
||||||
|
@ -22,7 +23,9 @@ HEADERS += \
|
||||||
src/libwalletqt/TransactionHistory.h \
|
src/libwalletqt/TransactionHistory.h \
|
||||||
src/libwalletqt/TransactionInfo.h \
|
src/libwalletqt/TransactionInfo.h \
|
||||||
oshelper.h \
|
oshelper.h \
|
||||||
TranslationManager.h
|
TranslationManager.h \
|
||||||
|
src/model/TransactionHistoryModel.h \
|
||||||
|
src/model/TransactionHistorySortFilterModel.h
|
||||||
|
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
|
@ -35,7 +38,9 @@ SOURCES += main.cpp \
|
||||||
src/libwalletqt/TransactionHistory.cpp \
|
src/libwalletqt/TransactionHistory.cpp \
|
||||||
src/libwalletqt/TransactionInfo.cpp \
|
src/libwalletqt/TransactionInfo.cpp \
|
||||||
oshelper.cpp \
|
oshelper.cpp \
|
||||||
TranslationManager.cpp
|
TranslationManager.cpp \
|
||||||
|
src/model/TransactionHistoryModel.cpp \
|
||||||
|
src/model/TransactionHistorySortFilterModel.cpp
|
||||||
|
|
||||||
lupdate_only {
|
lupdate_only {
|
||||||
SOURCES = *.qml \
|
SOURCES = *.qml \
|
||||||
|
|
|
@ -27,10 +27,28 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
|
|
||||||
|
import moneroComponents.Wallet 1.0
|
||||||
|
import moneroComponents.WalletManager 1.0
|
||||||
|
import moneroComponents.TransactionHistory 1.0
|
||||||
|
import moneroComponents.TransactionInfo 1.0
|
||||||
|
import moneroComponents.TransactionHistoryModel 1.0
|
||||||
|
|
||||||
import "../components"
|
import "../components"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
property var model
|
||||||
|
|
||||||
color: "#F0EEEE"
|
color: "#F0EEEE"
|
||||||
|
onModelChanged: {
|
||||||
|
if (typeof model !== 'undefined') {
|
||||||
|
// setup date filter scope according to real transactions
|
||||||
|
fromDatePicker.currentDate = model.transactionHistory.firstDateTime
|
||||||
|
toDatePicker.currentDate = model.transactionHistory.lastDateTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: filterHeaderText
|
id: filterHeaderText
|
||||||
|
@ -47,6 +65,8 @@ Rectangle {
|
||||||
text: qsTr("Filter transactions history") + translationManager.emptyString
|
text: qsTr("Filter transactions history") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter by Address input (senseless, removing)
|
||||||
|
/*
|
||||||
Label {
|
Label {
|
||||||
id: addressLabel
|
id: addressLabel
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -67,11 +87,14 @@ Rectangle {
|
||||||
anchors.rightMargin: 17
|
anchors.rightMargin: 17
|
||||||
anchors.topMargin: 5
|
anchors.topMargin: 5
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Filter by Payment ID input
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: paymentIdLabel
|
id: paymentIdLabel
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: addressLine.bottom
|
anchors.top: filterHeaderText.bottom // addressLine.bottom
|
||||||
anchors.leftMargin: 17
|
anchors.leftMargin: 17
|
||||||
anchors.topMargin: 17
|
anchors.topMargin: 17
|
||||||
text: qsTr("Payment ID <font size='2'>(Optional)</font>") + translationManager.emptyString
|
text: qsTr("Payment ID <font size='2'>(Optional)</font>") + translationManager.emptyString
|
||||||
|
@ -84,12 +107,16 @@ Rectangle {
|
||||||
id: paymentIdLine
|
id: paymentIdLine
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: paymentIdLabel.bottom
|
anchors.top: paymentIdLabel.bottom // addressLabel.bottom
|
||||||
anchors.leftMargin: 17
|
anchors.leftMargin: 17
|
||||||
anchors.rightMargin: 17
|
anchors.rightMargin: 17
|
||||||
anchors.topMargin: 5
|
anchors.topMargin: 5
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter by description input (not implemented yet)
|
||||||
|
/*
|
||||||
Label {
|
Label {
|
||||||
id: descriptionLabel
|
id: descriptionLabel
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -110,11 +137,14 @@ Rectangle {
|
||||||
anchors.rightMargin: 17
|
anchors.rightMargin: 17
|
||||||
anchors.topMargin: 5
|
anchors.topMargin: 5
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// DateFrom picker
|
||||||
Label {
|
Label {
|
||||||
id: dateFromText
|
id: dateFromText
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: descriptionLine.bottom
|
anchors.top: paymentIdLine.bottom // descriptionLine.bottom
|
||||||
anchors.leftMargin: 17
|
anchors.leftMargin: 17
|
||||||
anchors.topMargin: 17
|
anchors.topMargin: 17
|
||||||
width: 156
|
width: 156
|
||||||
|
@ -132,10 +162,11 @@ Rectangle {
|
||||||
z: 2
|
z: 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DateTo picker
|
||||||
Label {
|
Label {
|
||||||
id: dateToText
|
id: dateToText
|
||||||
anchors.left: dateFromText.right
|
anchors.left: dateFromText.right
|
||||||
anchors.top: descriptionLine.bottom
|
anchors.top: paymentIdLine.bottom //descriptionLine.bottom
|
||||||
anchors.leftMargin: 17
|
anchors.leftMargin: 17
|
||||||
anchors.topMargin: 17
|
anchors.topMargin: 17
|
||||||
text: qsTr("To")
|
text: qsTr("To")
|
||||||
|
@ -163,10 +194,30 @@ Rectangle {
|
||||||
shadowPressedColor: "#2D002F"
|
shadowPressedColor: "#2D002F"
|
||||||
releasedColor: "#6B0072"
|
releasedColor: "#6B0072"
|
||||||
pressedColor: "#4D0051"
|
pressedColor: "#4D0051"
|
||||||
|
onClicked: {
|
||||||
|
// Apply filter here;
|
||||||
|
model.paymentIdFilter = paymentIdLine.text
|
||||||
|
model.dateFromFilter = fromDatePicker.currentDate
|
||||||
|
model.dateToFilter = toDatePicker.currentDate
|
||||||
|
if (advancedFilteringCheckBox.checked) {
|
||||||
|
if (amountFromLine.text.length) {
|
||||||
|
model.amountFromFilter = parseFloat(amountFromLine.text)
|
||||||
|
}
|
||||||
|
if (amountToLine.text.length) {
|
||||||
|
model.amountToFilter = parseFloat(amountToLine.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
var directionFilter = transactionsModel.get(transactionTypeDropdown.currentIndex).value
|
||||||
|
console.log("Direction filter: " + directionFilter)
|
||||||
|
model.directionFilter = directionFilter
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBox {
|
CheckBox {
|
||||||
id: checkBox
|
id: advancedFilteringCheckBox
|
||||||
text: qsTr("Advance filtering")
|
text: qsTr("Advance filtering")
|
||||||
anchors.left: filterButton.right
|
anchors.left: filterButton.right
|
||||||
anchors.bottom: filterButton.bottom
|
anchors.bottom: filterButton.bottom
|
||||||
|
@ -193,9 +244,10 @@ Rectangle {
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: transactionsModel
|
id: transactionsModel
|
||||||
ListElement { column1: "SENT"; column2: "" }
|
ListElement { column1: "ALL"; column2: ""; value: TransactionInfo.Direction_Both }
|
||||||
ListElement { column1: "RECIVE"; column2: "" }
|
ListElement { column1: "SENT"; column2: ""; value: TransactionInfo.Direction_Out }
|
||||||
ListElement { column1: "ON HOLD"; column2: "" }
|
ListElement { column1: "RECEIVED"; column2: ""; value: TransactionInfo.Direction_In }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StandardDropdown {
|
StandardDropdown {
|
||||||
|
@ -274,8 +326,11 @@ Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
parent.expanded = !parent.expanded
|
parent.expanded = !parent.expanded
|
||||||
if(checkBox.checked) tableRect.height = Qt.binding(function(){ return parent.expanded ? tableRect.expandedHeight : tableRect.collapsedHeight })
|
if (advancedFilteringCheckBox.checked) {
|
||||||
else tableRect.height = Qt.binding(function(){ return parent.expanded ? tableRect.expandedHeight : tableRect.middleHeight })
|
tableRect.height = Qt.binding(function() { return parent.expanded ? tableRect.expandedHeight : tableRect.collapsedHeight })
|
||||||
|
} else {
|
||||||
|
tableRect.height = Qt.binding(function() { return parent.expanded ? tableRect.expandedHeight : tableRect.middleHeight })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,10 +367,11 @@ Rectangle {
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: columnsModel
|
id: columnsModel
|
||||||
ListElement { columnName: "Address"; columnWidth: 127 }
|
|
||||||
|
ListElement { columnName: "Payment ID"; columnWidth: 127 }
|
||||||
ListElement { columnName: "Date"; columnWidth: 100 }
|
ListElement { columnName: "Date"; columnWidth: 100 }
|
||||||
ListElement { columnName: "Amount"; columnWidth: 148 }
|
ListElement { columnName: "Amount"; columnWidth: 148 }
|
||||||
ListElement { columnName: "Description"; columnWidth: 148 }
|
// ListElement { columnName: "Description"; columnWidth: 148 }
|
||||||
}
|
}
|
||||||
|
|
||||||
TableHeader {
|
TableHeader {
|
||||||
|
@ -328,21 +384,24 @@ Rectangle {
|
||||||
anchors.rightMargin: 14
|
anchors.rightMargin: 14
|
||||||
dataModel: columnsModel
|
dataModel: columnsModel
|
||||||
offset: 20
|
offset: 20
|
||||||
onSortRequest: console.log("column: " + column + " desc: " + desc)
|
onSortRequest: {
|
||||||
}
|
console.log("column: " + column + " desc: " + desc)
|
||||||
|
switch (column) {
|
||||||
ListModel {
|
case 0:
|
||||||
id: testModel
|
// Payment ID
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: "Client from Australia"; out: false }
|
model.sortRole = TransactionHistoryModel.TransactionPaymentIdRole
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: true }
|
break;
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: true }
|
case 1:
|
||||||
ListElement { paymentId: ""; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: false }
|
// Date;
|
||||||
ListElement { paymentId: ""; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: "Client from Australia"; out: false }
|
model.sortRole = TransactionHistoryModel.TransactionDateRole
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: false }
|
break;
|
||||||
ListElement { paymentId: ""; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: false }
|
case 2:
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: false }
|
// Amount;
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: "Client from Australia"; out: false }
|
model.sortRole = TransactionHistoryModel.TransactionAmountRole
|
||||||
ListElement { paymentId: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; address: "faef56b9acf67a7dba75ec01f403497049d7cff111628edfe7b57278554dc798"; date: "Jan 12, 2014"; time: "12:23 <font size='2'>AM</font>"; amount: "0.<font size='2'>000709159241</font>"; balance: "19301.<font size='2'>870709159241</font>"; description: ""; out: false }
|
break;
|
||||||
|
}
|
||||||
|
model.sort(0, desc ? Qt.DescendingOrder : Qt.AscendingOrder)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scroll {
|
Scroll {
|
||||||
|
@ -363,7 +422,7 @@ Rectangle {
|
||||||
anchors.leftMargin: 14
|
anchors.leftMargin: 14
|
||||||
anchors.rightMargin: 14
|
anchors.rightMargin: 14
|
||||||
onContentYChanged: flickableScroll.flickableContentYChanged()
|
onContentYChanged: flickableScroll.flickableContentYChanged()
|
||||||
model: testModel
|
model: root.model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
// Copyright (c) 2014-2015, The Monero Project
|
// Copyright (c) 2014-2015, The Monero Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
// permitted provided that the following conditions are met:
|
// permitted provided that the following conditions are met:
|
||||||
//
|
//
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
// conditions and the following disclaimer.
|
// conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
// 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
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
// materials provided with the distribution.
|
// materials provided with the distribution.
|
||||||
//
|
//
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
// 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
|
// used to endorse or promote products derived from this software without specific
|
||||||
// prior written permission.
|
// prior written permission.
|
||||||
//
|
//
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
// 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
|
// 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
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
@ -32,7 +32,7 @@ import QtQuick.Controls.Styles 1.4
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
|
|
||||||
import "../components"
|
import "../components"
|
||||||
import moneroComponents 1.0
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
||||||
|
@ -43,14 +43,14 @@ Rectangle {
|
||||||
|
|
||||||
function updatePaymentId() {
|
function updatePaymentId() {
|
||||||
var payment_id = appWindow.persistentSettings.payment_id
|
var payment_id = appWindow.persistentSettings.payment_id
|
||||||
if (payment_id.length === 0) {
|
if (typeof appWindow.currentWallet !== 'undefined') {
|
||||||
payment_id = appWindow.wallet.generatePaymentId()
|
payment_id = appWindow.currentWallet.generatePaymentId()
|
||||||
appWindow.persistentSettings.payment_id = payment_id
|
appWindow.persistentSettings.payment_id = payment_id
|
||||||
appWindow.currentWallet.payment_id = payment_id
|
addressLine.text = appWindow.currentWallet.address
|
||||||
|
integratedAddressLine.text = appWindow.currentWallet.integratedAddress(payment_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
paymentIdLine.text = payment_id
|
paymentIdLine.text = payment_id
|
||||||
addressLine.text = appWindow.currentWallet.address
|
|
||||||
integratedAddressLine.text = appWindow.currentWallet.integratedAddress(payment_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipboard { id: clipboard }
|
Clipboard { id: clipboard }
|
||||||
|
@ -87,6 +87,8 @@ Rectangle {
|
||||||
readOnly: true
|
readOnly: true
|
||||||
width: mainLayout.editWidth
|
width: mainLayout.editWidth
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
onTextChanged: cursorPosition = 0
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
imageSource: "../images/copyToClipboard.png"
|
imageSource: "../images/copyToClipboard.png"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -116,6 +118,9 @@ Rectangle {
|
||||||
readOnly: true
|
readOnly: true
|
||||||
width: mainLayout.editWidth
|
width: mainLayout.editWidth
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
onTextChanged: cursorPosition = 0
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
imageSource: "../images/copyToClipboard.png"
|
imageSource: "../images/copyToClipboard.png"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -176,9 +181,13 @@ Rectangle {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
function onPageCompleted() {
|
||||||
console.log("Receive page loaded");
|
console.log("Receive page loaded");
|
||||||
updatePaymentId()
|
|
||||||
|
if(addressLine.text.length == 0) {
|
||||||
|
updatePaymentId()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,264 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
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 "../components"
|
||||||
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 100
|
|
||||||
height: 62
|
property var daemonAddress
|
||||||
|
|
||||||
|
color: "#F0EEEE"
|
||||||
|
|
||||||
|
Clipboard { id: clipboard }
|
||||||
|
|
||||||
|
function initSettings() {
|
||||||
|
|
||||||
|
|
||||||
|
// Mnemonic seed settings
|
||||||
|
memoTextInput.text = qsTr("Click button to show seed") + translationManager.emptyString
|
||||||
|
showSeedButton.visible = true
|
||||||
|
|
||||||
|
// Daemon settings
|
||||||
|
|
||||||
|
daemonAddress = persistentSettings.daemon_address.split(":");
|
||||||
|
console.log("address: " + persistentSettings.daemon_address)
|
||||||
|
// try connecting to daemon
|
||||||
|
var connectedToDaemon = currentWallet.connectToDaemon();
|
||||||
|
|
||||||
|
if(!connectedToDaemon){
|
||||||
|
console.log("not connected");
|
||||||
|
//TODO: Print error?
|
||||||
|
//daemonStatusText.text = qsTr("Unable to connect to Daemon.")
|
||||||
|
//daemonStatusText.visible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PasswordDialog {
|
||||||
|
id: settingsPasswordDialog
|
||||||
|
standardButtons: StandardButton.Ok + StandardButton.Cancel
|
||||||
|
onAccepted: {
|
||||||
|
if(appWindow.password == settingsPasswordDialog.password){
|
||||||
|
memoTextInput.text = currentWallet.seed
|
||||||
|
showSeedButton.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
onRejected: {
|
||||||
|
|
||||||
|
}
|
||||||
|
onDiscard: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: mainLayout
|
||||||
|
anchors.margins: 40
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: seedLabel
|
||||||
|
color: "#4A4949"
|
||||||
|
fontSize: 16
|
||||||
|
text: qsTr("Mnemonic seed: ") + translationManager.emptyString
|
||||||
|
Layout.preferredWidth: 100
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: memoTextInput
|
||||||
|
textMargin: 6
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pointSize: 14
|
||||||
|
wrapMode: TextEdit.WordWrap
|
||||||
|
readOnly: true
|
||||||
|
selectByMouse: true
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 100
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
text: qsTr("Click button to show seed") + translationManager.emptyString
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id : clipboardButton
|
||||||
|
anchors.right: memoTextInput.right
|
||||||
|
anchors.bottom: memoTextInput.bottom
|
||||||
|
source: "qrc:///images/greyTriangle.png"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: "qrc:///images/copyToClipboard.png"
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: clipboard.setText(memoTextInput.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Text {
|
||||||
|
id: wordsTipText
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pointSize: 12
|
||||||
|
color: "#4A4646"
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: qsTr("It is very important to write it down as this is the only backup you will need for your wallet.")
|
||||||
|
+ translationManager.emptyString
|
||||||
|
}
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
|
||||||
|
id: showSeedButton
|
||||||
|
|
||||||
|
fontSize: 14
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
text: qsTr("Show seed")
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
Layout.preferredWidth: 100
|
||||||
|
onClicked: {
|
||||||
|
settingsPasswordDialog.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: "#DEDEDE"
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: daemonAddrRow
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 40
|
||||||
|
Layout.topMargin: 40
|
||||||
|
spacing: 10
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: daemonAddrLabel
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
color: "#4A4949"
|
||||||
|
text: qsTr("Daemon adress") + translationManager.emptyString
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
LineEdit {
|
||||||
|
id: daemonAddr
|
||||||
|
Layout.preferredWidth: 200
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: (daemonAddress !== undefined) ? daemonAddress[0] : ""
|
||||||
|
placeholderText: qsTr("Hostname / IP")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LineEdit {
|
||||||
|
id: daemonPort
|
||||||
|
Layout.preferredWidth: 100
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: (daemonAddress !== undefined) ? daemonAddress[1] : ""
|
||||||
|
placeholderText: qsTr("Port")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
id: daemonAddrSave
|
||||||
|
|
||||||
|
Layout.fillWidth: false
|
||||||
|
|
||||||
|
Layout.leftMargin: 30
|
||||||
|
Layout.minimumWidth: 100
|
||||||
|
width: 60
|
||||||
|
text: qsTr("Save") + translationManager.emptyString
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
visible: true
|
||||||
|
onClicked: {
|
||||||
|
console.log("saving daemon adress settings")
|
||||||
|
var newDaemon = daemonAddr.text + ":" + daemonPort.text
|
||||||
|
if(persistentSettings.daemon_address != newDaemon) {
|
||||||
|
persistentSettings.daemon_address = newDaemon
|
||||||
|
//reconnect wallet
|
||||||
|
appWindow.initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: daemonStatusRow
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: daemonStatusText
|
||||||
|
font.family: "Arial"
|
||||||
|
font.pixelSize: 18
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
textFormat: Text.RichText
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
color: "#FF0000"
|
||||||
|
visible: true //!currentWallet.connected
|
||||||
|
}
|
||||||
|
|
||||||
|
// StandardButton {
|
||||||
|
// id: checkConnectionButton
|
||||||
|
// anchors.left: daemonStatusText.right
|
||||||
|
// anchors.leftMargin: 30
|
||||||
|
// width: 90
|
||||||
|
// text: qsTr("Check again") + translationManager.emptyString
|
||||||
|
// shadowReleasedColor: "#FF4304"
|
||||||
|
// shadowPressedColor: "#B32D00"
|
||||||
|
// releasedColor: "#FF6C3C"
|
||||||
|
// pressedColor: "#FF4304"
|
||||||
|
// visible: true
|
||||||
|
// onClicked: {
|
||||||
|
// checkDaemonConnection();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function onPageCompleted() {
|
||||||
|
console.log("Settings page loaded");
|
||||||
|
initSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import Bitmonero.PendingTransaction 1.0
|
import moneroComponents.PendingTransaction 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
|
|
||||||
|
|
||||||
|
|
1
qml.qrc
1
qml.qrc
|
@ -116,5 +116,6 @@
|
||||||
<file>lang/flags/italy.png</file>
|
<file>lang/flags/italy.png</file>
|
||||||
<file>components/PasswordDialog.qml</file>
|
<file>components/PasswordDialog.qml</file>
|
||||||
<file>components/ProcessingSplash.qml</file>
|
<file>components/ProcessingSplash.qml</file>
|
||||||
|
<file>components/DaemonProgress.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -2,49 +2,89 @@
|
||||||
#include "TransactionInfo.h"
|
#include "TransactionInfo.h"
|
||||||
#include <wallet/wallet2_api.h>
|
#include <wallet/wallet2_api.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
int TransactionHistory::count() const
|
|
||||||
{
|
|
||||||
return m_pimpl->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionInfo *TransactionHistory::transaction(int index)
|
TransactionInfo *TransactionHistory::transaction(int index)
|
||||||
{
|
{
|
||||||
// box up Bitmonero::TransactionInfo
|
|
||||||
Bitmonero::TransactionInfo * impl = m_pimpl->transaction(index);
|
if (index < 0 || index >= m_tinfo.size()) {
|
||||||
TransactionInfo * result = new TransactionInfo(impl, this);
|
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
|
||||||
return result;
|
qCritical("%s: there's %d transactions in backend", __FUNCTION__, m_pimpl->count());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return m_tinfo.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionInfo *TransactionHistory::transaction(const QString &id)
|
//// XXX: not sure if this method really needed;
|
||||||
{
|
//TransactionInfo *TransactionHistory::transaction(const QString &id)
|
||||||
// box up Bitmonero::TransactionInfo
|
//{
|
||||||
Bitmonero::TransactionInfo * impl = m_pimpl->transaction(id.toStdString());
|
// return nullptr;
|
||||||
TransactionInfo * result = new TransactionInfo(impl, this);
|
//}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<TransactionInfo *> TransactionHistory::getAll() const
|
QList<TransactionInfo *> TransactionHistory::getAll() const
|
||||||
{
|
{
|
||||||
|
// XXX this invalidates previously saved history that might be used by model
|
||||||
|
emit refreshStarted();
|
||||||
qDeleteAll(m_tinfo);
|
qDeleteAll(m_tinfo);
|
||||||
m_tinfo.clear();
|
m_tinfo.clear();
|
||||||
|
|
||||||
|
QDateTime firstDateTime = QDateTime::currentDateTime();
|
||||||
|
QDateTime lastDateTime = QDateTime(QDate(1970, 1, 1));
|
||||||
|
|
||||||
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
|
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
|
||||||
for (const auto i : m_pimpl->getAll()) {
|
for (const auto i : m_pimpl->getAll()) {
|
||||||
TransactionInfo * ti = new TransactionInfo(i, parent);
|
TransactionInfo * ti = new TransactionInfo(i, parent);
|
||||||
m_tinfo.append(ti);
|
m_tinfo.append(ti);
|
||||||
|
// looking for transactions timestamp scope
|
||||||
|
if (ti->timestamp() >= lastDateTime) {
|
||||||
|
lastDateTime = ti->timestamp();
|
||||||
|
}
|
||||||
|
if (ti->timestamp() <= firstDateTime) {
|
||||||
|
firstDateTime = ti->timestamp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
emit refreshFinished();
|
||||||
|
|
||||||
|
if (m_firstDateTime != firstDateTime) {
|
||||||
|
m_firstDateTime = firstDateTime;
|
||||||
|
emit firstDateTimeChanged();
|
||||||
|
}
|
||||||
|
if (m_lastDateTime != lastDateTime) {
|
||||||
|
m_lastDateTime = lastDateTime;
|
||||||
|
emit lastDateTimeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
return m_tinfo;
|
return m_tinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransactionHistory::refresh()
|
void TransactionHistory::refresh()
|
||||||
{
|
{
|
||||||
// XXX this invalidates previously saved history that might be used by clients
|
// rebuilding transaction list in wallet_api;
|
||||||
m_pimpl->refresh();
|
m_pimpl->refresh();
|
||||||
emit invalidated();
|
// copying list here and keep track on every item to avoid memleaks
|
||||||
|
getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint64 TransactionHistory::count() const
|
||||||
|
{
|
||||||
|
return m_tinfo.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime TransactionHistory::firstDateTime() const
|
||||||
|
{
|
||||||
|
return m_firstDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime TransactionHistory::lastDateTime() const
|
||||||
|
{
|
||||||
|
return m_lastDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TransactionHistory::TransactionHistory(Bitmonero::TransactionHistory *pimpl, QObject *parent)
|
TransactionHistory::TransactionHistory(Bitmonero::TransactionHistory *pimpl, QObject *parent)
|
||||||
: QObject(parent), m_pimpl(pimpl)
|
: QObject(parent), m_pimpl(pimpl)
|
||||||
{
|
{
|
||||||
|
m_firstDateTime = QDateTime(QDate(1970, 1, 1));
|
||||||
|
m_lastDateTime = QDateTime::currentDateTime();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
namespace Bitmonero {
|
namespace Bitmonero {
|
||||||
class TransactionHistory;
|
class TransactionHistory;
|
||||||
|
@ -14,16 +15,23 @@ class TransactionHistory : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int count READ count)
|
Q_PROPERTY(int count READ count)
|
||||||
|
Q_PROPERTY(QDateTime firstDateTime READ firstDateTime NOTIFY firstDateTimeChanged)
|
||||||
|
Q_PROPERTY(QDateTime lastDateTime READ lastDateTime NOTIFY lastDateTimeChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int count() const;
|
|
||||||
Q_INVOKABLE TransactionInfo *transaction(int index);
|
Q_INVOKABLE TransactionInfo *transaction(int index);
|
||||||
Q_INVOKABLE TransactionInfo * transaction(const QString &id);
|
// Q_INVOKABLE TransactionInfo * transaction(const QString &id);
|
||||||
Q_INVOKABLE QList<TransactionInfo*> getAll() const;
|
Q_INVOKABLE QList<TransactionInfo*> getAll() const;
|
||||||
Q_INVOKABLE void refresh();
|
Q_INVOKABLE void refresh();
|
||||||
|
quint64 count() const;
|
||||||
|
QDateTime firstDateTime() const;
|
||||||
|
QDateTime lastDateTime() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void invalidated();
|
void refreshStarted() const;
|
||||||
|
void refreshFinished() const;
|
||||||
|
void firstDateTimeChanged() const;
|
||||||
|
void lastDateTimeChanged() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
|
@ -36,6 +44,8 @@ private:
|
||||||
|
|
||||||
Bitmonero::TransactionHistory * m_pimpl;
|
Bitmonero::TransactionHistory * m_pimpl;
|
||||||
mutable QList<TransactionInfo*> m_tinfo;
|
mutable QList<TransactionInfo*> m_tinfo;
|
||||||
|
mutable QDateTime m_firstDateTime;
|
||||||
|
mutable QDateTime m_lastDateTime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include "TransactionInfo.h"
|
#include "TransactionInfo.h"
|
||||||
|
#include "WalletManager.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
TransactionInfo::Direction TransactionInfo::direction() const
|
TransactionInfo::Direction TransactionInfo::direction() const
|
||||||
|
@ -16,15 +18,21 @@ bool TransactionInfo::isFailed() const
|
||||||
return m_pimpl->isFailed();
|
return m_pimpl->isFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 TransactionInfo::amount() const
|
|
||||||
|
double TransactionInfo::amount() const
|
||||||
{
|
{
|
||||||
return m_pimpl->amount();
|
// there's no unsigned uint64 for JS, so better use double
|
||||||
|
return WalletManager::instance()->displayAmount(m_pimpl->amount()).toDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 TransactionInfo::fee() const
|
QString TransactionInfo::displayAmount() const
|
||||||
{
|
{
|
||||||
return m_pimpl->fee();
|
return WalletManager::instance()->displayAmount(m_pimpl->amount());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionInfo::fee() const
|
||||||
|
{
|
||||||
|
return WalletManager::instance()->displayAmount(m_pimpl->fee());
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 TransactionInfo::blockHeight() const
|
quint64 TransactionInfo::blockHeight() const
|
||||||
|
@ -37,13 +45,23 @@ QString TransactionInfo::hash() const
|
||||||
return QString::fromStdString(m_pimpl->hash());
|
return QString::fromStdString(m_pimpl->hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TransactionInfo::timestamp()
|
QDateTime TransactionInfo::timestamp() const
|
||||||
{
|
{
|
||||||
QString result = QDateTime::fromTime_t(m_pimpl->timestamp()).toString(Qt::ISODate);
|
QDateTime result = QDateTime::fromTime_t(m_pimpl->timestamp());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TransactionInfo::paymentId()
|
QString TransactionInfo::date() const
|
||||||
|
{
|
||||||
|
return timestamp().date().toString(Qt::ISODate);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionInfo::time() const
|
||||||
|
{
|
||||||
|
return timestamp().time().toString(Qt::ISODate);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionInfo::paymentId() const
|
||||||
{
|
{
|
||||||
return QString::fromStdString(m_pimpl->paymentId());
|
return QString::fromStdString(m_pimpl->paymentId());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#ifndef TRANSACTIONINFO_H
|
#ifndef TRANSACTIONINFO_H
|
||||||
#define TRANSACTIONINFO_H
|
#define TRANSACTIONINFO_H
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <wallet/wallet2_api.h>
|
#include <wallet/wallet2_api.h>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
class TransactionInfo : public QObject
|
class TransactionInfo : public QObject
|
||||||
{
|
{
|
||||||
|
@ -10,19 +11,25 @@ class TransactionInfo : public QObject
|
||||||
Q_PROPERTY(Direction direction READ direction)
|
Q_PROPERTY(Direction direction READ direction)
|
||||||
Q_PROPERTY(bool isPending READ isPending)
|
Q_PROPERTY(bool isPending READ isPending)
|
||||||
Q_PROPERTY(bool isFailed READ isFailed)
|
Q_PROPERTY(bool isFailed READ isFailed)
|
||||||
Q_PROPERTY(quint64 amount READ amount)
|
Q_PROPERTY(double amount READ amount)
|
||||||
Q_PROPERTY(quint64 fee READ fee)
|
Q_PROPERTY(QString displayAmount READ displayAmount)
|
||||||
|
Q_PROPERTY(QString fee READ fee)
|
||||||
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
Q_PROPERTY(quint64 blockHeight READ blockHeight)
|
||||||
Q_PROPERTY(QString hash READ hash)
|
Q_PROPERTY(QString hash READ hash)
|
||||||
Q_PROPERTY(QString timestamp READ timestamp)
|
Q_PROPERTY(QDateTime timestamp READ timestamp)
|
||||||
|
Q_PROPERTY(QString date READ date)
|
||||||
|
Q_PROPERTY(QString time READ time)
|
||||||
Q_PROPERTY(QString paymentId READ paymentId)
|
Q_PROPERTY(QString paymentId READ paymentId)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Direction {
|
enum Direction {
|
||||||
Direction_In = Bitmonero::TransactionInfo::Direction_In,
|
Direction_In = Bitmonero::TransactionInfo::Direction_In,
|
||||||
Direction_Out = Bitmonero::TransactionInfo::Direction_Out
|
Direction_Out = Bitmonero::TransactionInfo::Direction_Out,
|
||||||
|
Direction_Both // invalid direction value, used for filtering
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_ENUM(Direction)
|
||||||
|
|
||||||
// TODO: implement as separate class;
|
// TODO: implement as separate class;
|
||||||
|
|
||||||
// struct Transfer {
|
// struct Transfer {
|
||||||
|
@ -30,16 +37,21 @@ public:
|
||||||
// const uint64_t amount;
|
// const uint64_t amount;
|
||||||
// const std::string address;
|
// const std::string address;
|
||||||
// };
|
// };
|
||||||
|
|
||||||
Direction direction() const;
|
Direction direction() const;
|
||||||
bool isPending() const;
|
bool isPending() const;
|
||||||
bool isFailed() const;
|
bool isFailed() const;
|
||||||
quint64 amount() const;
|
double amount() const;
|
||||||
quint64 fee() const;
|
QString displayAmount() const;
|
||||||
|
QString fee() const;
|
||||||
quint64 blockHeight() const;
|
quint64 blockHeight() const;
|
||||||
//! transaction_id
|
//! transaction_id
|
||||||
QString hash() const;
|
QString hash() const;
|
||||||
QString timestamp();
|
QDateTime timestamp() const;
|
||||||
QString paymentId();
|
QString date() const;
|
||||||
|
QString time() const;
|
||||||
|
QString paymentId() const;
|
||||||
|
|
||||||
|
|
||||||
// TODO: implement it
|
// TODO: implement it
|
||||||
//! only applicable for output transactions
|
//! only applicable for output transactions
|
||||||
|
@ -51,4 +63,8 @@ private:
|
||||||
Bitmonero::TransactionInfo * m_pimpl;
|
Bitmonero::TransactionInfo * m_pimpl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// in order to wrap it to QVariant
|
||||||
|
Q_DECLARE_METATYPE(TransactionInfo*)
|
||||||
|
|
||||||
|
|
||||||
#endif // TRANSACTIONINFO_H
|
#endif // TRANSACTIONINFO_H
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include "PendingTransaction.h"
|
#include "PendingTransaction.h"
|
||||||
#include "TransactionHistory.h"
|
#include "TransactionHistory.h"
|
||||||
|
#include "model/TransactionHistoryModel.h"
|
||||||
|
#include "model/TransactionHistorySortFilterModel.h"
|
||||||
#include "wallet/wallet2_api.h"
|
#include "wallet/wallet2_api.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
@ -31,7 +33,6 @@ public:
|
||||||
|
|
||||||
virtual void moneyReceived(const std::string &txId, uint64_t amount)
|
virtual void moneyReceived(const std::string &txId, uint64_t amount)
|
||||||
{
|
{
|
||||||
|
|
||||||
qDebug() << __FUNCTION__;
|
qDebug() << __FUNCTION__;
|
||||||
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
|
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,10 @@ private:
|
||||||
Wallet * m_wallet;
|
Wallet * m_wallet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Wallet::Wallet(QObject * parent)
|
||||||
|
: Wallet(nullptr, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
QString Wallet::getSeed() const
|
QString Wallet::getSeed() const
|
||||||
{
|
{
|
||||||
|
@ -86,6 +90,11 @@ bool Wallet::connected() const
|
||||||
return m_walletImpl->connected();
|
return m_walletImpl->connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Wallet::synchronized() const
|
||||||
|
{
|
||||||
|
return m_walletImpl->synchronized();
|
||||||
|
}
|
||||||
|
|
||||||
QString Wallet::errorString() const
|
QString Wallet::errorString() const
|
||||||
{
|
{
|
||||||
return QString::fromStdString(m_walletImpl->errorString());
|
return QString::fromStdString(m_walletImpl->errorString());
|
||||||
|
@ -153,9 +162,16 @@ quint64 Wallet::daemonBlockChainHeight() const
|
||||||
return m_daemonBlockChainHeight;
|
return m_daemonBlockChainHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint64 Wallet::daemonBlockChainTargetHeight() const
|
||||||
|
{
|
||||||
|
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
|
||||||
|
return m_daemonBlockChainTargetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
bool Wallet::refresh()
|
bool Wallet::refresh()
|
||||||
{
|
{
|
||||||
bool result = m_walletImpl->refresh();
|
bool result = m_walletImpl->refresh();
|
||||||
|
m_history->refresh();
|
||||||
if (result)
|
if (result)
|
||||||
emit updated();
|
emit updated();
|
||||||
return result;
|
return result;
|
||||||
|
@ -193,15 +209,24 @@ void Wallet::disposeTransaction(PendingTransaction *t)
|
||||||
delete t;
|
delete t;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionHistory *Wallet::history()
|
TransactionHistory *Wallet::history() const
|
||||||
{
|
{
|
||||||
if (!m_history) {
|
|
||||||
Bitmonero::TransactionHistory * impl = m_walletImpl->history();
|
|
||||||
m_history = new TransactionHistory(impl, this);
|
|
||||||
}
|
|
||||||
return m_history;
|
return m_history;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransactionHistorySortFilterModel *Wallet::historyModel() const
|
||||||
|
{
|
||||||
|
if (!m_historyModel) {
|
||||||
|
Wallet * w = const_cast<Wallet*>(this);
|
||||||
|
m_historyModel = new TransactionHistoryModel(w);
|
||||||
|
m_historyModel->setTransactionHistory(this->history());
|
||||||
|
m_historySortFilterModel = new TransactionHistorySortFilterModel(w);
|
||||||
|
m_historySortFilterModel->setSourceModel(m_historyModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_historySortFilterModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QString Wallet::generatePaymentId() const
|
QString Wallet::generatePaymentId() const
|
||||||
{
|
{
|
||||||
|
@ -228,13 +253,16 @@ Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_walletImpl(w)
|
, m_walletImpl(w)
|
||||||
, m_history(nullptr)
|
, m_history(nullptr)
|
||||||
|
, m_historyModel(nullptr)
|
||||||
, m_daemonBlockChainHeight(0)
|
, m_daemonBlockChainHeight(0)
|
||||||
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
||||||
{
|
{
|
||||||
|
m_history = new TransactionHistory(m_walletImpl->history(), this);
|
||||||
m_walletImpl->setListener(new WalletListenerImpl(this));
|
m_walletImpl->setListener(new WalletListenerImpl(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet::~Wallet()
|
Wallet::~Wallet()
|
||||||
{
|
{
|
||||||
|
|
||||||
Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ namespace Bitmonero {
|
||||||
|
|
||||||
|
|
||||||
class TransactionHistory;
|
class TransactionHistory;
|
||||||
|
class TransactionHistoryModel;
|
||||||
|
class TransactionHistorySortFilterModel;
|
||||||
|
|
||||||
class Wallet : public QObject
|
class Wallet : public QObject
|
||||||
{
|
{
|
||||||
|
@ -21,14 +23,18 @@ class Wallet : public QObject
|
||||||
Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
|
Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
|
||||||
Q_PROPERTY(Status status READ status)
|
Q_PROPERTY(Status status READ status)
|
||||||
Q_PROPERTY(bool connected READ connected)
|
Q_PROPERTY(bool connected READ connected)
|
||||||
|
Q_PROPERTY(bool synchronized READ synchronized)
|
||||||
Q_PROPERTY(QString errorString READ errorString)
|
Q_PROPERTY(QString errorString READ errorString)
|
||||||
Q_PROPERTY(QString address READ address)
|
Q_PROPERTY(QString address READ address)
|
||||||
Q_PROPERTY(quint64 balance READ balance)
|
Q_PROPERTY(quint64 balance READ balance)
|
||||||
Q_PROPERTY(quint64 unlockedBalance READ unlockedBalance)
|
Q_PROPERTY(quint64 unlockedBalance READ unlockedBalance)
|
||||||
Q_PROPERTY(TransactionHistory * history READ history)
|
Q_PROPERTY(TransactionHistory * history READ history)
|
||||||
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
||||||
|
Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
Status_Ok = Bitmonero::Wallet::Status_Ok,
|
Status_Ok = Bitmonero::Wallet::Status_Ok,
|
||||||
Status_Error = Bitmonero::Wallet::Status_Error
|
Status_Error = Bitmonero::Wallet::Status_Error
|
||||||
|
@ -48,9 +54,13 @@ public:
|
||||||
//! returns last operation's status
|
//! returns last operation's status
|
||||||
Status status() const;
|
Status status() const;
|
||||||
|
|
||||||
//! returns of wallet connected
|
//! returns true if wallet connected
|
||||||
bool connected() const;
|
bool connected() const;
|
||||||
|
|
||||||
|
//! returns true if wallet was ever synchronized
|
||||||
|
bool synchronized() const;
|
||||||
|
|
||||||
|
|
||||||
//! returns last operation's error message
|
//! returns last operation's error message
|
||||||
QString errorString() const;
|
QString errorString() const;
|
||||||
|
|
||||||
|
@ -88,10 +98,12 @@ public:
|
||||||
//! returns daemon's blockchain height
|
//! returns daemon's blockchain height
|
||||||
Q_INVOKABLE quint64 daemonBlockChainHeight() const;
|
Q_INVOKABLE quint64 daemonBlockChainHeight() const;
|
||||||
|
|
||||||
|
//! returns daemon's blockchain target height
|
||||||
|
Q_INVOKABLE quint64 daemonBlockChainTargetHeight() const;
|
||||||
|
|
||||||
//! refreshes the wallet
|
//! refreshes the wallet
|
||||||
Q_INVOKABLE bool refresh();
|
Q_INVOKABLE bool refresh();
|
||||||
|
|
||||||
|
|
||||||
//! refreshes the wallet asynchronously
|
//! refreshes the wallet asynchronously
|
||||||
Q_INVOKABLE void refreshAsync();
|
Q_INVOKABLE void refreshAsync();
|
||||||
|
|
||||||
|
@ -109,7 +121,10 @@ public:
|
||||||
Q_INVOKABLE void disposeTransaction(PendingTransaction * t);
|
Q_INVOKABLE void disposeTransaction(PendingTransaction * t);
|
||||||
|
|
||||||
//! returns transaction history
|
//! returns transaction history
|
||||||
TransactionHistory * history();
|
TransactionHistory * history() const;
|
||||||
|
|
||||||
|
//! returns transaction history model
|
||||||
|
TransactionHistorySortFilterModel *historyModel() const;
|
||||||
|
|
||||||
//! generate payment id
|
//! generate payment id
|
||||||
Q_INVOKABLE QString generatePaymentId() const;
|
Q_INVOKABLE QString generatePaymentId() const;
|
||||||
|
@ -136,12 +151,13 @@ signals:
|
||||||
void moneySpent(const QString &txId, quint64 amount);
|
void moneySpent(const QString &txId, quint64 amount);
|
||||||
void moneyReceived(const QString &txId, quint64 amount);
|
void moneyReceived(const QString &txId, quint64 amount);
|
||||||
void newBlock(quint64 height);
|
void newBlock(quint64 height);
|
||||||
|
void historyModelChanged() const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Wallet(QObject * parent = nullptr);
|
||||||
Wallet(Bitmonero::Wallet *w, QObject * parent = 0);
|
Wallet(Bitmonero::Wallet *w, QObject * parent = 0);
|
||||||
~Wallet();
|
~Wallet();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class WalletManager;
|
friend class WalletManager;
|
||||||
friend class WalletListenerImpl;
|
friend class WalletListenerImpl;
|
||||||
|
@ -149,11 +165,16 @@ private:
|
||||||
Bitmonero::Wallet * m_walletImpl;
|
Bitmonero::Wallet * m_walletImpl;
|
||||||
// history lifetime managed by wallet;
|
// history lifetime managed by wallet;
|
||||||
TransactionHistory * m_history;
|
TransactionHistory * m_history;
|
||||||
|
// Used for UI history view
|
||||||
|
mutable TransactionHistoryModel * m_historyModel;
|
||||||
|
mutable TransactionHistorySortFilterModel * m_historySortFilterModel;
|
||||||
QString m_paymentId;
|
QString m_paymentId;
|
||||||
mutable QTime m_daemonBlockChainHeightTime;
|
mutable QTime m_daemonBlockChainHeightTime;
|
||||||
mutable quint64 m_daemonBlockChainHeight;
|
mutable quint64 m_daemonBlockChainHeight;
|
||||||
int m_daemonBlockChainHeightTtl;
|
int m_daemonBlockChainHeightTtl;
|
||||||
|
mutable quint64 m_daemonBlockChainTargetHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // WALLET_H
|
#endif // WALLET_H
|
||||||
|
|
|
@ -61,9 +61,9 @@ void WalletManager::openWalletAsync(const QString &path, const QString &password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, bool testnet)
|
Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, bool testnet, quint64 restoreHeight)
|
||||||
{
|
{
|
||||||
Bitmonero::Wallet * w = m_pimpl->recoveryWallet(path.toStdString(), memo.toStdString(), testnet);
|
Bitmonero::Wallet * w = m_pimpl->recoveryWallet(path.toStdString(), memo.toStdString(), testnet, restoreHeight);
|
||||||
Wallet * wallet = new Wallet(w);
|
Wallet * wallet = new Wallet(w);
|
||||||
return wallet;
|
return wallet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
|
|
||||||
// wizard: recoveryWallet path; hint: internally it recorvers wallet and set password = ""
|
// wizard: recoveryWallet path; hint: internally it recorvers wallet and set password = ""
|
||||||
Q_INVOKABLE Wallet * recoveryWallet(const QString &path, const QString &memo,
|
Q_INVOKABLE Wallet * recoveryWallet(const QString &path, const QString &memo,
|
||||||
bool testnet = false);
|
bool testnet = false, quint64 restoreHeight = 0);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief closeWallet - closes wallet and frees memory
|
* \brief closeWallet - closes wallet and frees memory
|
||||||
|
|
126
src/model/TransactionHistoryModel.cpp
Normal file
126
src/model/TransactionHistoryModel.cpp
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
#include "TransactionHistoryModel.h"
|
||||||
|
#include "TransactionHistory.h"
|
||||||
|
#include "TransactionInfo.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
|
||||||
|
TransactionHistoryModel::TransactionHistoryModel(QObject *parent)
|
||||||
|
: QAbstractListModel(parent), m_transactionHistory(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistoryModel::setTransactionHistory(TransactionHistory *th)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_transactionHistory = th;
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
connect(m_transactionHistory, &TransactionHistory::refreshStarted,
|
||||||
|
this, &TransactionHistoryModel::beginResetModel);
|
||||||
|
connect(m_transactionHistory, &TransactionHistory::refreshFinished,
|
||||||
|
this, &TransactionHistoryModel::endResetModel);
|
||||||
|
|
||||||
|
emit transactionHistoryChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionHistory *TransactionHistoryModel::transactionHistory() const
|
||||||
|
{
|
||||||
|
return m_transactionHistory;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!m_transactionHistory) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.row() < 0 || (unsigned)index.row() >= m_transactionHistory->count()) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionInfo * tInfo = m_transactionHistory->transaction(index.row());
|
||||||
|
|
||||||
|
|
||||||
|
Q_ASSERT(tInfo);
|
||||||
|
if (!tInfo) {
|
||||||
|
qCritical("%s: internal error: no transaction info for index %d", __FUNCTION__, index.row());
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
QVariant result;
|
||||||
|
switch (role) {
|
||||||
|
case TransactionRole:
|
||||||
|
result = QVariant::fromValue(tInfo);
|
||||||
|
break;
|
||||||
|
case TransactionDirectionRole:
|
||||||
|
result = QVariant::fromValue(tInfo->direction());
|
||||||
|
break;
|
||||||
|
case TransactionPendingRole:
|
||||||
|
result = tInfo->isPending();
|
||||||
|
break;
|
||||||
|
case TransactionFailedRole:
|
||||||
|
result = tInfo->isFailed();
|
||||||
|
break;
|
||||||
|
case TransactionAmountRole:
|
||||||
|
result = tInfo->amount();
|
||||||
|
break;
|
||||||
|
case TransactionDisplayAmountRole:
|
||||||
|
result = tInfo->displayAmount();
|
||||||
|
break;
|
||||||
|
case TransactionFeeRole:
|
||||||
|
result = tInfo->fee();
|
||||||
|
break;
|
||||||
|
case TransactionBlockHeightRole:
|
||||||
|
result = tInfo->blockHeight();
|
||||||
|
break;
|
||||||
|
case TransactionHashRole:
|
||||||
|
result = tInfo->hash();
|
||||||
|
break;
|
||||||
|
case TransactionTimeStampRole:
|
||||||
|
result = tInfo->timestamp();
|
||||||
|
break;
|
||||||
|
case TransactionPaymentIdRole:
|
||||||
|
result = tInfo->paymentId();
|
||||||
|
break;
|
||||||
|
case TransactionIsOutRole:
|
||||||
|
result = tInfo->direction() == TransactionInfo::Direction_Out;
|
||||||
|
break;
|
||||||
|
case TransactionDateRole:
|
||||||
|
result = tInfo->date();
|
||||||
|
break;
|
||||||
|
case TransactionTimeRole:
|
||||||
|
result = tInfo->time();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TransactionHistoryModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return m_transactionHistory ? m_transactionHistory->count() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
|
||||||
|
{
|
||||||
|
QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames();
|
||||||
|
roleNames.insert(TransactionRole, "transaction");
|
||||||
|
roleNames.insert(TransactionDirectionRole, "direction");
|
||||||
|
roleNames.insert(TransactionPendingRole, "isPending");
|
||||||
|
roleNames.insert(TransactionFailedRole, "isFailed");
|
||||||
|
roleNames.insert(TransactionAmountRole, "amount");
|
||||||
|
roleNames.insert(TransactionDisplayAmountRole, "displayAmount");
|
||||||
|
roleNames.insert(TransactionFeeRole, "fee");
|
||||||
|
roleNames.insert(TransactionBlockHeightRole, "blockHeight");
|
||||||
|
roleNames.insert(TransactionHashRole, "hash");
|
||||||
|
roleNames.insert(TransactionTimeStampRole, "timeStamp");
|
||||||
|
roleNames.insert(TransactionPaymentIdRole, "paymentId");
|
||||||
|
roleNames.insert(TransactionIsOutRole, "isOut");
|
||||||
|
roleNames.insert(TransactionDateRole, "date");
|
||||||
|
roleNames.insert(TransactionTimeRole, "time");
|
||||||
|
return roleNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
68
src/model/TransactionHistoryModel.h
Normal file
68
src/model/TransactionHistoryModel.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef TRANSACTIONHISTORYMODEL_H
|
||||||
|
#define TRANSACTIONHISTORYMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
|
class TransactionHistory;
|
||||||
|
class TransactionInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The TransactionHistoryModel class - read-only list model for Transaction History
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TransactionHistoryModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(TransactionHistory * transactionHistory READ transactionHistory WRITE setTransactionHistory NOTIFY transactionHistoryChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum TransactionInfoRole {
|
||||||
|
TransactionRole = Qt::UserRole + 1, // for the TransactionInfo object;
|
||||||
|
TransactionDirectionRole,
|
||||||
|
TransactionPendingRole,
|
||||||
|
TransactionFailedRole,
|
||||||
|
TransactionAmountRole,
|
||||||
|
TransactionDisplayAmountRole,
|
||||||
|
TransactionFeeRole,
|
||||||
|
TransactionBlockHeightRole,
|
||||||
|
TransactionHashRole,
|
||||||
|
TransactionTimeStampRole,
|
||||||
|
TransactionPaymentIdRole,
|
||||||
|
// extra role (alias) for TransactionDirectionRole (as UI currently wants just boolean "out")
|
||||||
|
TransactionIsOutRole,
|
||||||
|
// extra roles for date and time (as UI wants date and time separately)
|
||||||
|
TransactionDateRole,
|
||||||
|
TransactionTimeRole
|
||||||
|
};
|
||||||
|
Q_ENUM(TransactionInfoRole)
|
||||||
|
|
||||||
|
TransactionHistoryModel(QObject * parent = 0);
|
||||||
|
void setTransactionHistory(TransactionHistory * th);
|
||||||
|
TransactionHistory * transactionHistory() const;
|
||||||
|
/**
|
||||||
|
* @brief dateFrom - returns firstmost transaction datetime
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
QDateTime firstDateTime() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dateTo - returns lastmost transaction datetime
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
QDateTime lastDateTime() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// QAbstractListModel
|
||||||
|
virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
|
||||||
|
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const override;
|
||||||
|
virtual QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void transactionHistoryChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
TransactionHistory * m_transactionHistory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSACTIONHISTORYMODEL_H
|
209
src/model/TransactionHistorySortFilterModel.cpp
Normal file
209
src/model/TransactionHistorySortFilterModel.cpp
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
#include "TransactionHistorySortFilterModel.h"
|
||||||
|
#include "TransactionHistoryModel.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/**
|
||||||
|
* helper to extract scope value from filter
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T scopeFilterValue(const QMap<int, QVariant> &filters, int role, int scopeIndex)
|
||||||
|
{
|
||||||
|
if (!filters.contains(role)) {
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
return filters.value(role).toList().at(scopeIndex).value<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper to setup scope value to filter
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
void setScopeFilterValue(QMap<int, QVariant> &filters, int role, int scopeIndex, const T &value)
|
||||||
|
{
|
||||||
|
QVariantList scopeFilter;
|
||||||
|
|
||||||
|
if (filters.contains(role)) {
|
||||||
|
scopeFilter = filters.value(role).toList();
|
||||||
|
}
|
||||||
|
while (scopeFilter.size() < 2) {
|
||||||
|
scopeFilter.append(T());
|
||||||
|
}
|
||||||
|
scopeFilter[scopeIndex] = QVariant::fromValue(value);
|
||||||
|
filters[role] = scopeFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TransactionHistorySortFilterModel::TransactionHistorySortFilterModel(QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setDynamicSortFilter(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionHistorySortFilterModel::paymentIdFilter() const
|
||||||
|
{
|
||||||
|
return m_filterValues.value(TransactionHistoryModel::TransactionPaymentIdRole).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::setPaymentIdFilter(const QString &arg)
|
||||||
|
{
|
||||||
|
if (paymentIdFilter() != arg) {
|
||||||
|
m_filterValues[TransactionHistoryModel::TransactionPaymentIdRole] = arg;
|
||||||
|
emit paymentIdFilterChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDate TransactionHistorySortFilterModel::dateFromFilter() const
|
||||||
|
{
|
||||||
|
return scopeFilterValue<QDate>(m_filterValues, TransactionHistoryModel::TransactionTimeStampRole, ScopeIndex::From);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::setDateFromFilter(const QDate &date)
|
||||||
|
{
|
||||||
|
if (date != dateFromFilter()) {
|
||||||
|
setScopeFilterValue(m_filterValues, TransactionHistoryModel::TransactionTimeStampRole, ScopeIndex::From, date);
|
||||||
|
emit dateFromFilterChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDate TransactionHistorySortFilterModel::dateToFilter() const
|
||||||
|
{
|
||||||
|
return scopeFilterValue<QDate>(m_filterValues, TransactionHistoryModel::TransactionTimeStampRole, ScopeIndex::To);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::setDateToFilter(const QDate &date)
|
||||||
|
{
|
||||||
|
if (date != dateToFilter()) {
|
||||||
|
setScopeFilterValue(m_filterValues, TransactionHistoryModel::TransactionTimeStampRole, ScopeIndex::To, date);
|
||||||
|
emit dateToFilterChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double TransactionHistorySortFilterModel::amountFromFilter() const
|
||||||
|
{
|
||||||
|
return scopeFilterValue<double>(m_filterValues, TransactionHistoryModel::TransactionAmountRole, ScopeIndex::From);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::setAmountFromFilter(double value)
|
||||||
|
{
|
||||||
|
if (value != amountFromFilter()) {
|
||||||
|
setScopeFilterValue(m_filterValues, TransactionHistoryModel::TransactionAmountRole, ScopeIndex::From, value);
|
||||||
|
emit amountFromFilterChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double TransactionHistorySortFilterModel::amountToFilter() const
|
||||||
|
{
|
||||||
|
return scopeFilterValue<double>(m_filterValues, TransactionHistoryModel::TransactionAmountRole, ScopeIndex::To);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::setAmountToFilter(double value)
|
||||||
|
{
|
||||||
|
if (value != amountToFilter()) {
|
||||||
|
setScopeFilterValue(m_filterValues, TransactionHistoryModel::TransactionAmountRole, ScopeIndex::To, value);
|
||||||
|
emit amountToFilterChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TransactionHistorySortFilterModel::directionFilter() const
|
||||||
|
{
|
||||||
|
return m_filterValues.value(TransactionHistoryModel::TransactionDirectionRole).value<TransactionInfo::Direction>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::setDirectionFilter(int value)
|
||||||
|
{
|
||||||
|
if (value != directionFilter()) {
|
||||||
|
m_filterValues[TransactionHistoryModel::TransactionDirectionRole] = QVariant::fromValue(value);
|
||||||
|
emit directionFilterChanged();
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TransactionHistorySortFilterModel::sort(int column, Qt::SortOrder order)
|
||||||
|
{
|
||||||
|
QSortFilterProxyModel::sort(column, order);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionHistory *TransactionHistorySortFilterModel::transactionHistory() const
|
||||||
|
{
|
||||||
|
const TransactionHistoryModel * model = static_cast<const TransactionHistoryModel*> (sourceModel());
|
||||||
|
return model->transactionHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TransactionHistorySortFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||||
|
{
|
||||||
|
|
||||||
|
if (source_row < 0 || source_row >= sourceModel()->rowCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
// iterating through filters
|
||||||
|
for (int role : m_filterValues.keys()) {
|
||||||
|
if (m_filterValues.contains(role)) {
|
||||||
|
QVariant data = sourceModel()->data(index, role);
|
||||||
|
switch (role) {
|
||||||
|
case TransactionHistoryModel::TransactionPaymentIdRole:
|
||||||
|
result = data.toString().contains(paymentIdFilter());
|
||||||
|
break;
|
||||||
|
case TransactionHistoryModel::TransactionTimeStampRole:
|
||||||
|
{
|
||||||
|
QDateTime from = QDateTime(dateFromFilter());
|
||||||
|
QDateTime to = QDateTime(dateToFilter());
|
||||||
|
to = to.addDays(1); // including upperbound
|
||||||
|
QDateTime timestamp = data.toDateTime();
|
||||||
|
bool matchFrom = from.isNull() || timestamp.isNull() || timestamp >= from;
|
||||||
|
bool matchTo = to.isNull() || timestamp.isNull() || timestamp <= to;
|
||||||
|
result = matchFrom && matchTo;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TransactionHistoryModel::TransactionAmountRole:
|
||||||
|
{
|
||||||
|
double from = amountFromFilter();
|
||||||
|
double to = amountToFilter();
|
||||||
|
double amount = data.toDouble();
|
||||||
|
|
||||||
|
bool matchFrom = from <= 0 || amount >= from;
|
||||||
|
bool matchTo = to <= 0 || amount <= to;
|
||||||
|
result = matchFrom && matchTo;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TransactionHistoryModel::TransactionDirectionRole:
|
||||||
|
result = directionFilter() == TransactionInfo::Direction_Both ? true
|
||||||
|
: data.toInt() == directionFilter();
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!result) { // stop the loop once filter doesn't match
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TransactionHistorySortFilterModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||||
|
{
|
||||||
|
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
||||||
|
}
|
79
src/model/TransactionHistorySortFilterModel.h
Normal file
79
src/model/TransactionHistorySortFilterModel.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#ifndef TRANSACTIONHISTORYSORTFILTERMODEL_H
|
||||||
|
#define TRANSACTIONHISTORYSORTFILTERMODEL_H
|
||||||
|
|
||||||
|
#include "TransactionInfo.h"
|
||||||
|
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QDate>
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionHistory;
|
||||||
|
|
||||||
|
class TransactionHistorySortFilterModel: public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString paymentIdFilter READ paymentIdFilter WRITE setPaymentIdFilter NOTIFY paymentIdFilterChanged)
|
||||||
|
Q_PROPERTY(QDate dateFromFilter READ dateFromFilter WRITE setDateFromFilter NOTIFY dateFromFilterChanged)
|
||||||
|
Q_PROPERTY(QDate dateToFilter READ dateToFilter WRITE setDateToFilter NOTIFY dateToFilterChanged)
|
||||||
|
Q_PROPERTY(double amountFromFilter READ amountFromFilter WRITE setAmountFromFilter NOTIFY amountFromFilterChanged)
|
||||||
|
Q_PROPERTY(double amountToFilter READ amountToFilter WRITE setAmountToFilter NOTIFY amountToFilterChanged)
|
||||||
|
Q_PROPERTY(int directionFilter READ directionFilter WRITE setDirectionFilter NOTIFY directionFilterChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(TransactionHistory * transactionHistory READ transactionHistory)
|
||||||
|
|
||||||
|
public:
|
||||||
|
TransactionHistorySortFilterModel(QObject * parent = nullptr);
|
||||||
|
//! filtering by payment id
|
||||||
|
QString paymentIdFilter() const;
|
||||||
|
void setPaymentIdFilter(const QString &arg);
|
||||||
|
|
||||||
|
//! filtering by date (lower bound)
|
||||||
|
QDate dateFromFilter() const;
|
||||||
|
void setDateFromFilter(const QDate &date);
|
||||||
|
|
||||||
|
//! filtering by to date (upper bound)
|
||||||
|
QDate dateToFilter() const;
|
||||||
|
void setDateToFilter(const QDate &date);
|
||||||
|
|
||||||
|
//! filtering by amount (lower bound)
|
||||||
|
double amountFromFilter() const;
|
||||||
|
void setAmountFromFilter(double value);
|
||||||
|
|
||||||
|
//! filtering by amount (upper bound)
|
||||||
|
double amountToFilter() const;
|
||||||
|
void setAmountToFilter(double value);
|
||||||
|
|
||||||
|
//! filtering by direction
|
||||||
|
int directionFilter() const;
|
||||||
|
void setDirectionFilter(int value);
|
||||||
|
|
||||||
|
Q_INVOKABLE void sort(int column, Qt::SortOrder order);
|
||||||
|
TransactionHistory * transactionHistory() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void paymentIdFilterChanged();
|
||||||
|
void dateFromFilterChanged();
|
||||||
|
void dateToFilterChanged();
|
||||||
|
void amountFromFilterChanged();
|
||||||
|
void amountToFilterChanged();
|
||||||
|
void directionFilterChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// QSortFilterProxyModel overrides
|
||||||
|
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||||
|
virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum ScopeIndex {
|
||||||
|
From = 0,
|
||||||
|
To = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<int, QVariant> m_filterValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSACTIONHISTORYSORTFILTERMODEL_H
|
|
@ -27,7 +27,9 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import moneroComponents 1.0
|
import moneroComponents.WalletManager 1.0
|
||||||
|
import moneroComponents.Wallet 1.0
|
||||||
|
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import 'utils.js' as Utils
|
import 'utils.js' as Utils
|
||||||
|
|
||||||
|
@ -94,5 +96,6 @@ Item {
|
||||||
wordsTextItem.clipboardButtonVisible: true
|
wordsTextItem.clipboardButtonVisible: true
|
||||||
wordsTextItem.tipTextVisible: true
|
wordsTextItem.tipTextVisible: true
|
||||||
wordsTextItem.memoTextReadOnly: true
|
wordsTextItem.memoTextReadOnly: true
|
||||||
|
restoreHeightVisible:false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ Item {
|
||||||
+ qsTr("<b>Allow background mining: </b>") + wizard.settings['allow_background_mining'] + "<br>"
|
+ qsTr("<b>Allow background mining: </b>") + wizard.settings['allow_background_mining'] + "<br>"
|
||||||
+ qsTr("<b>Daemon address: </b>") + wizard.settings['daemon_address'] + "<br>"
|
+ qsTr("<b>Daemon address: </b>") + wizard.settings['daemon_address'] + "<br>"
|
||||||
+ qsTr("<b>testnet: </b>") + wizard.settings['testnet'] + "<br>"
|
+ qsTr("<b>testnet: </b>") + wizard.settings['testnet'] + "<br>"
|
||||||
|
+ (wizard.settings['restore_height'] === undefined ? "" : qsTr("<b>Restore height: </b>") + wizard.settings['restore_height']) + "<br>"
|
||||||
+ translationManager.emptyString
|
+ translationManager.emptyString
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,7 @@ Rectangle {
|
||||||
appWindow.persistentSettings.auto_donations_amount = settings.auto_donations_amount
|
appWindow.persistentSettings.auto_donations_amount = settings.auto_donations_amount
|
||||||
appWindow.persistentSettings.daemon_address = settings.daemon_address
|
appWindow.persistentSettings.daemon_address = settings.daemon_address
|
||||||
appWindow.persistentSettings.testnet = settings.testnet
|
appWindow.persistentSettings.testnet = settings.testnet
|
||||||
|
appWindow.persistentSettings.restore_height = parseInt(settings.restore_height)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,10 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import moneroComponents 1.0
|
import moneroComponents.TranslationManager 1.0
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import "../components"
|
||||||
|
|
||||||
// Reusable component for managing wallet (account name, path, private key)
|
// Reusable component for managing wallet (account name, path, private key)
|
||||||
|
|
||||||
|
@ -39,6 +41,8 @@ Item {
|
||||||
property alias wordsTextTitle: frameHeader.text
|
property alias wordsTextTitle: frameHeader.text
|
||||||
property alias walletPath: fileUrlInput.text
|
property alias walletPath: fileUrlInput.text
|
||||||
property alias wordsTextItem : memoTextItem
|
property alias wordsTextItem : memoTextItem
|
||||||
|
property alias restoreHeight : restoreHeightItem.text
|
||||||
|
property alias restoreHeightVisible: restoreHeightItem.visible
|
||||||
|
|
||||||
|
|
||||||
// TODO extend properties if needed
|
// TODO extend properties if needed
|
||||||
|
@ -112,7 +116,7 @@ Item {
|
||||||
width: 300
|
width: 300
|
||||||
height: 62
|
height: 62
|
||||||
|
|
||||||
TextInput {
|
TextEdit {
|
||||||
id: accountName
|
id: accountName
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
horizontalAlignment: TextInput.AlignHCenter
|
horizontalAlignment: TextInput.AlignHCenter
|
||||||
|
@ -159,10 +163,22 @@ Item {
|
||||||
anchors.topMargin: 16
|
anchors.topMargin: 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore Height
|
||||||
|
LineEdit {
|
||||||
|
id: restoreHeightItem
|
||||||
|
anchors.top: memoTextItem.bottom
|
||||||
|
width: 250
|
||||||
|
anchors.topMargin: 20
|
||||||
|
placeholderText: qsTr("Restore height")
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
validator: IntValidator {
|
||||||
|
bottom:0
|
||||||
|
}
|
||||||
|
}
|
||||||
Row {
|
Row {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: memoTextItem.bottom
|
anchors.top: (restoreHeightItem.visible)? restoreHeightItem.bottom : memoTextItem.bottom
|
||||||
anchors.topMargin: 24
|
anchors.topMargin: 24
|
||||||
spacing: 16
|
spacing: 16
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import moneroComponents 1.0
|
import moneroComponents.Clipboard 1.0
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ Item {
|
||||||
} else {
|
} else {
|
||||||
passwordPage.titleText = qsTr("Now that your wallet has been restored, please set a password for the wallet") + translationManager.emptyString
|
passwordPage.titleText = qsTr("Now that your wallet has been restored, please set a password for the wallet") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
passwordItem.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPageClosed(settingsObject) {
|
function onPageClosed(settingsObject) {
|
||||||
|
@ -146,30 +148,34 @@ Item {
|
||||||
anchors.topMargin: 24
|
anchors.topMargin: 24
|
||||||
width: 300
|
width: 300
|
||||||
height: 62
|
height: 62
|
||||||
|
placeholderText : qsTr("Password") + translationManager.emptyString;
|
||||||
|
KeyNavigation.tab: retypePasswordItem
|
||||||
onChanged: handlePassword()
|
onChanged: handlePassword()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WizardPasswordInput {
|
||||||
|
id: retypePasswordItem
|
||||||
|
anchors.top: passwordItem.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.topMargin: 24
|
||||||
|
width: 300
|
||||||
|
height: 62
|
||||||
|
placeholderText : qsTr("Confirm password") + translationManager.emptyString;
|
||||||
|
KeyNavigation.tab: passwordItem
|
||||||
|
onChanged: handlePassword()
|
||||||
|
}
|
||||||
|
|
||||||
PrivacyLevelSmall {
|
PrivacyLevelSmall {
|
||||||
id: privacyLevel
|
id: privacyLevel
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: passwordItem.bottom
|
anchors.top: retypePasswordItem.bottom
|
||||||
anchors.topMargin: 24
|
anchors.topMargin: 60
|
||||||
background: "#F0EEEE"
|
background: "#F0EEEE"
|
||||||
interactive: false
|
interactive: false
|
||||||
}
|
}
|
||||||
|
|
||||||
WizardPasswordInput {
|
|
||||||
id: retypePasswordItem
|
|
||||||
anchors.top: privacyLevel.bottom
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.topMargin: 24
|
|
||||||
width: 300
|
|
||||||
height: 62
|
|
||||||
onChanged: handlePassword()
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
console.log
|
console.log
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,24 +27,34 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
Item {
|
FocusScope {
|
||||||
property alias password: password.text
|
property alias password: password.text
|
||||||
|
property alias placeholderText: password.placeholderText
|
||||||
signal changed(string password)
|
signal changed(string password)
|
||||||
|
|
||||||
|
|
||||||
TextInput {
|
TextField {
|
||||||
id : password
|
id : password
|
||||||
|
focus:true
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
horizontalAlignment: TextInput.AlignHCenter
|
horizontalAlignment: TextInput.AlignLeft
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
font.family: "Arial"
|
font.family: "Arial"
|
||||||
font.pixelSize: 32
|
font.pixelSize: 32
|
||||||
renderType: Text.NativeRendering
|
|
||||||
color: "#35B05A"
|
|
||||||
passwordCharacter: "•"
|
|
||||||
echoMode: TextInput.Password
|
echoMode: TextInput.Password
|
||||||
focus: true
|
style: TextFieldStyle {
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
textColor: "#35B05A"
|
||||||
|
passwordCharacter: "•"
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 0
|
||||||
|
border.width: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Keys.onReleased: {
|
Keys.onReleased: {
|
||||||
changed(text)
|
changed(text)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,8 @@
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
import moneroComponents 1.0
|
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import Bitmonero.Wallet 1.0
|
import moneroComponents.Wallet 1.0
|
||||||
import 'utils.js' as Utils
|
import 'utils.js' as Utils
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -55,12 +54,14 @@ Item {
|
||||||
settingsObject['account_name'] = uiItem.accountNameText
|
settingsObject['account_name'] = uiItem.accountNameText
|
||||||
settingsObject['words'] = Utils.lineBreaksToSpaces(uiItem.wordsTextItem.memoText)
|
settingsObject['words'] = Utils.lineBreaksToSpaces(uiItem.wordsTextItem.memoText)
|
||||||
settingsObject['wallet_path'] = uiItem.walletPath
|
settingsObject['wallet_path'] = uiItem.walletPath
|
||||||
|
settingsObject['restoreHeight'] = parseInt(uiItem.restoreHeight)
|
||||||
return recoveryWallet(settingsObject)
|
return recoveryWallet(settingsObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
function recoveryWallet(settingsObject) {
|
function recoveryWallet(settingsObject) {
|
||||||
var testnet = appWindow.persistentSettings.testnet;
|
var testnet = appWindow.persistentSettings.testnet;
|
||||||
var wallet = walletManager.recoveryWallet(oshelper.temporaryFilename(), settingsObject.words, testnet);
|
var restoreHeight = settingsObject.restoreHeight;
|
||||||
|
var wallet = walletManager.recoveryWallet(oshelper.temporaryFilename(), settingsObject.words, testnet, restoreHeight);
|
||||||
var success = wallet.status === Wallet.Status_Ok;
|
var success = wallet.status === Wallet.Status_Ok;
|
||||||
if (success) {
|
if (success) {
|
||||||
settingsObject['wallet'] = wallet;
|
settingsObject['wallet'] = wallet;
|
||||||
|
@ -81,6 +82,7 @@ Item {
|
||||||
wordsTextItem.tipTextVisible: false
|
wordsTextItem.tipTextVisible: false
|
||||||
wordsTextItem.memoTextReadOnly: false
|
wordsTextItem.memoTextReadOnly: false
|
||||||
wordsTextItem.memoText: ""
|
wordsTextItem.memoText: ""
|
||||||
|
restoreHeightVisible: true
|
||||||
wordsTextItem.onMemoTextChanged: {
|
wordsTextItem.onMemoTextChanged: {
|
||||||
checkNextButton();
|
checkNextButton();
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,7 @@ Item {
|
||||||
if (data !== null || data !== undefined) {
|
if (data !== null || data !== undefined) {
|
||||||
var locale = data.locale
|
var locale = data.locale
|
||||||
translationManager.setLanguage(locale.split("_")[0]);
|
translationManager.setLanguage(locale.split("_")[0]);
|
||||||
|
wizard.switchPage(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue