Merge pull request #2 from szogun1987/master

Refresh with drop
This commit is contained in:
Wojciech Gomoła 2018-01-28 15:30:37 +01:00 committed by GitHub
commit 5adc39915e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
132 changed files with 28470 additions and 12053 deletions

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
Copyright (c) 2014-2017, The Monero Project Copyright (c) 2014-2018, The Monero Project
All rights reserved. All rights reserved.

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -112,7 +112,7 @@ Rectangle {
}, State { }, State {
name: "Receive" name: "Receive"
PropertyChanges { target: root; currentView: receiveView } PropertyChanges { target: root; currentView: receiveView }
PropertyChanges { target: mainFlickable; contentHeight: minHeight } PropertyChanges { target: mainFlickable; contentHeight: 1000 * scaleRatio }
}, State { }, State {
name: "TxKey" name: "TxKey"
PropertyChanges { target: root; currentView: txkeyView } PropertyChanges { target: root; currentView: txkeyView }

View File

@ -1,8 +1,8 @@
# Monero GUI # Monero GUI
Copyright (c) 2014-2017, The Monero Project Copyright (c) 2014-2018, The Monero Project
## Development Resources ## Development resources
- Web: [getmonero.org](https://getmonero.org) - Web: [getmonero.org](https://getmonero.org)
- Forum: [forum.getmonero.org](https://forum.getmonero.org) - Forum: [forum.getmonero.org](https://forum.getmonero.org)
@ -33,9 +33,7 @@ As with many development projects, the repository on Github is considered to be
## Supporting the project ## Supporting the project
Monero development can be supported directly through donations. Monero is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Both Monero and Bitcoin donations can be made to **donate.getmonero.org** if using a client that supports the [OpenAlias](https://openalias.org) standard.
Both Monero and Bitcoin donations can be made to **donate.getmonero.org** if using a client that supports the [OpenAlias](https://openalias.org) standard.
The Monero donation address is: `44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A` (viewkey: `f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501`) The Monero donation address is: `44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A` (viewkey: `f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501`)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
Copyright (c) 2014-2017, The Monero Project Copyright (c) 2014-2018, The Monero Project
## Current status : ALPHA ## Current status : ALPHA
@ -22,7 +22,7 @@ Copyright (c) 2014-2017, The Monero Project
# Get the apk # Get the apk
docker cp monero-gui-android:/opt/android/monero-core/build/release/bin/bin/QtApp-debug.apk . docker cp monero-gui-android:/opt/android/monero-gui/build/release/bin/bin/QtApp-debug.apk .
## Deployment ## Deployment
@ -31,7 +31,7 @@ Copyright (c) 2014-2017, The Monero Project
First, see section [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling) First, see section [Enable adb debugging on your device](https://developer.android.com/studio/command-line/adb.html#Enabling)
The only place where we are allowed to play is `/data/local/tmp`. So : The only place where we are allowed to play is `/data/local/tmp`. So :
adb push /opt/android/monero-core/build/release/bin/bin/QtApp-debug.apk /data/local/tmp adb push /opt/android/monero-gui/build/release/bin/bin/QtApp-debug.apk /data/local/tmp
adb shell pm install -r /data/local/tmp/QtApp-debug.apk adb shell pm install -r /data/local/tmp/QtApp-debug.apk
- Troubleshooting: - Troubleshooting:

View File

@ -88,21 +88,20 @@ APP_CFLAGS += -target armv7-none-linux-androideabi -fexceptions -fstack-protect
&& android update project --path . -t "${ANDROID_API}" \ && android update project --path . -t "${ANDROID_API}" \
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ant -Dndk.dir=${ANDROID_NDK_ROOT} -Diconv.src=${WORKDIR}/libiconv-${ICONV_VERSION} zbar-clean zbar-ndk-build && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ ant -Dndk.dir=${ANDROID_NDK_ROOT} -Diconv.src=${WORKDIR}/libiconv-${ICONV_VERSION} zbar-clean zbar-ndk-build
#Can't directly call build.sh because of env variables
RUN git clone https://github.com/monero-project/monero-core.git \
&& cd monero-core \
&& git submodule update \
&& CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ BOOST_ROOT=/opt/android/boost_1_62_0 BOOST_LIBRARYDIR=${WORKDIR}/boost_${BOOST_VERSION}/android32/lib/ OPENSSL_ROOT_DIR=${WORKDIR}/openssl/ ./get_libwallet_api.sh release-android
RUN cp openssl/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib RUN cp openssl/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
RUN cp boost_${BOOST_VERSION}/android32/lib/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib RUN cp boost_${BOOST_VERSION}/android32/lib/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
RUN cp ZBar/android/obj/local/armeabi-v7a/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib RUN cp ZBar/android/obj/local/armeabi-v7a/lib* ${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm/usr/lib
ENV PATH $ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:${WORKDIR}/Qt-${QT_VERSION}/bin:$CLEAN_PATH RUN git clone https://github.com/monero-project/monero-gui.git \
&& cd monero-gui \
# NB : zxcvbn-c needs to build a local binary and Qt don't care about these environnement variable && git submodule update \
RUN cd monero-core \ && CC=arm-linux-androideabi-clang CXX=arm-linux-androideabi-clang++ BOOST_ROOT=/opt/android/boost_1_62_0 \
&& CC="gcc" CXX="g++" ./build.sh release-android \ BOOST_LIBRARYDIR=${WORKDIR}/boost_${BOOST_VERSION}/android32/lib/ \
OPENSSL_ROOT_DIR=${WORKDIR}/openssl/ \
CMAKE_INCLUDE_PATH=${WORKDIR}/cppzmq/ \
CMAKE_LIBRARY_PATH=${WORKDIR}/zeromq4-1/.libs \
CXXFLAGS="-I ${WORKDIR}/zeromq4-1/include/" \
./build.sh release-android \
&& cd build \ && cd build \
&& make deploy && make deploy

View File

@ -8,6 +8,22 @@ if [ -z $BUILD_TYPE ]; then
BUILD_TYPE=release BUILD_TYPE=release
fi fi
# Return 0 if the command exists, 1 if it does not.
exists() {
command -v "$1" &>/dev/null
}
# Return the first value in $@ that's a runnable command.
find_command() {
for arg in "$@"; do
if exists "$arg"; then
echo "$arg"
return 0
fi
done
return 1
}
if [ "$BUILD_TYPE" == "release" ]; then if [ "$BUILD_TYPE" == "release" ]; then
echo "Building release" echo "Building release"
CONFIG="CONFIG+=release"; CONFIG="CONFIG+=release";
@ -24,14 +40,16 @@ elif [ "$BUILD_TYPE" == "release-static" ]; then
BIN_PATH=release/bin BIN_PATH=release/bin
elif [ "$BUILD_TYPE" == "release-android" ]; then elif [ "$BUILD_TYPE" == "release-android" ]; then
echo "Building release for ANDROID" echo "Building release for ANDROID"
CONFIG="CONFIG+=release static WITH_SCANNER"; CONFIG="CONFIG+=release static WITH_SCANNER DISABLE_PASS_STRENGTH_METER";
ANDROID=true ANDROID=true
BIN_PATH=release/bin BIN_PATH=release/bin
DISABLE_PASS_STRENGTH_METER=true
elif [ "$BUILD_TYPE" == "debug-android" ]; then elif [ "$BUILD_TYPE" == "debug-android" ]; then
echo "Building debug for ANDROID : ultra INSECURE !!" echo "Building debug for ANDROID : ultra INSECURE !!"
CONFIG="CONFIG+=debug qml_debug WITH_SCANNER"; CONFIG="CONFIG+=debug qml_debug WITH_SCANNER DISABLE_PASS_STRENGTH_METER";
ANDROID=true ANDROID=true
BIN_PATH=debug/bin BIN_PATH=debug/bin
DISABLE_PASS_STRENGTH_METER=true
elif [ "$BUILD_TYPE" == "debug" ]; then elif [ "$BUILD_TYPE" == "debug" ]; then
echo "Building debug" echo "Building debug"
CONFIG="CONFIG+=debug" CONFIG="CONFIG+=debug"
@ -57,15 +75,17 @@ fi
./get_libwallet_api.sh $BUILD_TYPE ./get_libwallet_api.sh $BUILD_TYPE
# build zxcvbn # build zxcvbn
$MAKE -C src/zxcvbn-c || exit if [ "$DISABLE_PASS_STRENGTH_METER" != true ]; then
$MAKE -C src/zxcvbn-c || exit
fi
if [ ! -d build ]; then mkdir build; fi if [ ! -d build ]; then mkdir build; fi
# Platform indepenent settings # Platform indepenent settings
if [ "$ANDROID" != true ] && ([ "$platform" == "linux32" ] || [ "$platform" == "linux64" ]); then if [ "$ANDROID" != true ] && ([ "$platform" == "linux32" ] || [ "$platform" == "linux64" ]); then
distro=$(lsb_release -is) exists lsb_release && distro="$(lsb_release -is)"
if [ "$distro" == "Ubuntu" ]; then if [ "$distro" = "Ubuntu" ] || [ "$distro" = "Fedora" ] || test -f /etc/fedora-release; then
CONFIG="$CONFIG libunwind_off" CONFIG="$CONFIG libunwind_off"
fi fi
fi fi
@ -85,7 +105,11 @@ popd
echo "var GUI_MONERO_VERSION = \"$TAGNAME\"" >> version.js echo "var GUI_MONERO_VERSION = \"$TAGNAME\"" >> version.js
cd build cd build
qmake ../monero-wallet-gui.pro "$CONFIG" || exit if ! QMAKE=$(find_command qmake qmake-qt5); then
echo "Failed to find suitable qmake command."
exit 1
fi
$QMAKE ../monero-wallet-gui.pro "$CONFIG" || exit
$MAKE || exit $MAKE || exit
# Copy monerod to bin folder # Copy monerod to bin folder

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -260,10 +260,51 @@ ListView {
return blockHeight return blockHeight
if (!isOut) if (!isOut)
return qsTr("UNCONFIRMED") + translationManager.emptyString return qsTr("UNCONFIRMED") + translationManager.emptyString
if (isFailed)
return qsTr("FAILED") + translationManager.emptyString
return qsTr("PENDING") + translationManager.emptyString return qsTr("PENDING") + translationManager.emptyString
} }
} }
Item { //separator
width: 100
height: 14
}
// -- "Received by" title
Text {
anchors.bottom: parent.bottom
font.family: "Arial"
font.pixelSize: 12
color: "#535353"
text: (isOut ? qsTr("Spent from:") : qsTr("Received by:")) + translationManager.emptyString
}
Item { //separator
width: 5
height: 14
}
// -- "Index" value
Text {
anchors.bottom: parent.bottom
font.family: "Arial"
font.pixelSize: 13
font.bold: true
color: "#545454"
text: "#" + subaddrIndex
}
Item { //separator
width: 5
height: 14
}
// -- "Label" value
Text {
anchors.bottom: parent.bottom
font.family: "Arial"
font.pixelSize: 13
color: "#545454"
text: label
elide: Text.ElideRight
width: detailsButton.x - x - 30
}
} }
// -- "Date", "Balance" and "Amound" section // -- "Date", "Balance" and "Amound" section

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -150,6 +150,8 @@ ListView {
return qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired) return qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired)
if (!isOut) if (!isOut)
return qsTr("UNCONFIRMED") + translationManager.emptyString return qsTr("UNCONFIRMED") + translationManager.emptyString
if (isFailed)
return qsTr("FAILED") + translationManager.emptyString
return qsTr("PENDING") + translationManager.emptyString return qsTr("PENDING") + translationManager.emptyString
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -30,6 +30,7 @@
import QtQuick 2.0 import QtQuick 2.0
Item { Item {
property alias image : buttonImage
property alias imageSource : buttonImage.source property alias imageSource : buttonImage.source
signal clicked(var mouse) signal clicked(var mouse)
@ -53,7 +54,8 @@ Item {
MouseArea { MouseArea {
id: buttonArea id: buttonArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: { onPressed: {
buttonImage.x = buttonImage.x + 2 buttonImage.x = buttonImage.x + 2

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

181
components/InputDialog.qml Normal file
View File

@ -0,0 +1,181 @@
// Copyright (c) 2014-2018, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.0
import "../components" as MoneroComponents
Item {
id: root
visible: false
Rectangle {
id: bg
z: parent.z + 1
anchors.fill: parent
color: "white"
opacity: 0.9
}
property alias labelText: label.text
property alias inputText: input.text
// same signals as Dialog has
signal accepted()
signal rejected()
function open() {
leftPanel.enabled = false
middlePanel.enabled = false
titleBar.enabled = false
show()
root.visible = true;
input.focus = true;
input.text = "";
}
function close() {
leftPanel.enabled = true
middlePanel.enabled = true
titleBar.enabled = true
root.visible = false;
}
ColumnLayout {
z: bg.z + 1
id: mainLayout
spacing: 10
anchors { fill: parent; margins: 35 }
ColumnLayout {
id: column
//anchors {fill: parent; margins: 16 }
Layout.alignment: Qt.AlignHCenter
Label {
id: label
Layout.alignment: Qt.AlignHCenter
// Layout.columnSpan: 2
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 18 * scaleRatio
font.family: "Arial"
color: "#555555"
}
TextField {
id : input
focus: true
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
font.family: "Arial"
font.pixelSize: 32 * scaleRatio
// echoMode: TextInput.Password
KeyNavigation.tab: okButton
style: TextFieldStyle {
renderType: Text.NativeRendering
textColor: "#35B05A"
// passwordCharacter: ""
// no background
background: Rectangle {
radius: 0
border.width: 0
}
}
Keys.onReturnPressed: {
root.close()
root.accepted()
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// underline
Rectangle {
height: 1
color: "#DBDBDB"
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
anchors.bottomMargin: 3
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
}
// Ok/Cancel buttons
RowLayout {
id: buttons
spacing: 60
Layout.alignment: Qt.AlignHCenter
MoneroComponents.StandardButton {
id: cancelButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: input
onClicked: {
root.close()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: okButton
width: 120
fontSize: 14
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Ok")
KeyNavigation.tab: cancelButton
onClicked: {
root.close()
root.accepted()
}
}
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -37,6 +37,7 @@ Item {
property alias cursorPosition: input.cursorPosition property alias cursorPosition: input.cursorPosition
property alias echoMode: input.echoMode property alias echoMode: input.echoMode
property int fontSize: 18 * scaleRatio property int fontSize: 18 * scaleRatio
property bool showBorder: true
property bool error: false property bool error: false
signal editingFinished() signal editingFinished()
signal accepted(); signal accepted();
@ -52,6 +53,7 @@ Item {
} }
Rectangle { Rectangle {
visible: showBorder
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: 1 * scaleRatio anchors.bottomMargin: 1 * scaleRatio
color: "#DBDBDB" color: "#DBDBDB"

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -0,0 +1,254 @@
// Copyright (c) 2017, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4
import QtQuick.Window 2.0
import "../components" as MoneroComponents
Item {
id: root
visible: false
Rectangle {
id: bg
z: parent.z + 1
anchors.fill: parent
color: "white"
opacity: 0.9
}
property alias password: passwordInput1.text
// same signals as Dialog has
signal accepted()
signal rejected()
signal closeCallback()
function open() {
leftPanel.enabled = false
middlePanel.enabled = false
titleBar.enabled = false
show();
root.visible = true;
passwordInput1.text = "";
passwordInput2.text = "";
passwordInput1.focus = true
}
function close() {
leftPanel.enabled = true
middlePanel.enabled = true
titleBar.enabled = true
root.visible = false;
closeCallback();
}
// TODO: implement without hardcoding sizes
width: 480
height: 360
// Make window draggable
MouseArea {
anchors.fill: parent
property point lastMousePos: Qt.point(0, 0)
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
}
ColumnLayout {
z: bg.z + 1
id: mainLayout
spacing: 10
anchors { fill: parent; margins: 35 * scaleRatio }
ColumnLayout {
id: column
//anchors {fill: parent; margins: 16 }
Layout.alignment: Qt.AlignHCenter
Label {
text: qsTr("Please enter new password")
Layout.alignment: Qt.AlignHCenter
Layout.columnSpan: 2
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 18 * scaleRatio
font.family: "Arial"
color: "#555555"
}
TextField {
id : passwordInput1
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 400 * scaleRatio
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
font.family: "Arial"
font.pixelSize: 32 * scaleRatio
echoMode: TextInput.Password
KeyNavigation.tab: passwordInput2
style: TextFieldStyle {
renderType: Text.NativeRendering
textColor: "#35B05A"
passwordCharacter: "•"
// no background
background: Rectangle {
radius: 0
border.width: 0
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// underline
Rectangle {
height: 1
color: "#DBDBDB"
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
anchors.bottomMargin: 3
Layout.maximumWidth: passwordInput1.width
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
Label {
text: qsTr("Please confirm new password")
Layout.alignment: Qt.AlignHCenter
Layout.columnSpan: 2
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 18 * scaleRatio
font.family: "Arial"
color: "#555555"
}
TextField {
id : passwordInput2
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 400 * scaleRatio
horizontalAlignment: TextInput.AlignHCenter
verticalAlignment: TextInput.AlignVCenter
font.family: "Arial"
font.pixelSize: 32 * scaleRatio
echoMode: TextInput.Password
KeyNavigation.tab: okButton
style: TextFieldStyle {
renderType: Text.NativeRendering
textColor: "#35B05A"
passwordCharacter: "•"
// no background
background: Rectangle {
radius: 0
border.width: 0
}
}
Keys.onReturnPressed: {
if (passwordInput1.text === passwordInput2.text) {
root.close()
root.accepted()
}
}
Keys.onEscapePressed: {
root.close()
root.rejected()
}
}
// underline
Rectangle {
height: 1
color: "#DBDBDB"
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
anchors.bottomMargin: 3
Layout.maximumWidth: passwordInput1.width
}
// padding
Rectangle {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
height: 10
opacity: 0
color: "black"
}
}
// Ok/Cancel buttons
RowLayout {
id: buttons
spacing: 60 * scaleRatio
Layout.alignment: Qt.AlignHCenter
MoneroComponents.StandardButton {
id: cancelButton
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Cancel") + translationManager.emptyString
KeyNavigation.tab: passwordInput1
onClicked: {
root.close()
root.rejected()
}
}
MoneroComponents.StandardButton {
id: okButton
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Continue")
KeyNavigation.tab: cancelButton
enabled: passwordInput1.text === passwordInput2.text
onClicked: {
root.close()
root.accepted()
}
}
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2017, The Monero Project // Copyright (c) 2017-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -0,0 +1,109 @@
// Copyright (c) 2014-2018, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import QtQuick 2.0
import moneroComponents.Clipboard 1.0
ListView {
id: listView
clip: true
boundsBehavior: ListView.StopAtBounds
highlightMoveDuration: 0
delegate: Rectangle {
id: delegate
height: 64
width: listView.width
LineEdit {
id: addressLine
fontSize: 12
readOnly: true
width: parent.width
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 5
onTextChanged: cursorPosition = 0
text: address
showBorder: false
IconButton {
id: clipboardButton
imageSource: "../images/copyToClipboard.png"
onClicked: {
console.log(addressLine.text + " copied to clipboard");
clipboard.setText(addressLine.text);
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3);
}
}
}
Text {
id: indexText
anchors.top: addressLine.bottom
anchors.left: parent.left
anchors.leftMargin: 20
font.family: "Arial"
font.bold: true
font.pixelSize: 12
color: "#444444"
text: "#" + index
}
Text {
id: labelText
anchors.top: addressLine.bottom
anchors.left: indexText.right
anchors.right: parent.right
anchors.leftMargin: 10
font.family: "Arial"
font.bold: true
font.pixelSize: 12
color: "#444444"
text: label
}
MouseArea {
z: 5
anchors.top: parent.top
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.rightMargin: clipboardButton.width
onClicked: listView.currentIndex = index
}
}
highlight: Rectangle {
height: 64
color: '#FF4304'
opacity: 0.2
z: 2
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
Copyright (c) 2014-2017, The Monero Project Copyright (c) 2014-2018, The Monero Project
All rights reserved. All rights reserved.

View File

@ -1,5 +1,5 @@
; Monero Helium Hydra GUI Wallet Installer for Windows ; Monero Helium Hydra GUI Wallet Installer for Windows
; Copyright (c) 2014-2017, The Monero Project ; Copyright (c) 2014-2018, The Monero Project
; See LICENSE ; See LICENSE
[Setup] [Setup]
@ -33,173 +33,187 @@ Name: "en"; MessagesFile: "compiler:Default.isl"
[Files] [Files]
Source: "ReadMe.htm"; DestDir: "{app}"; Flags: comparetimestamp ; The use of the flag "ignoreversion" for the following entries leads to the following behaviour:
; When updating / upgrading an existing installation ALL existing files are replaced with the files in this
; installer, regardless of file dates, version info within the files, or type of file (textual file or
; .exe/.dll file possibly with version info).
;
; This is far more robust than relying on version info or on file dates (flag "comparetimestamp").
; As of version 0.11.1.0, the Monero .exe files do not carry version info anyway in their .exe headers.
; The only small drawback seems to be somewhat longer update times because each and every file is
; copied again, even if already present with correct file date and identical content.
;
; Note that it would be very dangerous to use "ignoreversion" on files that may be shared with other
; applications somehow. Luckily this is no issue here because ALL files are "private" to Monero.
Source: "ReadMe.htm"; DestDir: "{app}"; Flags: ignoreversion
Source: "FinishImage.bmp"; Flags: dontcopy Source: "FinishImage.bmp"; Flags: dontcopy
; Monero GUI wallet ; Monero GUI wallet
Source: "bin\monero-wallet-gui.exe"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\monero-wallet-gui.exe"; DestDir: "{app}"; Flags: ignoreversion
; Monero GUI wallet log file ; Monero GUI wallet log file
; The GUI wallet does not have the "--log-file" command-line option of the CLI wallet and insists to put the .log beside the .exe ; The GUI wallet does not have the "--log-file" command-line option of the CLI wallet and insists to put the .log beside the .exe
; so pre-create the file and give the necessary permissions to the wallet to write into it ; so pre-create the file and give the necessary permissions to the wallet to write into it
Source: "monero-wallet-gui.log"; DestDir: "{app}"; Flags: comparetimestamp; Permissions: users-modify ; Flag is "onlyifdoesntexist": We do not want to overwrite an already existing log
Source: "monero-wallet-gui.log"; DestDir: "{app}"; Flags: onlyifdoesntexist; Permissions: users-modify
; Monero CLI wallet ; Monero CLI wallet
Source: "bin\monero-wallet-cli.exe"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\monero-wallet-cli.exe"; DestDir: "{app}"; Flags: ignoreversion
; Monero wallet RPC interface implementation ; Monero wallet RPC interface implementation
Source: "bin\monero-wallet-rpc.exe"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\monero-wallet-rpc.exe"; DestDir: "{app}"; Flags: ignoreversion
; Monero daemon ; Monero daemon
Source: "bin\monerod.exe"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\monerod.exe"; DestDir: "{app}"; Flags: ignoreversion
; Monero daemon wrapped in a batch file that stops before the text window closes, to see any error messages ; Monero daemon wrapped in a batch file that stops before the text window closes, to see any error messages
Source: "monero-daemon.bat"; DestDir: "{app}"; Flags: comparetimestamp; Source: "monero-daemon.bat"; DestDir: "{app}"; Flags: ignoreversion;
; Monero blockchain utilities ; Monero blockchain utilities
Source: "bin\monero-blockchain-export.exe"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\monero-blockchain-export.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\monero-blockchain-import.exe"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\monero-blockchain-import.exe"; DestDir: "{app}"; Flags: ignoreversion
; was present in 0.10.3.1, not present anymore in 0.11.1.0 ; was present in 0.10.3.1, not present anymore in 0.11.1.0
; Source: "bin\monero-utils-deserialize.exe"; DestDir: "{app}"; Flags: comparetimestamp ; Source: "bin\monero-utils-deserialize.exe"; DestDir: "{app}"; Flags: ignoreversion
; Various .qm files for translating the wallet UI "on the fly" into all supported languages ; Various .qm files for translating the wallet UI "on the fly" into all supported languages
Source: "bin\translations\*"; DestDir: "{app}\translations"; Flags: recursesubdirs comparetimestamp Source: "bin\translations\*"; DestDir: "{app}\translations"; Flags: recursesubdirs ignoreversion
; Core Qt runtime ; Core Qt runtime
Source: "bin\Qt5Core.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Core.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Gui.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Multimedia.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Multimedia.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5MultimediaQuick_p.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5MultimediaQuick_p.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Network.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Network.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Qml.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Qml.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Quick.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Quick.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Svg.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Svg.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5Widgets.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\Qt5XmlPatterns.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\Qt5XmlPatterns.dll"; DestDir: "{app}"; Flags: ignoreversion
; Qt QML elements like the local files selector "FolderListModel" and "Settings" ; Qt QML elements like the local files selector "FolderListModel" and "Settings"
Source: "bin\Qt\*"; DestDir: "{app}\Qt"; Flags: recursesubdirs comparetimestamp Source: "bin\Qt\*"; DestDir: "{app}\Qt"; Flags: recursesubdirs ignoreversion
; Qt audio support ; Qt audio support
Source: "bin\audio\*"; DestDir: "{app}\audio"; Flags: recursesubdirs comparetimestamp Source: "bin\audio\*"; DestDir: "{app}\audio"; Flags: recursesubdirs ignoreversion
; Qt bearer / network connection management ; Qt bearer / network connection management
Source: "bin\bearer\*"; DestDir: "{app}\bearer"; Flags: recursesubdirs comparetimestamp Source: "bin\bearer\*"; DestDir: "{app}\bearer"; Flags: recursesubdirs ignoreversion
; Qt Windows platform plugin ; Qt Windows platform plugin
Source: "bin\platforms\qwindows.dll"; DestDir: "{app}\platforms"; Flags: comparetimestamp Source: "bin\platforms\qwindows.dll"; DestDir: "{app}\platforms"; Flags: ignoreversion
; Qt support for SVG icons ; Qt support for SVG icons
Source: "bin\iconengines\*"; DestDir: "{app}\iconengines"; Flags: recursesubdirs comparetimestamp Source: "bin\iconengines\*"; DestDir: "{app}\iconengines"; Flags: recursesubdirs ignoreversion
; Qt support for various image formats (JPEG, BMP, SVG etc) ; Qt support for various image formats (JPEG, BMP, SVG etc)
Source: "bin\imageformats\*"; DestDir: "{app}\imageformats"; Flags: recursesubdirs comparetimestamp Source: "bin\imageformats\*"; DestDir: "{app}\imageformats"; Flags: recursesubdirs ignoreversion
; Qt multimedia support ; Qt multimedia support
Source: "bin\QtMultimedia\*"; DestDir: "{app}\QtMultimedia"; Flags: recursesubdirs comparetimestamp Source: "bin\QtMultimedia\*"; DestDir: "{app}\QtMultimedia"; Flags: recursesubdirs ignoreversion
Source: "bin\mediaservice\*"; DestDir: "{app}\mediaservice"; Flags: recursesubdirs comparetimestamp Source: "bin\mediaservice\*"; DestDir: "{app}\mediaservice"; Flags: recursesubdirs ignoreversion
; Qt support for "m3u" playlists ; Qt support for "m3u" playlists
; candidate for elimination? Don't think the GUI wallet needs such playlists ; candidate for elimination? Don't think the GUI wallet needs such playlists
Source: "bin\playlistformats\*"; DestDir: "{app}\playlistformats"; Flags: recursesubdirs comparetimestamp Source: "bin\playlistformats\*"; DestDir: "{app}\playlistformats"; Flags: recursesubdirs ignoreversion
; Qt graphical effects as part of the core runtime, effects like blurring and blending ; Qt graphical effects as part of the core runtime, effects like blurring and blending
Source: "bin\QtGraphicalEffects\*"; DestDir: "{app}\QtGraphicalEffects"; Flags: recursesubdirs comparetimestamp Source: "bin\QtGraphicalEffects\*"; DestDir: "{app}\QtGraphicalEffects"; Flags: recursesubdirs ignoreversion
; Some more Qt graphical effects ; Some more Qt graphical effects
; "private" as a name for this directory looks a little strange. Historical reasons? ; "private" as a name for this directory looks a little strange. Historical reasons?
Source: "bin\private\*"; DestDir: "{app}\private"; Flags: recursesubdirs comparetimestamp Source: "bin\private\*"; DestDir: "{app}\private"; Flags: recursesubdirs ignoreversion
; Qt QML files ; Qt QML files
Source: "bin\QtQml\*"; DestDir: "{app}\QtQml"; Flags: recursesubdirs comparetimestamp Source: "bin\QtQml\*"; DestDir: "{app}\QtQml"; Flags: recursesubdirs ignoreversion
; Qt Quick files ; Qt Quick files
Source: "bin\QtQuick\*"; DestDir: "{app}\QtQuick"; Flags: recursesubdirs comparetimestamp Source: "bin\QtQuick\*"; DestDir: "{app}\QtQuick"; Flags: recursesubdirs ignoreversion
Source: "bin\QtQuick.2\*"; DestDir: "{app}\QtQuick.2"; Flags: recursesubdirs comparetimestamp Source: "bin\QtQuick.2\*"; DestDir: "{app}\QtQuick.2"; Flags: recursesubdirs ignoreversion
; Qt Quick 2D Renderer fallback for systems / environments with "low-level graphics" i.e. without 3D support ; Qt Quick 2D Renderer fallback for systems / environments with "low-level graphics" i.e. without 3D support
Source: "bin\scenegraph\*"; DestDir: "{app}\scenegraph"; Flags: recursesubdirs comparetimestamp Source: "bin\scenegraph\*"; DestDir: "{app}\scenegraph"; Flags: recursesubdirs ignoreversion
Source: "bin\start-low-graphics-mode.bat"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\start-low-graphics-mode.bat"; DestDir: "{app}"; Flags: ignoreversion
; Mesa, open-source OpenGL implementation; part of "low-level graphics" support ; Mesa, open-source OpenGL implementation; part of "low-level graphics" support
Source: "bin\opengl32sw.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\opengl32sw.dll"; DestDir: "{app}"; Flags: ignoreversion
; Left out subdirectory "qmltooling" with the Qt QML debugger: Probably not relevant in an end-user package ; Left out subdirectory "qmltooling" with the Qt QML debugger: Probably not relevant in an end-user package
; Microsoft Direct3D runtime ; Microsoft Direct3D runtime
Source: "bin\D3Dcompiler_47.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\D3Dcompiler_47.dll"; DestDir: "{app}"; Flags: ignoreversion
; bzip2 support ; bzip2 support
Source: "bin\libbz2-1.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libbz2-1.dll"; DestDir: "{app}"; Flags: ignoreversion
; ANGLE ("Almost Native Graphics Layer Engine") support, as used by Qt ; ANGLE ("Almost Native Graphics Layer Engine") support, as used by Qt
Source: "bin\libEGL.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libEGL.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\libGLESV2.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libGLESV2.dll"; DestDir: "{app}"; Flags: ignoreversion
; FreeType font engine, as used by Qt ; FreeType font engine, as used by Qt
Source: "bin\libfreetype-6.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libfreetype-6.dll"; DestDir: "{app}"; Flags: ignoreversion
; GCC runtime, x64 version ; GCC runtime, x64 version
Source: "bin\libgcc_s_seh-1.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libgcc_s_seh-1.dll"; DestDir: "{app}"; Flags: ignoreversion
; GLib, low level core library e.g. for GNOME and GTK+ ; GLib, low level core library e.g. for GNOME and GTK+
; Really needed under Windows? ; Really needed under Windows?
Source: "bin\libglib-2.0-0.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libglib-2.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion
; Graphite font support ; Graphite font support
; Really needed? ; Really needed?
Source: "bin\libgraphite2.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libgraphite2.dll"; DestDir: "{app}"; Flags: ignoreversion
; HarfBuzz OpenType text shaping engine ; HarfBuzz OpenType text shaping engine
; Really needed? ; Really needed?
Source: "bin\libharfbuzz-0.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libharfbuzz-0.dll"; DestDir: "{app}"; Flags: ignoreversion
; LibIconv, conversions between character encodings ; LibIconv, conversions between character encodings
Source: "bin\libiconv-2.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libiconv-2.dll"; DestDir: "{app}"; Flags: ignoreversion
; Part of cygwin? Needed by Qt somehow? ; Part of cygwin? Needed by Qt somehow?
Source: "bin\libicudt57.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libicudt57.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\libicuin57.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libicuin57.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\libicuuc57.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libicuuc57.dll"; DestDir: "{app}"; Flags: ignoreversion
; Library for native language support, part of GNU gettext ; Library for native language support, part of GNU gettext
Source: "bin\libintl-8.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libintl-8.dll"; DestDir: "{app}"; Flags: ignoreversion
; JasPer, support for JPEG-2000 ; JasPer, support for JPEG-2000
; was present in 0.10.3.1, not present anymore in 0.11.1.0 ; was present in 0.10.3.1, not present anymore in 0.11.1.0
; Source: "bin\libjasper-1.dll"; DestDir: "{app}"; Flags: comparetimestamp ; Source: "bin\libjasper-1.dll"; DestDir: "{app}"; Flags: ignoreversion
; libjpeg, C library for reading and writing JPEG image files ; libjpeg, C library for reading and writing JPEG image files
Source: "bin\libjpeg-8.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libjpeg-8.dll"; DestDir: "{app}"; Flags: ignoreversion
; Little CMS, color management system ; Little CMS, color management system
Source: "bin\liblcms2-2.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\liblcms2-2.dll"; DestDir: "{app}"; Flags: ignoreversion
; XZ Utils, LZMA compression library ; XZ Utils, LZMA compression library
Source: "bin\liblzma-5.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\liblzma-5.dll"; DestDir: "{app}"; Flags: ignoreversion
; MNG / Portable Network Graphics ("animated PNG") ; MNG / Portable Network Graphics ("animated PNG")
Source: "bin\libmng-2.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libmng-2.dll"; DestDir: "{app}"; Flags: ignoreversion
; PCRE, Perl Compatible Regular Expressions ; PCRE, Perl Compatible Regular Expressions
Source: "bin\libpcre-1.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libpcre-1.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "bin\libpcre16-0.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libpcre16-0.dll"; DestDir: "{app}"; Flags: ignoreversion
; libpng, the official PNG reference library ; libpng, the official PNG reference library
Source: "bin\libpng16-16.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libpng16-16.dll"; DestDir: "{app}"; Flags: ignoreversion
; libstdc++, GNU Standard C++ Library ; libstdc++, GNU Standard C++ Library
Source: "bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libstdc++-6.dll"; DestDir: "{app}"; Flags: ignoreversion
; LibTIFF, TIFF Library and Utilities ; LibTIFF, TIFF Library and Utilities
Source: "bin\libtiff-5.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libtiff-5.dll"; DestDir: "{app}"; Flags: ignoreversion
; C++ threading support ; C++ threading support
Source: "bin\libwinpthread-1.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\libwinpthread-1.dll"; DestDir: "{app}"; Flags: ignoreversion
; zlib compression library ; zlib compression library
Source: "bin\zlib1.dll"; DestDir: "{app}"; Flags: comparetimestamp Source: "bin\zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion
[Tasks] [Tasks]

View File

@ -1,6 +1,6 @@
# Monero GUI Wallet Windows Installer # # Monero GUI Wallet Windows Installer #
Copyright (c) 2014-2017, The Monero Project Copyright (c) 2014-2018, The Monero Project
## Introduction ## ## Introduction ##

View File

@ -6,7 +6,7 @@
<body style="font-family: Arial, Helvetica, sans-serif"> <body style="font-family: Arial, Helvetica, sans-serif">
<h1>Monero Helium Hydra GUI Wallet</h1> <h1>Monero Helium Hydra GUI Wallet</h1>
<p>Copyright (c) 2014-2017, The Monero Project<br> <p>Copyright (c) 2014-2018, The Monero Project<br>
Date: September 19, 2017</p> Date: September 19, 2017</p>
<h2>Preface</h2> <h2>Preface</h2>

BIN
lang/flags/czech.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
lang/flags/denmark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
lang/flags/egypt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
lang/flags/slovakia.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -38,4 +38,8 @@ List of available languages for your wallet's seed:
<language display_name="עברית" locale="he_HE" wallet_language="English" flag="/lang/flags/israel.png" qs="none"/> <language display_name="עברית" locale="he_HE" wallet_language="English" flag="/lang/flags/israel.png" qs="none"/>
<language display_name="한국어" locale="ko_KO" wallet_language="English" flag="/lang/flags/south_korea.png" qs="none"/> <language display_name="한국어" locale="ko_KO" wallet_language="English" flag="/lang/flags/south_korea.png" qs="none"/>
<language display_name="Română" locale="ro_RO" wallet_language="English" flag="/lang/flags/romania.png" qs="none"/> <language display_name="Română" locale="ro_RO" wallet_language="English" flag="/lang/flags/romania.png" qs="none"/>
<language display_name="Dansk" locale="da_DK" wallet-language="English" flag="/lang/flags/denmark.png" qs="none"/>
<language display_name="Česky" locale="cs_CZ" wallet_language="English" flag="/lang/flags/czech.png" qs="none"/>
<language display_name="Slovensky" locale="sk_SK" wallet_language="English" flag="/lang/flags/slovakia.png" qs="none"/>
<language display_name="Arabic" locale="ar_AR" wallet_language="English" flag="/lang/flags/egypt.png" qs="none"/>
</languages> </languages>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -50,6 +50,8 @@
#include "model/TransactionHistorySortFilterModel.h" #include "model/TransactionHistorySortFilterModel.h"
#include "AddressBook.h" #include "AddressBook.h"
#include "model/AddressBookModel.h" #include "model/AddressBookModel.h"
#include "Subaddress.h"
#include "model/SubaddressModel.h"
#include "wallet/api/wallet2_api.h" #include "wallet/api/wallet2_api.h"
#include "MainApp.h" #include "MainApp.h"
@ -70,6 +72,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
Monero::Utils::onStartup();
// // Enable high DPI scaling on windows & linux // // Enable high DPI scaling on windows & linux
//#if !defined(Q_OS_ANDROID) && QT_VERSION >= 0x050600 //#if !defined(Q_OS_ANDROID) && QT_VERSION >= 0x050600
// QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
@ -132,6 +135,12 @@ int main(int argc, char *argv[])
qmlRegisterUncreatableType<AddressBook>("moneroComponents.AddressBook", 1, 0, "AddressBook", qmlRegisterUncreatableType<AddressBook>("moneroComponents.AddressBook", 1, 0, "AddressBook",
"AddressBook can't be instantiated directly"); "AddressBook can't be instantiated directly");
qmlRegisterUncreatableType<SubaddressModel>("moneroComponents.SubaddressModel", 1, 0, "SubaddressModel",
"SubaddressModel can't be instantiated directly");
qmlRegisterUncreatableType<Subaddress>("moneroComponents.Subaddress", 1, 0, "Subaddress",
"Subaddress can't be instantiated directly");
qRegisterMetaType<PendingTransaction::Priority>(); qRegisterMetaType<PendingTransaction::Priority>();
qRegisterMetaType<TransactionInfo::Direction>(); qRegisterMetaType<TransactionInfo::Direction>();
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>(); qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();

242
main.qml
View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -53,7 +53,7 @@ ApplicationWindow {
property var currentWallet; property var currentWallet;
property var transaction; property var transaction;
property var transactionDescription; property var transactionDescription;
property alias password : passwordDialog.password property var walletPassword
property bool isNewWallet: false property bool isNewWallet: false
property int restoreHeight:0 property int restoreHeight:0
property bool daemonSynced: false property bool daemonSynced: false
@ -144,6 +144,8 @@ ApplicationWindow {
else if(middlePanel.state === "Transfer") middlePanel.state = "Settings" else if(middlePanel.state === "Transfer") middlePanel.state = "Settings"
} }
if (middlePanel.state !== "Advanced") updateBalance();
leftPanel.selectItem(middlePanel.state) leftPanel.selectItem(middlePanel.state)
} }
@ -164,7 +166,7 @@ ApplicationWindow {
persistentSettings.restore_height = 0 persistentSettings.restore_height = 0
restoreHeight = 0; restoreHeight = 0;
persistentSettings.is_recovering = false persistentSettings.is_recovering = false
appWindow.password = "" walletPassword = ""
fileDialog.open(); fileDialog.open();
} }
@ -224,7 +226,7 @@ ApplicationWindow {
wallet_path = moneroAccountsDir + wallet_path; wallet_path = moneroAccountsDir + wallet_path;
// 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, ", testnet: ", persistentSettings.testnet); console.log("opening wallet at: ", wallet_path, ", testnet: ", persistentSettings.testnet);
walletManager.openWalletAsync(wallet_path, appWindow.password, walletManager.openWalletAsync(wallet_path, walletPassword,
persistentSettings.testnet); persistentSettings.testnet);
} }
@ -307,6 +309,13 @@ ApplicationWindow {
return path.replace(/.*[\/\\]/, '').replace(/\.keys$/, '') return path.replace(/.*[\/\\]/, '').replace(/\.keys$/, '')
} }
function updateBalance() {
if (!currentWallet)
return;
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.unlockedBalance(currentWallet.currentSubaddressAccount));
middlePanel.balanceText = leftPanel.balanceText = middlePanel.state === "Receive" ? qsTr("HIDDEN") : walletManager.displayAmount(currentWallet.balance(currentWallet.currentSubaddressAccount));
}
function onWalletConnectionStatusChanged(status){ function onWalletConnectionStatusChanged(status){
console.log("Wallet connection status changed " + status) console.log("Wallet connection status changed " + status)
middlePanel.updateStatus(); middlePanel.updateStatus();
@ -322,7 +331,7 @@ ApplicationWindow {
} }
// initialize transaction history once wallet is initialized first time; // initialize transaction history once wallet is initialized first time;
if (!walletInitialized) { if (!walletInitialized) {
currentWallet.history.refresh() currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
walletInitialized = true walletInitialized = true
} }
} }
@ -331,25 +340,25 @@ ApplicationWindow {
walletName = usefulName(wallet.path) walletName = usefulName(wallet.path)
console.log(">>> wallet opened: " + wallet) console.log(">>> wallet opened: " + wallet)
if (wallet.status !== Wallet.Status_Ok) { if (wallet.status !== Wallet.Status_Ok) {
if (appWindow.password === '') { passwordDialog.onAcceptedCallback = function() {
console.error("Error opening wallet with empty password: ", wallet.errorString); walletPassword = passwordDialog.password;
console.log("closing wallet async : " + wallet.address) appWindow.initialize();
closeWallet(); }
// try to open wallet with password; passwordDialog.onRejectedCallback = function() {
passwordDialog.open(walletName); walletPassword = "";
} else { //appWindow.enableUI(false)
// opening with password but password doesn't match rootItem.state = "wizard";
console.error("Error opening wallet with password: ", wallet.errorString); }
// opening with password but password doesn't match
informationPopup.title = qsTr("Error") + translationManager.emptyString; console.error("Error opening wallet with password: ", wallet.errorString);
informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString; informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.icon = StandardIcon.Critical informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString;
console.log("closing wallet async : " + wallet.address) informationPopup.icon = StandardIcon.Critical
closeWallet(); console.log("closing wallet async : " + wallet.address)
informationPopup.open() closeWallet();
informationPopup.onCloseCallback = function() { informationPopup.open()
passwordDialog.open(walletName) informationPopup.onCloseCallback = function() {
} passwordDialog.open(walletName)
} }
return; return;
} }
@ -365,13 +374,12 @@ ApplicationWindow {
function onWalletUpdate() { function onWalletUpdate() {
console.log(">>> wallet updated") console.log(">>> wallet updated")
middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance); updateBalance();
middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance);
// Update history if new block found since last update // Update history if new block found since last update
if(foundNewBlock) { if(foundNewBlock) {
foundNewBlock = false; foundNewBlock = false;
console.log("New block found - updating history") console.log("New block found - updating history")
currentWallet.history.refresh() currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
timeToUnlock = currentWallet.history.minutesToUnlock timeToUnlock = currentWallet.history.minutesToUnlock
leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)") : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance"); leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? (timeToUnlock == 20)? qsTr("Unlocked balance (waiting for block)") : qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance");
} }
@ -447,6 +455,9 @@ ApplicationWindow {
console.log("Saving wallet after first refresh"); console.log("Saving wallet after first refresh");
currentWallet.store() currentWallet.store()
isNewWallet = false isNewWallet = false
// Update History
currentWallet.history.refresh(currentWallet.currentSubaddressAccount);
} }
// recovering from seed is finished after first refresh // recovering from seed is finished after first refresh
@ -457,7 +468,7 @@ ApplicationWindow {
// Update history on every refresh if it's empty // Update history on every refresh if it's empty
if(currentWallet.history.count == 0) if(currentWallet.history.count == 0)
currentWallet.history.refresh() currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
onWalletUpdate(); onWalletUpdate();
} }
@ -520,19 +531,21 @@ ApplicationWindow {
currentWallet.refresh() currentWallet.refresh()
console.log("Confirmed money found") console.log("Confirmed money found")
// history refresh is handled by walletUpdated // history refresh is handled by walletUpdated
currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model
currentWallet.subaddress.refresh(currentWallet.currentSubaddressAccount)
} }
function onWalletUnconfirmedMoneyReceived(txId, amount) { function onWalletUnconfirmedMoneyReceived(txId, amount) {
// refresh history // refresh history
console.log("unconfirmed money found") console.log("unconfirmed money found")
currentWallet.history.refresh() currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
} }
function onWalletMoneySent(txId, amount) { function onWalletMoneySent(txId, amount) {
// refresh transaction history here // refresh transaction history here
console.log("money sent found") console.log("money sent found")
currentWallet.refresh() currentWallet.refresh()
currentWallet.history.refresh() // this will refresh model currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model
} }
function walletsFound() { function walletsFound() {
@ -578,8 +591,11 @@ ApplicationWindow {
// here we show confirmation popup; // here we show confirmation popup;
transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString
transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n") transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n");
+ (address === "" ? "" : (qsTr("\nAddress: ") + address)) for (var i = 0; i < transaction.subaddrIndices.length; ++i)
transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i]
transactionConfirmationPopup.text +=
(address === "" ? "" : (qsTr("\n\nAddress: ") + address))
+ (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId)) + (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId))
+ qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount) + qsTr("\n\nAmount: ") + walletManager.displayAmount(transaction.amount)
+ qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee) + qsTr("\nFee: ") + walletManager.displayAmount(transaction.fee)
@ -764,7 +780,11 @@ ApplicationWindow {
", address: ", address, ", address: ", address,
", message: ", message); ", message: ", message);
var result = currentWallet.getTxProof(txid, address, message); var result;
if (address.length > 0)
result = currentWallet.getTxProof(txid, address, message);
if (!result || result.startsWith("error|"))
result = currentWallet.getSpendProof(txid, message);
informationPopup.title = qsTr("Payment proof") + translationManager.emptyString; informationPopup.title = qsTr("Payment proof") + translationManager.emptyString;
if (result.startsWith("error|")) { if (result.startsWith("error|")) {
var errorString = result.split("|")[1]; var errorString = result.split("|")[1];
@ -786,12 +806,16 @@ ApplicationWindow {
", message: ", message, ", message: ", message,
", signature: ", signature); ", signature: ", signature);
var result = currentWallet.checkTxProof(txid, address, message, signature); var result;
if (address.length > 0)
result = currentWallet.checkTxProof(txid, address, message, signature);
else
result = currentWallet.checkSpendProof(txid, message, signature);
var results = result.split("|"); var results = result.split("|");
if (results.length == 5 && results[0] == "true") { if (address.length > 0 && results.length == 5 && results[0] === "true") {
var good = results[1] == "true"; var good = results[1] === "true";
var received = results[2]; var received = results[2];
var in_pool = results[3] == "true"; var in_pool = results[3] === "true";
var confirmations = results[4]; var confirmations = results[4];
informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString; informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString;
@ -812,6 +836,12 @@ ApplicationWindow {
informationPopup.text = qsTr("This address received nothing"); informationPopup.text = qsTr("This address received nothing");
} }
} }
else if (results.length == 2 && results[0] === "true") {
var good = results[1] === "true";
informationPopup.title = qsTr("Payment proof check") + translationManager.emptyString;
informationPopup.icon = good ? StandardIcon.Information : StandardIcon.Critical;
informationPopup.text = good ? qsTr("Good signature") : qsTr("Bad signature");
}
else { else {
informationPopup.title = qsTr("Error") + translationManager.emptyString; informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = currentWallet.errorString; informationPopup.text = currentWallet.errorString;
@ -931,7 +961,14 @@ ApplicationWindow {
rootItem.state = "wizard" rootItem.state = "wizard"
} else { } else {
rootItem.state = "normal" rootItem.state = "normal"
passwordDialog.onAcceptedCallback = function() {
walletPassword = passwordDialog.password;
initialize(persistentSettings); initialize(persistentSettings);
}
passwordDialog.onRejectedCallback = function() {
rootItem.state = "wizard"
}
passwordDialog.open(usefulName(walletPath()))
} }
checkUpdates(); checkUpdates();
@ -993,8 +1030,8 @@ ApplicationWindow {
id: transactionConfirmationPopup id: transactionConfirmationPopup
onAccepted: { onAccepted: {
close(); close();
transactionConfirmationPasswordDialog.onAcceptedCallback = function() { passwordDialog.onAcceptedCallback = function() {
if(appWindow.password === transactionConfirmationPasswordDialog.password){ if(walletPassword === passwordDialog.password){
// Save transaction to file if view only wallet // Save transaction to file if view only wallet
if(viewOnly) { if(viewOnly) {
saveTxDialog.open(); saveTxDialog.open();
@ -1006,15 +1043,12 @@ ApplicationWindow {
informationPopup.text = qsTr("Wrong password"); informationPopup.text = qsTr("Wrong password");
informationPopup.open() informationPopup.open()
informationPopup.onCloseCallback = function() { informationPopup.onCloseCallback = function() {
transactionConfirmationPasswordDialog.open() passwordDialog.open()
} }
} }
transactionConfirmationPasswordDialog.password = ""
} }
transactionConfirmationPasswordDialog.onRejectedCallback = function() { passwordDialog.onRejectedCallback = null;
transactionConfirmationPasswordDialog.password = "" passwordDialog.open()
}
transactionConfirmationPasswordDialog.open()
} }
} }
@ -1052,7 +1086,15 @@ ApplicationWindow {
console.log(moneroAccountsDir) console.log(moneroAccountsDir)
console.log(fileDialog.fileUrl) console.log(fileDialog.fileUrl)
console.log(persistentSettings.wallet_path) console.log(persistentSettings.wallet_path)
initialize(); passwordDialog.onAcceptedCallback = function() {
walletPassword = passwordDialog.password;
initialize();
}
passwordDialog.onRejectedCallback = function() {
console.log("Canceled")
rootItem.state = "wizard";
}
passwordDialog.open(usefulName(walletPath()));
} }
onRejected: { onRejected: {
console.log("Canceled") console.log("Canceled")
@ -1118,21 +1160,6 @@ ApplicationWindow {
visible: false visible: false
z: parent.z + 1 z: parent.z + 1
anchors.fill: parent anchors.fill: parent
onAccepted: {
appWindow.initialize();
}
onRejected: {
//appWindow.enableUI(false)
rootItem.state = "wizard"
}
}
PasswordDialog {
id: transactionConfirmationPasswordDialog
z: parent.z + 1
visible:false
anchors.fill: parent
property var onAcceptedCallback property var onAcceptedCallback
property var onRejectedCallback property var onRejectedCallback
onAccepted: { onAccepted: {
@ -1144,35 +1171,44 @@ ApplicationWindow {
onRejectedCallback(); onRejectedCallback();
} }
} }
PasswordDialog { NewPasswordDialog {
id: settingsPasswordDialog id: newPasswordDialog
z: parent.z + 1 z: parent.z + 1
visible:false visible:false
anchors.fill: parent anchors.fill: parent
onAccepted: { onAccepted: {
if(appWindow.password === settingsPasswordDialog.password){ if (currentWallet.setPassword(newPasswordDialog.password)) {
if(currentWallet.seedLanguage == "") { appWindow.walletPassword = newPasswordDialog.password;
console.log("No seed language set. Using English as default"); informationPopup.title = qsTr("Information") + translationManager.emptyString;
currentWallet.setSeedLanguage("English"); informationPopup.text = qsTr("Password changed successfully") + translationManager.emptyString;
} informationPopup.icon = StandardIcon.Information;
// Load keys page
middlePanel.state = "Keys"
} else { } else {
informationPopup.title = qsTr("Error") + translationManager.emptyString; informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password"); informationPopup.text = qsTr("Error: ") + currentWallet.errorString;
informationPopup.open() informationPopup.icon = StandardIcon.Critical;
informationPopup.onCloseCallback = function() {
settingsPasswordDialog.open()
}
} }
informationPopup.onCloseCallback = null;
settingsPasswordDialog.password = "" informationPopup.open();
} }
onRejected: { onRejected: {
appWindow.showPageRequest("Settings"); }
}
InputDialog {
id: inputDialog
visible: false
z: parent.z + 1
anchors.fill: parent
property var onAcceptedCallback
property var onRejectedCallback
onAccepted: {
if (onAcceptedCallback)
onAcceptedCallback()
}
onRejected: {
if (onRejectedCallback)
onRejectedCallback()
} }
} }
@ -1249,16 +1285,40 @@ ApplicationWindow {
anchors.top: mobileHeader.bottom anchors.top: mobileHeader.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
onDashboardClicked: {middlePanel.state = "Dashboard"; if(isMobile) hideMenu()} onDashboardClicked: { middlePanel.state = "Dashboard"; if(isMobile) hideMenu(); updateBalance(); }
onTransferClicked: {middlePanel.state = "Transfer"; if(isMobile) hideMenu()} onTransferClicked: { middlePanel.state = "Transfer"; if(isMobile) hideMenu(); updateBalance(); }
onReceiveClicked: {middlePanel.state = "Receive"; if(isMobile) hideMenu()} onReceiveClicked: { middlePanel.state = "Receive"; if(isMobile) hideMenu(); updateBalance(); }
onTxkeyClicked: {middlePanel.state = "TxKey"; if(isMobile) hideMenu()} onTxkeyClicked: { middlePanel.state = "TxKey"; if(isMobile) hideMenu(); updateBalance(); }
onHistoryClicked: {middlePanel.state = "History"; if(isMobile) hideMenu()} onHistoryClicked: { middlePanel.state = "History"; if(isMobile) hideMenu(); updateBalance(); }
onAddressBookClicked: {middlePanel.state = "AddressBook"; if(isMobile) hideMenu()} onAddressBookClicked: { middlePanel.state = "AddressBook"; if(isMobile) hideMenu(); updateBalance(); }
onMiningClicked: {middlePanel.state = "Mining"; if(isMobile) hideMenu()} onMiningClicked: { middlePanel.state = "Mining"; if(isMobile) hideMenu(); updateBalance(); }
onSignClicked: {middlePanel.state = "Sign"; if(isMobile) hideMenu()} onSignClicked: { middlePanel.state = "Sign"; if(isMobile) hideMenu(); updateBalance(); }
onSettingsClicked: {middlePanel.state = "Settings"; if(isMobile) hideMenu()} onSettingsClicked: { middlePanel.state = "Settings"; if(isMobile) hideMenu(); updateBalance(); }
onKeysClicked: {settingsPasswordDialog.open(); if(isMobile) hideMenu()} onKeysClicked: {
passwordDialog.onAcceptedCallback = function() {
if(walletPassword === passwordDialog.password){
if(currentWallet.seedLanguage == "") {
console.log("No seed language set. Using English as default");
currentWallet.setSeedLanguage("English");
}
// Load keys page
middlePanel.state = "Keys"
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password");
informationPopup.open()
informationPopup.onCloseCallback = function() {
passwordDialog.open()
}
}
}
passwordDialog.onRejectedCallback = function() {
appWindow.showPageRequest("Settings");
}
passwordDialog.open();
if(isMobile) hideMenu();
updateBalance();
}
} }
RightPanel { RightPanel {

View File

@ -35,6 +35,8 @@ HEADERS += \
src/QR-Code-generator/QrSegment.hpp \ src/QR-Code-generator/QrSegment.hpp \
src/model/AddressBookModel.h \ src/model/AddressBookModel.h \
src/libwalletqt/AddressBook.h \ src/libwalletqt/AddressBook.h \
src/model/SubaddressModel.h \
src/libwalletqt/Subaddress.h \
src/zxcvbn-c/zxcvbn.h \ src/zxcvbn-c/zxcvbn.h \
src/libwalletqt/UnsignedTransaction.h \ src/libwalletqt/UnsignedTransaction.h \
MainApp.h MainApp.h
@ -58,10 +60,18 @@ SOURCES += main.cpp \
src/QR-Code-generator/QrSegment.cpp \ src/QR-Code-generator/QrSegment.cpp \
src/model/AddressBookModel.cpp \ src/model/AddressBookModel.cpp \
src/libwalletqt/AddressBook.cpp \ src/libwalletqt/AddressBook.cpp \
src/model/SubaddressModel.cpp \
src/libwalletqt/Subaddress.cpp \
src/zxcvbn-c/zxcvbn.c \ src/zxcvbn-c/zxcvbn.c \
src/libwalletqt/UnsignedTransaction.cpp \ src/libwalletqt/UnsignedTransaction.cpp \
MainApp.cpp MainApp.cpp
CONFIG(DISABLE_PASS_STRENGTH_METER) {
HEADERS -= src/zxcvbn-c/zxcvbn.h
SOURCES -= src/zxcvbn-c/zxcvbn.c
DEFINES += "DISABLE_PASS_STRENGTH_METER"
}
!ios { !ios {
HEADERS += src/daemon/DaemonManager.h HEADERS += src/daemon/DaemonManager.h
SOURCES += src/daemon/DaemonManager.cpp SOURCES += src/daemon/DaemonManager.cpp
@ -317,6 +327,10 @@ TRANSLATIONS = \ # English is default language, no explicit translation file
$$PWD/translations/monero-core_he.ts \ # Hebrew $$PWD/translations/monero-core_he.ts \ # Hebrew
$$PWD/translations/monero-core_ko.ts \ # Korean $$PWD/translations/monero-core_ko.ts \ # Korean
$$PWD/translations/monero-core_ro.ts \ # Romanian $$PWD/translations/monero-core_ro.ts \ # Romanian
$$PWD/translations/monero-core_da.ts \ # Danish
$$PWD/translations/monero-core_cs.ts \ # Czech
$$PWD/translations/monero-core_sk.ts \ # Slovak
$$PWD/translations/monero-core_ar.ts \ # Arabic
CONFIG(release, debug|release) { CONFIG(release, debug|release) {
DESTDIR = release/bin DESTDIR = release/bin

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -546,7 +546,7 @@ Rectangle {
function onPageCompleted() { function onPageCompleted() {
if(currentWallet != null && typeof currentWallet.history !== "undefined" ) { if(currentWallet != null && typeof currentWallet.history !== "undefined" ) {
currentWallet.history.refresh() currentWallet.history.refresh(currentWallet.currentSubaddressAccount)
table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null
transactionTypeDropdown.update() transactionTypeDropdown.update()
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -151,7 +151,7 @@ Rectangle {
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
pressedColor: "#FF4304" pressedColor: "#FF4304"
onClicked: { onClicked: {
var success = walletManager.startMining(appWindow.currentWallet.address, soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery) var success = walletManager.startMining(appWindow.currentWallet.address(0, 0), soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery)
if (success) { if (success) {
update() update()
} else { } else {

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -38,53 +38,26 @@ import moneroComponents.Wallet 1.0
import moneroComponents.WalletManager 1.0 import moneroComponents.WalletManager 1.0
import moneroComponents.TransactionHistory 1.0 import moneroComponents.TransactionHistory 1.0
import moneroComponents.TransactionHistoryModel 1.0 import moneroComponents.TransactionHistoryModel 1.0
import moneroComponents.Subaddress 1.0
import moneroComponents.SubaddressModel 1.0
Rectangle { Rectangle {
id: pageReceive
color: "#F0EEEE" color: "#F0EEEE"
property alias addressText : addressLine.text
property alias paymentIdText : paymentIdLine.text
property alias integratedAddressText : integratedAddressLine.text
property var model property var model
property var current_address
property alias addressText : pageReceive.current_address
property string trackingLineText: "" property string trackingLineText: ""
function updatePaymentId(payment_id) {
if (typeof appWindow.currentWallet === 'undefined' || appWindow.currentWallet == null)
return
// generate a new one if not given as argument
if (typeof payment_id === 'undefined') {
payment_id = appWindow.currentWallet.generatePaymentId()
paymentIdLine.text = payment_id
}
if (payment_id.length > 0) {
integratedAddressLine.text = appWindow.currentWallet.integratedAddress(payment_id)
if (integratedAddressLine.text === "")
integratedAddressLine.text = qsTr("Invalid payment ID")
}
else {
paymentIdLine.text = ""
integratedAddressLine.text = ""
}
update()
}
function makeQRCodeString() { function makeQRCodeString() {
var s = "monero:" var s = "monero:"
var nfields = 0 var nfields = 0
s += addressLine.text s += current_address;
var amount = amountLine.text.trim() var amount = amountLine.text.trim()
if (amount !== "") { if (amount !== "") {
s += (nfields++ ? "&" : "?") s += (nfields++ ? "&" : "?")
s += "tx_amount=" + amount s += "tx_amount=" + amount
} }
var pid = paymentIdLine.text.trim()
if (pid !== "") {
s += (nfields++ ? "&" : "?")
s += "tx_payment_id=" + pid
}
return s return s
} }
@ -112,13 +85,14 @@ Rectangle {
var count = model.rowCount() var count = model.rowCount()
var totalAmount = 0 var totalAmount = 0
var nTransactions = 0 var nTransactions = 0
var list = "" var list = []
var blockchainHeight = 0 var blockchainHeight = 0
for (var i = 0; i < count; ++i) { for (var i = 0; i < count; ++i) {
var idx = model.index(i, 0) var idx = model.index(i, 0)
var isout = model.data(idx, TransactionHistoryModel.TransactionIsOutRole); var isout = model.data(idx, TransactionHistoryModel.TransactionIsOutRole);
var payment_id = model.data(idx, TransactionHistoryModel.TransactionPaymentIdRole); var subaddrAccount = model.data(idx, TransactionHistoryModel.TransactionSubaddrAccountRole);
if (!isout && payment_id == paymentIdLine.text) { var subaddrIndex = model.data(idx, TransactionHistoryModel.TransactionSubaddrIndexRole);
if (!isout && subaddrAccount == appWindow.currentWallet.currentSubaddressAccount && subaddrIndex == table.currentIndex) {
var amount = model.data(idx, TransactionHistoryModel.TransactionAtomicAmountRole); var amount = model.data(idx, TransactionHistoryModel.TransactionAtomicAmountRole);
totalAmount = walletManager.addi(totalAmount, amount) totalAmount = walletManager.addi(totalAmount, amount)
nTransactions += 1 nTransactions += 1
@ -126,21 +100,25 @@ Rectangle {
var txid = model.data(idx, TransactionHistoryModel.TransactionHashRole); var txid = model.data(idx, TransactionHistoryModel.TransactionHashRole);
var blockHeight = model.data(idx, TransactionHistoryModel.TransactionBlockHeightRole); var blockHeight = model.data(idx, TransactionHistoryModel.TransactionBlockHeightRole);
if (blockHeight == 0) { if (blockHeight == 0) {
list += qsTr("in the txpool: %1").arg(txid) + translationManager.emptyString list.push(qsTr("in the txpool: %1").arg(txid) + translationManager.emptyString)
} else { } else {
if (blockchainHeight == 0) if (blockchainHeight == 0)
blockchainHeight = walletManager.blockchainHeight() blockchainHeight = walletManager.blockchainHeight()
var confirmations = blockchainHeight - blockHeight - 1 var confirmations = blockchainHeight - blockHeight - 1
var displayAmount = model.data(idx, TransactionHistoryModel.TransactionDisplayAmountRole); var displayAmount = model.data(idx, TransactionHistoryModel.TransactionDisplayAmountRole);
if (confirmations > 1) { if (confirmations > 1) {
list += qsTr("%2 confirmations: %3 (%1)").arg(txid).arg(confirmations).arg(displayAmount) + translationManager.emptyString list.push(qsTr("%2 confirmations: %3 (%1)").arg(txid).arg(confirmations).arg(displayAmount) + translationManager.emptyString)
} else { } else {
list += qsTr("1 confirmation: %2 (%1)").arg(txid).arg(displayAmount) + translationManager.emptyString list.push(qsTr("1 confirmation: %2 (%1)").arg(txid).arg(displayAmount) + translationManager.emptyString)
} }
} }
list += "<br>"
} }
} }
// if there are too many txes, only show the first 3
if (list.length > 3) {
list.length = 3;
list.push("...");
}
if (nTransactions == 0) { if (nTransactions == 0) {
setTrackingLineText(qsTr("No transaction found yet...") + translationManager.emptyString) setTrackingLineText(qsTr("No transaction found yet...") + translationManager.emptyString)
@ -159,7 +137,7 @@ Rectangle {
} }
} }
setTrackingLineText(text + "<br>" + list) setTrackingLineText(text + "<br>" + list.join("<br>"))
} }
Clipboard { id: clipboard } Clipboard { id: clipboard }
@ -186,116 +164,68 @@ Rectangle {
id: addressRow id: addressRow
Label { Label {
id: addressLabel id: addressLabel
text: qsTr("Address") + translationManager.emptyString text: qsTr("Addresses") + translationManager.emptyString
width: mainLayout.labelWidth width: mainLayout.labelWidth
} }
LineEdit { Rectangle {
id: addressLine id: tableRect
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("ReadOnly wallet address displayed here") + translationManager.emptyString;
readOnly: true
width: mainLayout.editWidth
Layout.fillWidth: true Layout.fillWidth: true
onTextChanged: cursorPosition = 0 Layout.preferredHeight: 200
color: "#FFFFFF"
IconButton { Scroll {
imageSource: "../images/copyToClipboard.png" id: flickableScroll
onClicked: { anchors.right: table.right
if (addressLine.text.length > 0) { anchors.top: table.top
console.log(addressLine.text + " copied to clipboard") anchors.bottom: table.bottom
clipboard.setText(addressLine.text) flickable: table
appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3)
}
}
} }
} SubaddressTable {
} id: table
anchors.fill: parent
GridLayout { onContentYChanged: flickableScroll.flickableContentYChanged()
id: paymentIdRow onCurrentItemChanged: {
columns:2 current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex);
Label {
Layout.columnSpan: 2
id: paymentIdLabel
text: qsTr("Payment ID") + translationManager.emptyString
width: mainLayout.labelWidth
}
LineEdit {
id: paymentIdLine
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("16 hexadecimal characters") + translationManager.emptyString;
readOnly: false
onTextChanged: updatePaymentId(paymentIdLine.text)
width: mainLayout.editWidth
Layout.fillWidth: true
IconButton {
imageSource: "../images/copyToClipboard.png"
onClicked: {
if (paymentIdLine.text.length > 0) {
clipboard.setText(paymentIdLine.text)
appWindow.showStatusMessage(qsTr("Payment ID copied to clipboard"),3)
}
} }
} }
} }
StandardButton { RowLayout {
id: generatePaymentId spacing: 20
shadowReleasedColor: "#FF4304" StandardButton {
shadowPressedColor: "#B32D00" shadowReleasedColor: "#FF4304"
releasedColor: "#FF6C3C" shadowPressedColor: "#B32D00"
pressedColor: "#FF4304" releasedColor: "#FF6C3C"
text: qsTr("Generate") + translationManager.emptyString; pressedColor: "#FF4304"
onClicked: updatePaymentId() text: qsTr("Create new address") + translationManager.emptyString;
}
StandardButton {
id: clearPaymentId
enabled: !!paymentIdLine.text
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
text: qsTr("Clear") + translationManager.emptyString;
onClicked: updatePaymentId("")
}
}
ColumnLayout {
id: integratedAddressRow
Label {
id: integratedAddressLabel
text: qsTr("Integrated address") + translationManager.emptyString
width: mainLayout.labelWidth
}
LineEdit {
id: integratedAddressLine
fontSize: mainLayout.lineEditFontSize
placeholderText: qsTr("Generate payment ID for integrated address") + translationManager.emptyString
readOnly: true
width: mainLayout.editWidth
Layout.fillWidth: true
onTextChanged: cursorPosition = 0
IconButton {
imageSource: "../images/copyToClipboard.png"
onClicked: { onClicked: {
if (integratedAddressLine.text.length > 0) { inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
clipboard.setText(integratedAddressLine.text) inputDialog.inputText = qsTr("(Untitled)")
appWindow.showStatusMessage(qsTr("Integrated address copied to clipboard"),3) inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
table.currentIndex = appWindow.currentWallet.numSubaddresses() - 1
} }
inputDialog.onRejectedCallback = null;
inputDialog.open()
}
}
StandardButton {
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
enabled: table.currentIndex > 0
text: qsTr("Rename") + translationManager.emptyString;
onClicked: {
inputDialog.labelText = qsTr("Set the label of the selected address:") + translationManager.emptyString
inputDialog.inputText = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex)
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.setLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex, inputDialog.inputText)
}
inputDialog.onRejectedCallback = null;
inputDialog.open()
} }
} }
} }
} }
@ -331,15 +261,17 @@ Rectangle {
Label { Label {
id: trackingLabel id: trackingLabel
textFormat: Text.RichText textFormat: Text.RichText
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\ text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>" +
Tracking <font size='2'> (</font><a href='#'>help</a><font size='2'>)</font>") qsTr("Tracking") +
+ translationManager.emptyString "<font size='2'> (</font><a href='#'>" +
qsTr("help") +
"</a><font size='2'>)</font>" +
translationManager.emptyString
width: mainLayout.labelWidth width: mainLayout.labelWidth
onLinkActivated: { onLinkActivated: {
trackingHowToUseDialog.title = qsTr("Tracking payments") + translationManager.emptyString; trackingHowToUseDialog.title = qsTr("Tracking payments") + translationManager.emptyString;
trackingHowToUseDialog.text = qsTr( trackingHowToUseDialog.text = qsTr(
"<p><font size='+2'>This is a simple sales tracker:</font></p>" + "<p><font size='+2'>This is a simple sales tracker:</font></p>" +
"<p>Click Generate to create a random payment id for a new customer</p> " +
"<p>Let your customer scan that QR code to make a payment (if that customer has software which " + "<p>Let your customer scan that QR code to make a payment (if that customer has software which " +
"supports QR code scanning).</p>" + "supports QR code scanning).</p>" +
"<p>This page will automatically scan the blockchain and the tx pool " + "<p>This page will automatically scan the blockchain and the tx pool " +
@ -427,11 +359,12 @@ Rectangle {
function onPageCompleted() { function onPageCompleted() {
console.log("Receive page loaded"); console.log("Receive page loaded");
table.model = currentWallet.subaddressModel;
if (appWindow.currentWallet) { if (appWindow.currentWallet) {
if (addressLine.text.length === 0 || addressLine.text !== appWindow.currentWallet.address) { current_address = appWindow.currentWallet.address(appWindow.currentWallet.currentSubaddressAccount, 0)
addressLine.text = appWindow.currentWallet.address appWindow.currentWallet.subaddress.refresh(appWindow.currentWallet.currentSubaddressAccount)
} table.currentIndex = 0
} }
update() update()

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -164,6 +164,32 @@ Rectangle {
} }
} }
} }
StandardButton {
id: changePasswordButton
text: qsTr("Change password") + translationManager.emptyString
shadowReleasedColor: "#FF4304"
shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C"
pressedColor: "#FF4304"
onClicked: {
passwordDialog.onAcceptedCallback = function() {
if(appWindow.walletPassword === passwordDialog.password){
newPasswordDialog.open()
} else {
informationPopup.title = qsTr("Error") + translationManager.emptyString;
informationPopup.text = qsTr("Wrong password");
informationPopup.open()
informationPopup.onCloseCallback = function() {
changePasswordDialog.open()
}
passwordDialog.open()
}
}
passwordDialog.onRejectedCallback = null;
passwordDialog.open()
}
}
} }
RowLayout { RowLayout {
@ -565,6 +591,10 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
text: (typeof currentWallet == "undefined") ? "" : qsTr("Wallet log path: ") + currentWallet.walletLogPath + translationManager.emptyString text: (typeof currentWallet == "undefined") ? "" : qsTr("Wallet log path: ") + currentWallet.walletLogPath + translationManager.emptyString
} }
TextBlock {
Layout.fillWidth: true
text: qsTr("Wallet Name: ") + walletName + translationManager.emptyString
}
TextBlock { TextBlock {
Layout.fillWidth: true Layout.fillWidth: true
text: (typeof currentWallet == "undefined") ? "" : qsTr("Daemon log path: ") + currentWallet.daemonLogPath + translationManager.emptyString text: (typeof currentWallet == "undefined") ? "" : qsTr("Daemon log path: ") + currentWallet.daemonLogPath + translationManager.emptyString

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -383,9 +383,12 @@ Rectangle {
Text { Text {
id: verifyAddressLabel id: verifyAddressLabel
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: %1px;}</style>\ text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: " + (14 * scaleRatio) + "px;}</style>" +
Signing address <font size='%2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='%3'> )</font>").arg(14 * scaleRatio).arg(2 * scaleRatio).arg(2 * scaleRatio) qsTr("Signing address") +
+ translationManager.emptyString "<font size='" + (2 * scaleRatio) + "'> ( " +
qsTr("Paste in or select from <a href='#'>Address book</a>") +
" )</font>" +
translationManager.emptyString
wrapMode: Text.Wrap wrapMode: Text.Wrap
font.pixelSize: 14 * scaleRatio font.pixelSize: 14 * scaleRatio
Layout.fillWidth: true Layout.fillWidth: true

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -41,7 +41,10 @@ Rectangle {
signal sweepUnmixableClicked() signal sweepUnmixableClicked()
color: "#F0EEEE" color: "#F0EEEE"
property string startLinkText: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style><font size='2'> (</font><a href='#'>Start daemon</a><font size='2'>)</font>") + translationManager.emptyString property string startLinkText: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style><font size='2'> (</font><a href='#'>" +
qsTr("Start daemon") +
"</a><font size='2'>)</font>" +
translationManager.emptyString
property bool showAdvanced: false property bool showAdvanced: false
function scaleValueToMixinCount(scaleValue) { function scaleValueToMixinCount(scaleValue) {
@ -184,15 +187,6 @@ Rectangle {
// For translations to work, the strings need to be listed in // For translations to work, the strings need to be listed in
// the file components/StandardDropdown.qml too. // the file components/StandardDropdown.qml too.
// Priorities before v5
ListModel {
id: priorityModel
ListElement { column1: qsTr("Low (x1 fee)") ; column2: ""; priority: PendingTransaction.Priority_Low }
ListElement { column1: qsTr("Medium (x20 fee)") ; column2: ""; priority: PendingTransaction.Priority_Medium }
ListElement { column1: qsTr("High (x166 fee)") ; column2: ""; priority: PendingTransaction.Priority_High }
}
// Priorites after v5 // Priorites after v5
ListModel { ListModel {
id: priorityModelV5 id: priorityModelV5
@ -222,10 +216,12 @@ Rectangle {
Label { Label {
id: addressLabel id: addressLabel
textFormat: Text.RichText textFormat: Text.RichText
text: qsTr("<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>\ text: "<style type='text/css'>a {text-decoration: none; color: #FF6C3C; font-size: 14px;}</style>" +
Address <font size='2'> ( Paste in or select from </font> <a href='#'>Address book</a><font size='2'> )</font>") qsTr("Address") +
+ translationManager.emptyString "<font size='2'> ( " +
qsTr("Paste in or select from <a href='#'>Address book</a>") +
" )</font>" +
translationManager.emptyString
onLinkActivated: appWindow.showPageRequest("AddressBook") onLinkActivated: appWindow.showPageRequest("AddressBook")
Layout.fillWidth: true Layout.fillWidth: true
} }
@ -335,7 +331,7 @@ Rectangle {
enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet) enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
onClicked: { onClicked: {
console.log("Transfer: paymentClicked") console.log("Transfer: paymentClicked")
var priority = priorityModel.get(priorityDropdown.currentIndex).priority var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
console.log("priority: " + priority) console.log("priority: " + priority)
console.log("amount: " + amountLine.text) console.log("amount: " + amountLine.text)
addressLine.text = addressLine.text.trim() addressLine.text = addressLine.text.trim()
@ -478,7 +474,7 @@ Rectangle {
enabled: pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet) enabled: pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet)
onClicked: { onClicked: {
console.log("Transfer: saveTx Clicked") console.log("Transfer: saveTx Clicked")
var priority = priorityModel.get(priorityDropdown.currentIndex).priority var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority
console.log("priority: " + priority) console.log("priority: " + priority)
console.log("amount: " + amountLine.text) console.log("amount: " + amountLine.text)
addressLine.text = addressLine.text.trim() addressLine.text = addressLine.text.trim()

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //
@ -72,6 +72,10 @@ Rectangle {
if ((signature.length - 9) % 132 != 0) if ((signature.length - 9) % 132 != 0)
return false; return false;
return check256(signature, signature.length); return check256(signature, signature.length);
} else if (signature.startsWith("SpendProofV")) {
if ((signature.length - 12) % 88 != 0)
return false;
return check256(signature, signature.length);
} }
return false; return false;
} }
@ -90,7 +94,8 @@ Rectangle {
property int lineEditFontSize: 12 property int lineEditFontSize: 12
Text { Text {
text: qsTr("Generate a proof of your incoming/outgoing payment by supplying the transaction ID, the recipient address and an optional message:") + translationManager.emptyString text: qsTr("Generate a proof of your incoming/outgoing payment by supplying the transaction ID, the recipient address and an optional message. \n" +
"For the case of outgoing payments, you can get a 'Spend Proof' that proves the authorship of a transaction. In this case, you don't need to specify the recipient address.") + translationManager.emptyString
wrapMode: Text.Wrap wrapMode: Text.Wrap
Layout.fillWidth: true; Layout.fillWidth: true;
} }
@ -183,7 +188,7 @@ Rectangle {
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
pressedColor: "#FF4304" pressedColor: "#FF4304"
enabled: checkTxID(getProofTxIdLine.text) && checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet) enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet))
onClicked: { onClicked: {
console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text);
root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text)
@ -201,7 +206,8 @@ Rectangle {
} }
Text { Text {
text: qsTr("Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature:") + translationManager.emptyString text: qsTr("Verify that funds were paid to an address by supplying the transaction ID, the recipient address, the message used for signing and the signature.\n" +
"For the case with Spend Proof, you don't need to specify the recipient address.") + translationManager.emptyString
wrapMode: Text.Wrap wrapMode: Text.Wrap
Layout.fillWidth: true; Layout.fillWidth: true;
} }
@ -322,7 +328,7 @@ Rectangle {
shadowPressedColor: "#B32D00" shadowPressedColor: "#B32D00"
releasedColor: "#FF6C3C" releasedColor: "#FF6C3C"
pressedColor: "#FF4304" pressedColor: "#FF4304"
enabled: checkTxID(checkProofTxIdLine.text) && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet) && checkSignature(checkProofSignatureLine.text) enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.startsWith("SpendProofV") && checkProofAddressLine.text.length == 0) || (!checkProofSignatureLine.text.startsWith("SpendProofV") && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet)))
onClicked: { onClicked: {
console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text); console.log("checkProof: Check clicked: txid " + checkProofTxIdLine.text + ", address " + checkProofAddressLine.text + ", message " + checkProofMessageLine.text + ", signature " + checkProofSignatureLine.text);
root.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text) root.checkProofClicked(checkProofTxIdLine.text, checkProofAddressLine.text, checkProofMessageLine.text, checkProofSignatureLine.text)

View File

@ -51,6 +51,7 @@
<file>tabs/TweetsModel.qml</file> <file>tabs/TweetsModel.qml</file>
<file>components/Scroll.qml</file> <file>components/Scroll.qml</file>
<file>components/AddressBookTable.qml</file> <file>components/AddressBookTable.qml</file>
<file>components/SubaddressTable.qml</file>
<file>images/deleteIcon.png</file> <file>images/deleteIcon.png</file>
<file>images/moneroIcon.png</file> <file>images/moneroIcon.png</file>
<file>components/StandardDropdown.qml</file> <file>components/StandardDropdown.qml</file>
@ -118,11 +119,15 @@
<file>lang/flags/spain.png</file> <file>lang/flags/spain.png</file>
<file>lang/flags/sweden.png</file> <file>lang/flags/sweden.png</file>
<file>lang/flags/taiwan.png</file> <file>lang/flags/taiwan.png</file>
<file>lang/flags/denmark.png</file>
<file>lang/flags/uk.png</file> <file>lang/flags/uk.png</file>
<file>lang/flags/usa.png</file> <file>lang/flags/usa.png</file>
<file>lang/flags/israel.png</file> <file>lang/flags/israel.png</file>
<file>lang/flags/south_korea.png</file> <file>lang/flags/south_korea.png</file>
<file>lang/flags/romania.png</file> <file>lang/flags/romania.png</file>
<file>lang/flags/czech.png</file>
<file>lang/flags/slovakia.png</file>
<file>lang/flags/egypt.png</file>
<file>wizard/WizardManageWalletUI.qml</file> <file>wizard/WizardManageWalletUI.qml</file>
<file>wizard/WizardRecoveryWallet.qml</file> <file>wizard/WizardRecoveryWallet.qml</file>
<file>wizard/WizardMemoTextInput.qml</file> <file>wizard/WizardMemoTextInput.qml</file>
@ -131,6 +136,8 @@
<file>pages/TxKey.qml</file> <file>pages/TxKey.qml</file>
<file>components/IconButton.qml</file> <file>components/IconButton.qml</file>
<file>components/PasswordDialog.qml</file> <file>components/PasswordDialog.qml</file>
<file>components/NewPasswordDialog.qml</file>
<file>components/InputDialog.qml</file>
<file>components/ProcessingSplash.qml</file> <file>components/ProcessingSplash.qml</file>
<file>components/ProgressBar.qml</file> <file>components/ProgressBar.qml</file>
<file>components/StandardDialog.qml</file> <file>components/StandardDialog.qml</file>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2017, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -50,6 +50,16 @@ quint64 PendingTransaction::txCount() const
return m_pimpl->txCount(); return m_pimpl->txCount();
} }
QList<QVariant> PendingTransaction::subaddrIndices() const
{
std::vector<std::set<uint32_t>> subaddrIndices = m_pimpl->subaddrIndices();
QList<QVariant> result;
for (const auto& x : subaddrIndices)
for (uint32_t i : x)
result.push_back(i);
return result;
}
void PendingTransaction::setFilename(const QString &fileName) void PendingTransaction::setFilename(const QString &fileName)
{ {
m_fileName = fileName; m_fileName = fileName;

View File

@ -2,6 +2,8 @@
#define PENDINGTRANSACTION_H #define PENDINGTRANSACTION_H
#include <QObject> #include <QObject>
#include <QList>
#include <QVariant>
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
@ -19,6 +21,7 @@ class PendingTransaction : public QObject
Q_PROPERTY(quint64 fee READ fee) Q_PROPERTY(quint64 fee READ fee)
Q_PROPERTY(QStringList txid READ txid) Q_PROPERTY(QStringList txid READ txid)
Q_PROPERTY(quint64 txCount READ txCount) Q_PROPERTY(quint64 txCount READ txCount)
Q_PROPERTY(QList<QVariant> subaddrIndices READ subaddrIndices)
public: public:
enum Status { enum Status {
@ -44,6 +47,7 @@ public:
quint64 fee() const; quint64 fee() const;
QStringList txid() const; QStringList txid() const;
quint64 txCount() const; quint64 txCount() const;
QList<QVariant> subaddrIndices() const;
Q_INVOKABLE void setFilename(const QString &fileName); Q_INVOKABLE void setFilename(const QString &fileName);
private: private:

View File

@ -0,0 +1,84 @@
// Copyright (c) 2018, 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.
#include "Subaddress.h"
#include <QDebug>
Subaddress::Subaddress(Monero::Subaddress *subaddressImpl, QObject *parent)
: QObject(parent), m_subaddressImpl(subaddressImpl)
{
qDebug(__FUNCTION__);
getAll();
}
QList<Monero::SubaddressRow*> Subaddress::getAll(bool update) const
{
qDebug(__FUNCTION__);
emit refreshStarted();
if(update)
m_rows.clear();
if (m_rows.empty()){
for (auto &row: m_subaddressImpl->getAll()) {
m_rows.append(row);
}
}
emit refreshFinished();
return m_rows;
}
Monero::SubaddressRow * Subaddress::getRow(int index) const
{
return m_rows.at(index);
}
void Subaddress::addRow(quint32 accountIndex, const QString &label) const
{
m_subaddressImpl->addRow(accountIndex, label.toStdString());
getAll(true);
}
void Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) const
{
m_subaddressImpl->setLabel(accountIndex, addressIndex, label.toStdString());
getAll(true);
}
void Subaddress::refresh(quint32 accountIndex) const
{
m_subaddressImpl->refresh(accountIndex);
getAll(true);
}
quint64 Subaddress::count() const
{
return m_rows.size();
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 2018, 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.
#ifndef SUBADDRESS_H
#define SUBADDRESS_H
#include <wallet/api/wallet2_api.h>
#include <QObject>
#include <QList>
#include <QDateTime>
class Subaddress : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE QList<Monero::SubaddressRow*> getAll(bool update = false) const;
Q_INVOKABLE Monero::SubaddressRow * getRow(int index) const;
Q_INVOKABLE void addRow(quint32 accountIndex, const QString &label) const;
Q_INVOKABLE void setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) const;
Q_INVOKABLE void refresh(quint32 accountIndex) const;
quint64 count() const;
signals:
void refreshStarted() const;
void refreshFinished() const;
public slots:
private:
explicit Subaddress(Monero::Subaddress * subaddressImpl, QObject *parent);
friend class Wallet;
Monero::Subaddress * m_subaddressImpl;
mutable QList<Monero::SubaddressRow*> m_rows;
};
#endif // SUBADDRESS_H

View File

@ -22,7 +22,7 @@ TransactionInfo *TransactionHistory::transaction(int index)
// return nullptr; // return nullptr;
//} //}
QList<TransactionInfo *> TransactionHistory::getAll() const QList<TransactionInfo *> TransactionHistory::getAll(quint32 accountIndex) const
{ {
// XXX this invalidates previously saved history that might be used by model // XXX this invalidates previously saved history that might be used by model
emit refreshStarted(); emit refreshStarted();
@ -37,6 +37,10 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
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);
if (ti->subaddrAccount() != accountIndex) {
delete ti;
continue;
}
m_tinfo.append(ti); m_tinfo.append(ti);
// looking for transactions timestamp scope // looking for transactions timestamp scope
if (ti->timestamp() >= lastDateTime) { if (ti->timestamp() >= lastDateTime) {
@ -69,12 +73,12 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
return m_tinfo; return m_tinfo;
} }
void TransactionHistory::refresh() void TransactionHistory::refresh(quint32 accountIndex)
{ {
// rebuilding transaction list in wallet_api; // rebuilding transaction list in wallet_api;
m_pimpl->refresh(); m_pimpl->refresh();
// copying list here and keep track on every item to avoid memleaks // copying list here and keep track on every item to avoid memleaks
getAll(); getAll(accountIndex);
} }
quint64 TransactionHistory::count() const quint64 TransactionHistory::count() const

View File

@ -23,8 +23,8 @@ class TransactionHistory : public QObject
public: public:
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(quint32 accountIndex) const;
Q_INVOKABLE void refresh(); Q_INVOKABLE void refresh(quint32 accountIndex);
quint64 count() const; quint64 count() const;
QDateTime firstDateTime() const; QDateTime firstDateTime() const;
QDateTime lastDateTime() const; QDateTime lastDateTime() const;

View File

@ -48,6 +48,24 @@ quint64 TransactionInfo::blockHeight() const
return m_pimpl->blockHeight(); return m_pimpl->blockHeight();
} }
QSet<quint32> TransactionInfo::subaddrIndex() const
{
QSet<quint32> result;
for (uint32_t i : m_pimpl->subaddrIndex())
result.insert(i);
return result;
}
quint32 TransactionInfo::subaddrAccount() const
{
return m_pimpl->subaddrAccount();
}
QString TransactionInfo::label() const
{
return QString::fromStdString(m_pimpl->label());
}
quint64 TransactionInfo::confirmations() const quint64 TransactionInfo::confirmations() const
{ {
return m_pimpl->confirmations(); return m_pimpl->confirmations();

View File

@ -4,6 +4,7 @@
#include <wallet/api/wallet2_api.h> #include <wallet/api/wallet2_api.h>
#include <QObject> #include <QObject>
#include <QDateTime> #include <QDateTime>
#include <QSet>
class Transfer; class Transfer;
@ -18,6 +19,9 @@ class TransactionInfo : public QObject
Q_PROPERTY(QString displayAmount READ displayAmount) Q_PROPERTY(QString displayAmount READ displayAmount)
Q_PROPERTY(QString fee READ fee) Q_PROPERTY(QString fee READ fee)
Q_PROPERTY(quint64 blockHeight READ blockHeight) Q_PROPERTY(quint64 blockHeight READ blockHeight)
Q_PROPERTY(QSet<quint32> subaddrIndex READ subaddrIndex)
Q_PROPERTY(quint32 subaddrAccount READ subaddrAccount)
Q_PROPERTY(QString label READ label)
Q_PROPERTY(quint64 confirmations READ confirmations) Q_PROPERTY(quint64 confirmations READ confirmations)
Q_PROPERTY(quint64 unlockTime READ unlockTime) Q_PROPERTY(quint64 unlockTime READ unlockTime)
Q_PROPERTY(QString hash READ hash) Q_PROPERTY(QString hash READ hash)
@ -44,6 +48,9 @@ public:
QString displayAmount() const; QString displayAmount() const;
QString fee() const; QString fee() const;
quint64 blockHeight() const; quint64 blockHeight() const;
QSet<quint32> subaddrIndex() const;
quint32 subaddrAccount() const;
QString label() const;
quint64 confirmations() const; quint64 confirmations() const;
quint64 unlockTime() const; quint64 unlockTime() const;
//! transaction_id //! transaction_id

View File

@ -3,9 +3,11 @@
#include "UnsignedTransaction.h" #include "UnsignedTransaction.h"
#include "TransactionHistory.h" #include "TransactionHistory.h"
#include "AddressBook.h" #include "AddressBook.h"
#include "Subaddress.h"
#include "model/TransactionHistoryModel.h" #include "model/TransactionHistoryModel.h"
#include "model/TransactionHistorySortFilterModel.h" #include "model/TransactionHistorySortFilterModel.h"
#include "model/AddressBookModel.h" #include "model/AddressBookModel.h"
#include "model/SubaddressModel.h"
#include "wallet/api/wallet2_api.h" #include "wallet/api/wallet2_api.h"
#include <QFile> #include <QFile>
@ -155,9 +157,9 @@ bool Wallet::setPassword(const QString &password)
return m_walletImpl->setPassword(password.toStdString()); return m_walletImpl->setPassword(password.toStdString());
} }
QString Wallet::address() const QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const
{ {
return QString::fromStdString(m_walletImpl->address()); return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex));
} }
QString Wallet::path() const QString Wallet::path() const
@ -241,14 +243,63 @@ bool Wallet::viewOnly() const
return m_walletImpl->watchOnly(); return m_walletImpl->watchOnly();
} }
quint64 Wallet::balance() const quint64 Wallet::balance(quint32 accountIndex) const
{ {
return m_walletImpl->balance(); return m_walletImpl->balance(accountIndex);
} }
quint64 Wallet::unlockedBalance() const quint64 Wallet::balanceAll() const
{ {
return m_walletImpl->unlockedBalance(); return m_walletImpl->balanceAll();
}
quint64 Wallet::unlockedBalance(quint32 accountIndex) const
{
return m_walletImpl->unlockedBalance(accountIndex);
}
quint64 Wallet::unlockedBalanceAll() const
{
return m_walletImpl->unlockedBalanceAll();
}
quint32 Wallet::currentSubaddressAccount() const
{
return m_currentSubaddressAccount;
}
void Wallet::switchSubaddressAccount(quint32 accountIndex)
{
if (accountIndex < numSubaddressAccounts())
{
m_currentSubaddressAccount = accountIndex;
m_subaddress->refresh(m_currentSubaddressAccount);
m_history->refresh(m_currentSubaddressAccount);
}
}
void Wallet::addSubaddressAccount(const QString& label)
{
m_walletImpl->addSubaddressAccount(label.toStdString());
switchSubaddressAccount(numSubaddressAccounts() - 1);
}
quint32 Wallet::numSubaddressAccounts() const
{
return m_walletImpl->numSubaddressAccounts();
}
quint32 Wallet::numSubaddresses(quint32 accountIndex) const
{
return m_walletImpl->numSubaddresses(accountIndex);
}
void Wallet::addSubaddress(const QString& label)
{
m_walletImpl->addSubaddress(currentSubaddressAccount(), label.toStdString());
}
QString Wallet::getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const
{
return QString::fromStdString(m_walletImpl->getSubaddressLabel(accountIndex, addressIndex));
}
void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label)
{
m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString());
} }
quint64 Wallet::blockChainHeight() const quint64 Wallet::blockChainHeight() const
@ -288,7 +339,8 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
bool Wallet::refresh() bool Wallet::refresh()
{ {
bool result = m_walletImpl->refresh(); bool result = m_walletImpl->refresh();
m_history->refresh(); m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
if (result) if (result)
emit updated(); emit updated();
return result; return result;
@ -324,9 +376,10 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
quint64 amount, quint32 mixin_count, quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority) PendingTransaction::Priority priority)
{ {
std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction( Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count, dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority)); static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl,0); PendingTransaction * result = new PendingTransaction(ptImpl,0);
return result; return result;
} }
@ -351,9 +404,10 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id, PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
quint32 mixin_count, PendingTransaction::Priority priority) quint32 mixin_count, PendingTransaction::Priority priority)
{ {
std::set<uint32_t> subaddr_indices;
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction( Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count, dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
static_cast<Monero::PendingTransaction::Priority>(priority)); static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
PendingTransaction * result = new PendingTransaction(ptImpl, this); PendingTransaction * result = new PendingTransaction(ptImpl, this);
return result; return result;
} }
@ -458,6 +512,18 @@ AddressBookModel *Wallet::addressBookModel() const
return m_addressBookModel; return m_addressBookModel;
} }
Subaddress *Wallet::subaddress()
{
return m_subaddress;
}
SubaddressModel *Wallet::subaddressModel()
{
if (!m_subaddressModel) {
m_subaddressModel = new SubaddressModel(this, m_subaddress);
}
return m_subaddressModel;
}
QString Wallet::generatePaymentId() const QString Wallet::generatePaymentId() const
{ {
@ -523,6 +589,22 @@ QString Wallet::checkTxProof(const QString &txid, const QString &address, const
return QString::fromStdString(result); return QString::fromStdString(result);
} }
Q_INVOKABLE QString Wallet::getSpendProof(const QString &txid, const QString &message) const
{
std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString());
if (result.empty())
result = "error|" + m_walletImpl->errorString();
return QString::fromStdString(result);
}
Q_INVOKABLE QString Wallet::checkSpendProof(const QString &txid, const QString &message, const QString &signature) const
{
bool good;
bool success = m_walletImpl->checkSpendProof(txid.toStdString(), message.toStdString(), signature.toStdString(), good);
std::string result = std::string(success ? "true" : "false") + "|" + std::string(!success ? m_walletImpl->errorString() : good ? "true" : "false");
return QString::fromStdString(result);
}
QString Wallet::signMessage(const QString &message, bool filename) const QString Wallet::signMessage(const QString &message, bool filename) const
{ {
if (filename) { if (filename) {
@ -652,14 +734,18 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_historyModel(nullptr) , m_historyModel(nullptr)
, m_addressBook(nullptr) , m_addressBook(nullptr)
, m_addressBookModel(nullptr) , m_addressBookModel(nullptr)
, m_subaddress(nullptr)
, m_subaddressModel(nullptr)
, m_daemonBlockChainHeight(0) , m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS) , m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
, m_daemonBlockChainTargetHeight(0) , m_daemonBlockChainTargetHeight(0)
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS) , m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS) , m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
, m_currentSubaddressAccount(0)
{ {
m_history = new TransactionHistory(m_walletImpl->history(), this); m_history = new TransactionHistory(m_walletImpl->history(), this);
m_addressBook = new AddressBook(m_walletImpl->addressBook(), this); m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
m_subaddress = new Subaddress(m_walletImpl->subaddress(), this);
m_walletImpl->setListener(new WalletListenerImpl(this)); m_walletImpl->setListener(new WalletListenerImpl(this));
m_connectionStatus = Wallet::ConnectionStatus_Disconnected; m_connectionStatus = Wallet::ConnectionStatus_Disconnected;
// start cache timers // start cache timers
@ -680,6 +766,10 @@ Wallet::~Wallet()
delete m_history; delete m_history;
m_history = NULL; m_history = NULL;
delete m_addressBook;
m_addressBook = NULL;
delete m_subaddress;
m_subaddress = NULL;
//Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl); //Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
if(status() == Status_Critical) if(status() == Status_Critical)
qDebug("Not storing wallet cache"); qDebug("Not storing wallet cache");

View File

@ -20,6 +20,8 @@ class TransactionHistoryModel;
class TransactionHistorySortFilterModel; class TransactionHistorySortFilterModel;
class AddressBook; class AddressBook;
class AddressBookModel; class AddressBookModel;
class Subaddress;
class SubaddressModel;
class Wallet : public QObject class Wallet : public QObject
{ {
@ -29,17 +31,17 @@ class Wallet : public QObject
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
Q_PROPERTY(bool testnet READ testnet) Q_PROPERTY(bool testnet READ testnet)
// Q_PROPERTY(ConnectionStatus connected READ connected) // Q_PROPERTY(ConnectionStatus connected READ connected)
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount)
Q_PROPERTY(bool synchronized READ synchronized) 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(quint64 balance READ balance)
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) Q_PROPERTY(TransactionHistorySortFilterModel * historyModel READ historyModel NOTIFY historyModelChanged)
Q_PROPERTY(QString path READ path) Q_PROPERTY(QString path READ path)
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel) Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
Q_PROPERTY(AddressBook * addressBook READ addressBook) Q_PROPERTY(AddressBook * addressBook READ addressBook)
Q_PROPERTY(SubaddressModel * subaddressModel READ subaddressModel)
Q_PROPERTY(Subaddress * subaddress READ subaddress)
Q_PROPERTY(bool viewOnly READ viewOnly) Q_PROPERTY(bool viewOnly READ viewOnly)
Q_PROPERTY(QString secretViewKey READ getSecretViewKey) Q_PROPERTY(QString secretViewKey READ getSecretViewKey)
Q_PROPERTY(QString publicViewKey READ getPublicViewKey) Q_PROPERTY(QString publicViewKey READ getPublicViewKey)
@ -98,7 +100,7 @@ public:
Q_INVOKABLE bool setPassword(const QString &password); Q_INVOKABLE bool setPassword(const QString &password);
//! returns wallet's public address //! returns wallet's public address
QString address() const; Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
//! returns wallet file's path //! returns wallet file's path
QString path() const; QString path() const;
@ -126,10 +128,22 @@ public:
Q_INVOKABLE void setTrustedDaemon(bool arg); Q_INVOKABLE void setTrustedDaemon(bool arg);
//! returns balance //! returns balance
Q_INVOKABLE quint64 balance() const; Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
Q_INVOKABLE quint64 balanceAll() const;
//! returns unlocked balance //! returns unlocked balance
Q_INVOKABLE quint64 unlockedBalance() const; Q_INVOKABLE quint64 unlockedBalance(quint32 accountIndex) const;
Q_INVOKABLE quint64 unlockedBalanceAll() const;
//! account/address management
quint32 currentSubaddressAccount() const;
Q_INVOKABLE void switchSubaddressAccount(quint32 accountIndex);
Q_INVOKABLE void addSubaddressAccount(const QString& label);
Q_INVOKABLE quint32 numSubaddressAccounts() const;
Q_INVOKABLE quint32 numSubaddresses(quint32 accountIndex) const;
Q_INVOKABLE void addSubaddress(const QString& label);
Q_INVOKABLE QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
Q_INVOKABLE void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
//! returns if view only wallet //! returns if view only wallet
Q_INVOKABLE bool viewOnly() const; Q_INVOKABLE bool viewOnly() const;
@ -209,6 +223,12 @@ public:
//! returns adress book model //! returns adress book model
AddressBookModel *addressBookModel() const; AddressBookModel *addressBookModel() const;
//! returns subaddress
Subaddress *subaddress();
//! returns subadress model
SubaddressModel *subaddressModel();
//! generate payment id //! generate payment id
Q_INVOKABLE QString generatePaymentId() const; Q_INVOKABLE QString generatePaymentId() const;
@ -235,6 +255,8 @@ public:
Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address); Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const; Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const;
Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const;
Q_INVOKABLE QString checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
// Rescan spent outputs // Rescan spent outputs
Q_INVOKABLE bool rescanSpent(); Q_INVOKABLE bool rescanSpent();
@ -300,8 +322,11 @@ private:
int m_connectionStatusTtl; int m_connectionStatusTtl;
mutable QTime m_connectionStatusTime; mutable QTime m_connectionStatusTime;
mutable bool m_initialized; mutable bool m_initialized;
uint32_t m_currentSubaddressAccount;
AddressBook * m_addressBook; AddressBook * m_addressBook;
mutable AddressBookModel * m_addressBookModel; mutable AddressBookModel * m_addressBookModel;
Subaddress * m_subaddress;
mutable SubaddressModel * m_subaddressModel;
QMutex m_connectionStatusMutex; QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning; bool m_connectionStatusRunning;
QString m_daemonUsername; QString m_daemonUsername;

View File

@ -49,7 +49,7 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password,
__PRETTY_FUNCTION__, qPrintable(path), testnet); __PRETTY_FUNCTION__, qPrintable(path), testnet);
Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet); Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet);
qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address().c_str(), w->status()); qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address(0, 0).c_str(), w->status());
m_currentWallet = new Wallet(w); m_currentWallet = new Wallet(w);
// move wallet to the GUI thread. Otherwise it wont be emitting signals // move wallet to the GUI thread. Otherwise it wont be emitting signals
@ -110,7 +110,7 @@ QString WalletManager::closeWallet()
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
QString result; QString result;
if (m_currentWallet) { if (m_currentWallet) {
result = m_currentWallet->address(); result = m_currentWallet->address(0, 0);
delete m_currentWallet; delete m_currentWallet;
} else { } else {
qCritical() << "Trying to close non existing wallet " << m_currentWallet; qCritical() << "Trying to close non existing wallet " << m_currentWallet;
@ -304,6 +304,7 @@ QUrl WalletManager::localPathToUrl(const QString &path) const
return QUrl::fromLocalFile(path); return QUrl::fromLocalFile(path);
} }
#ifndef DISABLE_PASS_STRENGTH_METER
double WalletManager::getPasswordStrength(const QString &password) const double WalletManager::getPasswordStrength(const QString &password) const
{ {
static const char *local_dict[] = { static const char *local_dict[] = {
@ -318,6 +319,7 @@ double WalletManager::getPasswordStrength(const QString &password) const
ZxcvbnUnInit(); ZxcvbnUnInit();
return e; return e;
} }
#endif
bool WalletManager::saveQrCode(const QString &code, const QString &path) const bool WalletManager::saveQrCode(const QString &code, const QString &path) const
{ {

View File

@ -128,7 +128,9 @@ public:
Q_INVOKABLE qint64 addi(qint64 x, qint64 y) const { return x + y; } Q_INVOKABLE qint64 addi(qint64 x, qint64 y) const { return x + y; }
Q_INVOKABLE qint64 subi(qint64 x, qint64 y) const { return x - y; } Q_INVOKABLE qint64 subi(qint64 x, qint64 y) const { return x - y; }
#ifndef DISABLE_PASS_STRENGTH_METER
Q_INVOKABLE double getPasswordStrength(const QString &password) const; Q_INVOKABLE double getPasswordStrength(const QString &password) const;
#endif
Q_INVOKABLE QString resolveOpenAlias(const QString &address) const; Q_INVOKABLE QString resolveOpenAlias(const QString &address) const;
Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error); Q_INVOKABLE bool parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error);

View File

@ -0,0 +1,89 @@
// Copyright (c) 2018, 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.
#include "SubaddressModel.h"
#include "Subaddress.h"
#include <QDebug>
#include <QHash>
#include <wallet/api/wallet2_api.h>
SubaddressModel::SubaddressModel(QObject *parent, Subaddress *subaddress)
: QAbstractListModel(parent), m_subaddress(subaddress)
{
qDebug(__FUNCTION__);
connect(m_subaddress,SIGNAL(refreshStarted()),this,SLOT(startReset()));
connect(m_subaddress,SIGNAL(refreshFinished()),this,SLOT(endReset()));
}
void SubaddressModel::startReset(){
qDebug(__FUNCTION__);
beginResetModel();
}
void SubaddressModel::endReset(){
qDebug(__FUNCTION__);
endResetModel();
}
int SubaddressModel::rowCount(const QModelIndex &parent) const
{
return m_subaddress->count();
}
QVariant SubaddressModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || (unsigned)index.row() >= m_subaddress->count())
return {};
Monero::SubaddressRow * sr = m_subaddress->getRow(index.row());
if (!sr)
return {};
QVariant result = "";
switch (role) {
case SubaddressAddressRole:
result = QString::fromStdString(sr->getAddress());
break;
case SubaddressLabelRole:
result = index.row() == 0 ? tr("Primary address") : QString::fromStdString(sr->getLabel());
break;
}
return result;
}
QHash<int, QByteArray> SubaddressModel::roleNames() const
{
static QHash<int, QByteArray> roleNames;
if (roleNames.empty())
{
roleNames.insert(SubaddressAddressRole, "address");
roleNames.insert(SubaddressLabelRole, "label");
}
return roleNames;
}

View File

@ -0,0 +1,62 @@
// Copyright (c) 2018, 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.
#ifndef SUBADDRESSMODEL_H
#define SUBADDRESSMODEL_H
#include <QAbstractListModel>
class Subaddress;
class SubaddressModel : public QAbstractListModel
{
Q_OBJECT
public:
enum SubaddressRowRole {
SubaddressRole = Qt::UserRole + 1, // for the SubaddressRow object;
SubaddressAddressRole,
SubaddressLabelRole,
};
Q_ENUM(SubaddressRowRole)
SubaddressModel(QObject *parent, Subaddress *subaddress);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
public slots:
void startReset();
void endReset();
private:
Subaddress *m_subaddress;
};
#endif // SUBADDRESSMODEL_H

View File

@ -83,6 +83,25 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
} }
break; break;
case TransactionSubaddrIndexRole:
{
QString str = QString{""};
bool first = true;
for (quint32 i : tInfo->subaddrIndex()) {
if (!first)
str += QString{","};
first = false;
str += QString::number(i);
}
result = str;
}
break;
case TransactionSubaddrAccountRole:
result = tInfo->subaddrAccount();
break;
case TransactionLabelRole:
result = tInfo->subaddrIndex().size() == 1 && *tInfo->subaddrIndex().begin() == 0 ? tr("Primary address") : tInfo->label();
break;
case TransactionConfirmationsRole: case TransactionConfirmationsRole:
result = tInfo->confirmations(); result = tInfo->confirmations();
break; break;
@ -133,6 +152,9 @@ QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
roleNames.insert(TransactionAtomicAmountRole, "atomicAmount"); roleNames.insert(TransactionAtomicAmountRole, "atomicAmount");
roleNames.insert(TransactionFeeRole, "fee"); roleNames.insert(TransactionFeeRole, "fee");
roleNames.insert(TransactionBlockHeightRole, "blockHeight"); roleNames.insert(TransactionBlockHeightRole, "blockHeight");
roleNames.insert(TransactionSubaddrIndexRole, "subaddrIndex");
roleNames.insert(TransactionSubaddrAccountRole, "subaddrAccount");
roleNames.insert(TransactionLabelRole, "label");
roleNames.insert(TransactionConfirmationsRole, "confirmations"); roleNames.insert(TransactionConfirmationsRole, "confirmations");
roleNames.insert(TransactionConfirmationsRequiredRole, "confirmationsRequired"); roleNames.insert(TransactionConfirmationsRequiredRole, "confirmationsRequired");
roleNames.insert(TransactionHashRole, "hash"); roleNames.insert(TransactionHashRole, "hash");

View File

@ -25,6 +25,9 @@ public:
TransactionDisplayAmountRole, TransactionDisplayAmountRole,
TransactionFeeRole, TransactionFeeRole,
TransactionBlockHeightRole, TransactionBlockHeightRole,
TransactionSubaddrIndexRole,
TransactionSubaddrAccountRole,
TransactionLabelRole,
TransactionConfirmationsRole, TransactionConfirmationsRole,
TransactionConfirmationsRequiredRole, TransactionConfirmationsRequiredRole,
TransactionHashRole, TransactionHashRole,

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

View File

@ -1,4 +1,4 @@
// Copyright (c) 2014-2015, The Monero Project // Copyright (c) 2014-2018, The Monero Project
// //
// All rights reserved. // All rights reserved.
// //

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More