From 9943ceaf0ed22d14bfe2450823b09619c4cf2b78 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 17:52:30 +0100 Subject: [PATCH 001/126] Added 2 image resources --- images/card-background.png | Bin 0 -> 31270 bytes images/right.png | Bin 0 -> 122 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/card-background.png create mode 100644 images/right.png diff --git a/images/card-background.png b/images/card-background.png new file mode 100644 index 0000000000000000000000000000000000000000..82b7c79f450dd6a59e3d1ddd39e7ae377f3465b6 GIT binary patch literal 31270 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 literal 0 HcmV?d00001 diff --git a/images/right.png b/images/right.png new file mode 100644 index 0000000000000000000000000000000000000000..d465fe5c8c441c8c3c86d940f6605e0c3694cb23 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^96-#+!3HFS!eXZZDaPU;cPEB*=VV?2IVPSijv*3~ z$v^)8->)q2+wcLCf~Uei)+2^Ht{60^uy0hdSDT}ET($AK`UL@Y~&_ U$2!a0AE=+f)78&qol`;+09PO+SO5S3 literal 0 HcmV?d00001 From d03f94da4652f12ded4796747a479fcd1c5750b4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 17:55:13 +0100 Subject: [PATCH 002/126] Increasing left panel width to 300 --- LeftPanel.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index 79206fb4..171646ff 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -72,8 +72,8 @@ Rectangle { menuColumn.previousButton.checked = true } - width: (isMobile)? appWindow.width : 260 - color: "#FFFFFF" + width: (isMobile)? appWindow.width : 300 + color: "black" anchors.bottom: parent.bottom anchors.top: parent.top From 2556f24b8f9b7ed78b27387f97a1629cf591830f Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 18:06:54 +0100 Subject: [PATCH 003/126] Updating QRC --- qml.qrc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qml.qrc b/qml.qrc index 86f7dde3..f8e75e48 100644 --- a/qml.qrc +++ b/qml.qrc @@ -163,5 +163,7 @@ pages/Keys.qml images/menu.png images/appicon.ico + images/right.png + images/card-background.png From f68ca5d76ead42bc9bd529cf41642caba20c6d40 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 18:07:22 +0100 Subject: [PATCH 004/126] Add property fontBold to Labels, change default color --- components/Label.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/Label.qml b/components/Label.qml index 76b13c05..3de0eadb 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -36,6 +36,7 @@ Item { property alias textFormat: label.textFormat property string tipText: "" property int fontSize: 16 * scaleRatio + property bool fontBold: false property alias wrapMode: label.wrapMode property alias horizontalAlignment: label.horizontalAlignment signal linkActivated() @@ -50,7 +51,8 @@ Item { anchors.left: parent.left font.family: "Arial" font.pixelSize: fontSize - color: "#555555" + font.bold: fontBold + color: "white" onLinkActivated: item.linkActivated() } From f49ad844b810c68415bc4daf78e7bc578529172a Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 18:45:06 +0100 Subject: [PATCH 005/126] Redoing the menu buttons --- components/MenuButton.qml | 51 +++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 778dca68..7c7b0426 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 +import QtGraphicalEffects 1.0 Rectangle { id: button @@ -55,9 +56,25 @@ Rectangle { return offset } - color: checked ? "#FFFFFF" : "#1C1C1C" + color: "black" property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 - height: present ? ((appWindow.height >= 800) ? 48 * scaleRatio : 36 * scaleRatio ) : 0 + height: present ? ((appWindow.height >= 800) ? 40 * scaleRatio : 52 * scaleRatio ) : 0 + + Item { + visible: parent.checked ? true : false + width: 300 + height: 40 + + LinearGradient { + anchors.fill: parent + start: Qt.point(0, 0) + end: Qt.point(300, 0) + gradient: Gradient { + GradientStop { position: 1.0; color: "#333333" } + GradientStop { position: 0.0; color: "black" } + } + } + } transform: Scale { yScale: button.present ? 1 : 0 @@ -83,18 +100,18 @@ Rectangle { anchors.bottom: parent.bottom anchors.left: parent.left anchors.leftMargin: parent.getOffset() - width: 50 * scaleRatio + width: 46 * scaleRatio Rectangle { id: dot anchors.centerIn: parent - width: 14 * scaleRatio + width: 8 * scaleRatio height: width radius: height / 2 Rectangle { anchors.centerIn: parent - width: 10 * scaleRatio + width: 8 * scaleRatio height: width radius: height / 2 color: "#1C1C1C" @@ -112,31 +129,33 @@ Rectangle { } } - Rectangle { - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - width: 1 - color: "#DBDBDB" - visible: parent.checked - } +// Rectangle { +// anchors.left: parent.left +// anchors.top: parent.top +// anchors.bottom: parent.bottom +// width: 1 +// color: "#DBDBDB" +// visible: parent.checked +// } + // menu button arrow Image { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: 20 * scaleRatio anchors.leftMargin: parent.getOffset() - source: "../images/menuIndicator.png" + source: "../images/right.png" } + // menu button text Text { id: label anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: parent.getOffset() + 50 * scaleRatio + anchors.leftMargin: parent.getOffset() + 38 * scaleRatio font.family: "Arial" font.pixelSize: 16 * scaleRatio - color: parent.checked ? "#000000" : "#FFFFFF" + color: "#FFFFFF" } MouseArea { From f362953afc1ffb5c029c280254b163531c02b80b Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 18:46:00 +0100 Subject: [PATCH 006/126] New layouts for leftpanel --- LeftPanel.qml | 232 ++++++++++++++++++++++++-------------------------- 1 file changed, 111 insertions(+), 121 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index 171646ff..173b9c24 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -77,147 +77,137 @@ Rectangle { anchors.bottom: parent.bottom anchors.top: parent.top - // Item with monero logo - Item { - visible: !isMobile - id: logoItem + // card with monero logo + Column { + visible: true + id: column1 + height: 200 anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: (persistentSettings.customDecorations)? 66 : 36 - height: logo.implicitHeight - - Image { - id: logo - anchors.left: parent.left - anchors.leftMargin: 50 - source: "images/moneroLogo.png" - } - - Text { - id: viewOnlyLabel - visible: viewOnly - text: qsTr("View Only") + translationManager.emptyString - anchors.top: logo.bottom - anchors.topMargin: 5 - anchors.left: parent.left - anchors.leftMargin: 50 - font.bold: true - color: "blue" - } - - Text { - id: testnetLabel - visible: persistentSettings.nettype !== NetworkType.MAINNET - text: (persistentSettings.nettype === NetworkType.TESTNET ? qsTr("Testnet") : qsTr("Stagenet")) + translationManager.emptyString - anchors.top: logo.bottom - anchors.topMargin: 5 - anchors.left: viewOnly ? viewOnlyLabel.right : parent.left - anchors.leftMargin: viewOnly ? 10 : 50 - font.bold: true - color: "red" - } - - /* Disable twitter/news panel - Image { - anchors.left: parent.left - anchors.verticalCenter: logo.verticalCenter - anchors.leftMargin: 19 - source: appWindow.rightPanelExpanded ? "images/expandRightPanel.png" : - "images/collapseRightPanel.png" - } - - MouseArea { - anchors.fill: parent - onClicked: appWindow.rightPanelExpanded = !appWindow.rightPanelExpanded - } - */ - } - - - - Column { - visible: !isMobile - id: column1 - anchors.left: parent.left - anchors.right: parent.right - anchors.top: logoItem.bottom - anchors.topMargin: 26 - spacing: 5 - - Label { - visible: !isMobile - id: balanceLabel - text: qsTr("Balance") + translationManager.emptyString - anchors.left: parent.left - anchors.leftMargin: 50 - } + anchors.topMargin: (persistentSettings.customDecorations)? 56 : 36 Row { - visible: !isMobile + visible: true Item { + anchors.left: parent.left + anchors.top: parent.top + anchors.leftMargin: 20 anchors.verticalCenter: parent.verticalCenter - height: 26 * scaleRatio + height: 490 * scaleRatio width: 50 * scaleRatio Image { - anchors.centerIn: parent - source: "images/lockIcon.png" + width: 259; height:170 + fillMode: Image.PreserveAspectFit + source: "images/card-background.png" } - } - Text { - visible: !isMobile - id: balanceText - anchors.verticalCenter: parent.verticalCenter - font.family: "Arial" - color: "#000000" - text: "N/A" - // dynamically adjust text size - font.pixelSize: { - var digits = text.split('.')[0].length - var defaultSize = 25; - if(digits > 2) { - return defaultSize - 1.1*digits + Text { + visible: !isMobile + id: balanceText + anchors.left: parent.left + anchors.leftMargin: 20 + anchors.top: parent.top + anchors.topMargin: 76 + font.family: "Arial" + color: "#FFFFFF" + text: "N/A" + // dynamically adjust text size + font.pixelSize: { + var digits = text.split('.')[0].length + var defaultSize = 22; + if(digits > 2) { + return defaultSize - 1.1*digits + } + return defaultSize; } - return defaultSize; } - } - } - Item { //separator - anchors.left: parent.left - anchors.right: parent.right - height: 1 - } - - Label { - id: unlockedBalanceLabel - text: qsTr("Unlocked balance") + translationManager.emptyString - anchors.left: parent.left - anchors.leftMargin: 50 - } - - Text { - id: unlockedBalanceText - anchors.left: parent.left - anchors.leftMargin: 50 - font.family: "Arial" - color: "#000000" - text: "N/A" - // dynamically adjust text size - font.pixelSize: { - var digits = text.split('.')[0].length - var defaultSize = 18; - if(digits > 3) { - return defaultSize - 0.6*digits + Text { + id: unlockedBalanceText + anchors.left: parent.left + anchors.leftMargin: 20 + anchors.top: parent.top + anchors.topMargin: 126 + font.family: "Arial" + color: "#FFFFFF" + text: "N/A" + // dynamically adjust text size + font.pixelSize: { + var digits = text.split('.')[0].length + var defaultSize = 20; + if(digits > 3) { + return defaultSize - 0.6*digits + } + return defaultSize; + } } - return defaultSize; + Text { + id: testnetLabel + visible: persistentSettings.testnet + text: qsTr("Testnet") + translationManager.emptyString + anchors.top: logo.bottom + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 50 + font.bold: true + color: "red" + } +// @TODO: implement +// Text { +// id: viewOnlyLabel +// visible: viewOnly +// text: qsTr("View Only") + translationManager.emptyString +// anchors.top: logo.bottom +// anchors.topMargin: 5 +// anchors.left: parent.left +// anchors.leftMargin: 50 +// font.bold: true +// color: "blue" +// } + Label { + id: unlockedBalanceLabel + text: qsTr("Unlocked balance") + translationManager.emptyString + anchors.left: parent.left + anchors.leftMargin: 20 + anchors.top: parent.top + anchors.topMargin: 110 + } + + Label { + visible: !isMobile + id: balanceLabel + text: qsTr("Balance") + translationManager.emptyString + fontSize: 14 + anchors.left: parent.left + anchors.leftMargin: 20 + anchors.top: parent.top + anchors.topMargin: 60 + } + Item { //separator + anchors.left: parent.left + anchors.right: parent.right + height: 1 + } + /* Disable twitter/news panel + Image { + anchors.left: parent.left + anchors.verticalCenter: logo.verticalCenter + anchors.leftMargin: 19 + source: appWindow.rightPanelExpanded ? "images/expandRightPanel.png" : + "images/collapseRightPanel.png" + } + + MouseArea { + anchors.fill: parent + onClicked: appWindow.rightPanelExpanded = !appWindow.rightPanelExpanded + } + */ } } } - Rectangle { anchors.top: parent.top anchors.left: parent.left From c64977a7db61d5f4ce6215d364952bf41028f639 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 19:43:40 +0100 Subject: [PATCH 007/126] Removing some obsolete rectangles --- LeftPanel.qml | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index 173b9c24..d3ca0dca 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -208,31 +208,13 @@ Rectangle { } } - Rectangle { - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: menuRect.top - width: 1 - color: "#DBDBDB" - } - - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - height: 1 - color: "#DBDBDB" - } - - - Rectangle { id: menuRect anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.top: (isMobile)? parent.top : column1.bottom - anchors.topMargin: (isMobile)? 0 : 25 + anchors.topMargin: (isMobile)? 0 : 4 color: "#1C1C1C" From 8a3490a30064d5e373a7a5d32f3e90b1655e099e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 21:03:10 +0100 Subject: [PATCH 008/126] Added titlebar images, updated QRC --- images/close.png | Bin 0 -> 280 bytes images/fullscreen.png | Bin 0 -> 185 bytes images/minimize.png | Bin 0 -> 125 bytes qml.qrc | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 images/close.png create mode 100644 images/fullscreen.png create mode 100644 images/minimize.png diff --git a/images/close.png b/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..c9e47a66406edad73567a5cd583d2c181550cf92 GIT binary patch literal 280 zcmV+z0q6dSP)Px#(n&-?R5%f(lQ9m$FbqW#HhLDAxf$I+Y_ua6V(tuQ31fI41*s%XGGOU9sr~)k z#IBDqo}6<7xOnehtX(5#3+W8PhKG_5U`heDbxWKHhH?fc2e^TITBU9pahqEWtYo^J z7NHee)o|u%LO|>!GP6~pOhU&zSpl{2FDnFAM^JTD z7PRlriFIL?53$l(#8&L1)Fr^Ga;kyyBTW&Hz!k23471O|tobU!JYDStT9^P3100007_P z$qXi*$65>Q!dF%1UQsx7(LlmdKI;Vst0Be9gFaQ7m literal 0 HcmV?d00001 diff --git a/images/minimize.png b/images/minimize.png new file mode 100644 index 0000000000000000000000000000000000000000..f0f59144185164bc47813e2239155ad146b02eac GIT binary patch literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&I!3HFo9rG^&DaPU;cPEB*=VV?2Ip&@&jv*3~ z$$$R;-!II}?5rxVnZeNV0e?WSwep1pcOBSvwjI#lqm~ Xtm9=V*n8R$Xas|&tDnm{r-UW|tyU!W literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index f8e75e48..7b52b992 100644 --- a/qml.qrc +++ b/qml.qrc @@ -165,5 +165,8 @@ images/appicon.ico images/right.png images/card-background.png + images/minimize.png + images/fullscreen.png + images/close.png From 3b4d7ba93e74be3d2586a76841b789abb01d9289 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 22:40:38 +0100 Subject: [PATCH 009/126] Added a white version of the monero logo --- images/moneroLogo_white.png | Bin 0 -> 1808 bytes qml.qrc | 1 + 2 files changed, 1 insertion(+) create mode 100644 images/moneroLogo_white.png diff --git a/images/moneroLogo_white.png b/images/moneroLogo_white.png new file mode 100644 index 0000000000000000000000000000000000000000..ba4e1438dd4e94f4c746b177e3e5c78bd56abcba GIT binary patch literal 1808 zcmV+r2k-caP)-!?P)Lj`in3S& zK|q2?0~9K$RLb#>cb=IZ<}UA1Nc$x>d2?pD_nmuYzHiQ4LjByIga~z1#r=MI1+onh|L%$gJ@}W#b zibZ6lhzu8zL>j(Kh{*jS@_~r#6_E-Zvs^^Bi^u{I=@Hc58WwsUZg7l;_{7sMJ4U~j zBCLey5<0>Waeh-Ag^XP$`cjydK^5ovA5NKh4BxDZ1KM;4Ihv3H5+ z*B96Y3#LIQQ&9bR@Z0)BG=RLVW3{f zzz+cR(+r5dzy_d2K>go7wDxpr z2J{QL+0X!cZh$=-SOYXN_AMG*je#Z_gnfWFflAZ%IpDE0oOu^8wHjZ}ES;56S5d?` zWx(~Gs~a#8I32^+<0E%Od{VcG@=*dxa9Yc51;dkY;6!L+sPPwsp;Pb#? zpq*JITpsOj?y)39Jo>Oe^+QVJb^_YyeSP=^IB9~Q5NPiSmUPfB=5D7DI1p0bAVAwR z0(t?D82fk5?@mBlr+gN8JB|Nv4ww(TRYkZu+)`pVWvnS5QT|D_A7<(|ipX+fn_&3M z-lIbXJiOJ6kr$#Nid1KuH1@T%EDs?fa!y3LIAi6T`pp^mvb`DOM8cs2cMDhvEC&uc zwrk9uHQz+sN?^CKb@tGRi^Cbr&Oba`rzqN(Wo!>d?3`*Mp4Plg3Rg$?B@Pam6}nj} zAiA1{dw~jIwXx?rbaAhti#6tfedFTU9$hTrB()ZLwt$5mkyaCNRFikF8M_tvXEPXE z^xgfBl!oYL8t!yv{WO!^dJ?z~Xz19BfMcG3utN1X(A+7v)hJB|Z9;@r7{+R5E)@jV zsSa41fg_7z8KWoi6@Ccy2+_FK%p2Q*nT)3Hs7@zQ+Q;-R5TaK;GU z9QA$bC0zxK_pA2*?@ibe5F0o|)#Oi0><$TtL%=(xey-*g5+M)Yo8(EJd;W0}cs&D$Z?C51{!-x($@3c*)9@bz zE}-gpM+;!1XM$Ty23|C_b-<2`r64XS+E^^~wn6kJl%8 zxU~fMM)e4W|Bq+r^o1E}hs%YzsxMsaG~LtgFD^Xg>bkZNE{vtvpGTpMZfH;Xc$4nLRHA zaB3!7$3-=Gm3YN$Hye^XtMFk0$!{WjXsD~MkCMws9#DSi>Ve!4LFr~L*Ly_G>VUSz z5%~y6o?!L_RuJzzV;?X`og&rb^a3vKOyg3bR7IkTalj1$0&@y5%;>!^d`0rS=Gj&Ao&RwMrimages/minimize.png images/fullscreen.png images/close.png + images/moneroLogo_white.png From f51cf3593520032e52d1b7bc81c91a628f510506 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 12 Nov 2017 23:17:34 +0100 Subject: [PATCH 010/126] Added transparent monero icons --- images/moneroIcon-trans28x28.png | Bin 0 -> 1051 bytes images/moneroIcon-trans56x56.png | Bin 0 -> 2013 bytes images/moneroIcon-trans84x84.png | Bin 0 -> 3126 bytes qml.qrc | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 images/moneroIcon-trans28x28.png create mode 100644 images/moneroIcon-trans56x56.png create mode 100644 images/moneroIcon-trans84x84.png diff --git a/images/moneroIcon-trans28x28.png b/images/moneroIcon-trans28x28.png new file mode 100644 index 0000000000000000000000000000000000000000..61092193cef15d008177ce42fbe839de3c68a9e7 GIT binary patch literal 1051 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/fullscreen.png images/close.png images/moneroLogo_white.png + images/moneroIcon-trans28x28.png + images/moneroIcon-trans84x84.png + images/moneroIcon-trans56x56.png From 4c432000cb67c4bad7bc91cbf19202f91ac9528f Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 13 Nov 2017 00:11:55 +0100 Subject: [PATCH 011/126] Removing borders; changing left-border color --- MiddlePanel.qml | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 38c9bb2c..6cac3f10 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -212,30 +212,14 @@ Rectangle { }// flickable } + // border - Rectangle { - anchors.top: styledRow.bottom - anchors.bottom: parent.bottom - anchors.right: parent.right - width: 1 - color: "#DBDBDB" - } - Rectangle { anchors.top: styledRow.bottom anchors.bottom: parent.bottom anchors.left: parent.left width: 1 - color: "#DBDBDB" - } - - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - height: 1 - color: "#DBDBDB" - + color: "#313131" } /* connect "payment" click */ From ed95c4f4bf98439adb2c0296ec1ec86978ccb24e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 13 Nov 2017 00:13:05 +0100 Subject: [PATCH 012/126] Added question.png, updated QRC --- images/question.png | Bin 0 -> 334 bytes qml.qrc | 1 + 2 files changed, 1 insertion(+) create mode 100644 images/question.png diff --git a/images/question.png b/images/question.png new file mode 100644 index 0000000000000000000000000000000000000000..79b4d3bc2b4dc5e4aba7e7609753c409db5df419 GIT binary patch literal 334 zcmV-U0kQsxP)Px$2uVaiR45f~k+DhxK@f&-!-_>x_!dguz%;og+KAO*lfvezyo6OqmuHBrq)`+> zgli<}tSp2ec@fR|&1H6P-F4u*`Df<8*<;US8g*TtBCp^?Tc6}RW6WA=BM(d^X)OAm zxW&A%y2+VdF+M>DE@24Qcs?wm0Erjgob6@ve8+Hu%At@q-8bE%<9N`images/moneroIcon-trans28x28.png images/moneroIcon-trans84x84.png images/moneroIcon-trans56x56.png + images/question.png From f6dc84a26adf26689a261c34292dcfa12e8b75f6 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 13 Nov 2017 00:20:54 +0100 Subject: [PATCH 013/126] Added top-border for titlebar --- main.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/main.qml b/main.qml index f8c6af06..3b57a523 100644 --- a/main.qml +++ b/main.qml @@ -1533,6 +1533,15 @@ ApplicationWindow { } } } + + Rectangle { + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.left: parent.left + height:1 + color: "#2F2F2F" + z: 2 + } } // new ToolTip From 9347e8d936175703227b26c3f979c07cdee4b147 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 13 Nov 2017 00:36:41 +0100 Subject: [PATCH 014/126] Changed some colors & margins for LeftPanel --- LeftPanel.qml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index d3ca0dca..a9fe715e 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -85,7 +85,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: (persistentSettings.customDecorations)? 56 : 36 + anchors.topMargin: (persistentSettings.customDecorations)? 76 : 56 Row { visible: true @@ -147,7 +147,7 @@ Rectangle { id: testnetLabel visible: persistentSettings.testnet text: qsTr("Testnet") + translationManager.emptyString - anchors.top: logo.bottom + anchors.top: unlockedBalanceText.bottom anchors.topMargin: 5 anchors.left: parent.left anchors.leftMargin: 50 @@ -257,7 +257,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: dashboardButton.checked || transferButton.checked ? "#1C1C1C" : "#505050" + color: dashboardButton.checked || transferButton.checked ? "#1C1C1C" : "#313131" height: 1 } */ @@ -283,7 +283,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } @@ -309,7 +309,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } @@ -332,7 +332,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } @@ -356,7 +356,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } @@ -378,7 +378,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } @@ -404,7 +404,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: miningButton.checked || settingsButton.checked ? "#1C1C1C" : "#505050" + color: miningButton.checked || settingsButton.checked ? "#1C1C1C" : "#313131" height: 1 } // ------------- TxKey tab --------------- @@ -450,7 +450,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } @@ -475,7 +475,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } // ------------- Settings tab --------------- @@ -497,7 +497,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } // ------------- Sign/verify tab --------------- @@ -520,7 +520,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } From 5be04964a3d2c21882592a7eac5b8bec12a66d44 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 15 Nov 2017 23:43:16 +0100 Subject: [PATCH 015/126] Added images, updated QRC --- images/balanceGradient.jpg | Bin 0 -> 4201 bytes images/expand.png | Bin 0 -> 238 bytes images/titlebarGradient.jpg | Bin 0 -> 760 bytes qml.qrc | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 images/balanceGradient.jpg create mode 100644 images/expand.png create mode 100644 images/titlebarGradient.jpg diff --git a/images/balanceGradient.jpg b/images/balanceGradient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..24ae02cca0ae9e8c48b410ce4e77b4eca48fdf73 GIT binary patch literal 4201 zcmb_fNl+6(6z!QwG9fHxFoEbzP!ukfxS(DvK~T8?CP6K0O2DiTQZO=@W$xL?>z)%b|)6gG;0Pu(}V(j}Ej2vrX0B?@4 zL^6P7IrS=fz!{7tdC>}3hT~WRYvMU{VM`d66AZvOD|W%k9Mkm83B?t*)Y^L9?nzI) zm)rGbVO+tN*?TI-=433&JJ!%zSaN^ys=3F{U0V{ruBh}u_pmvsD#GHJQC*jr)!63h zan76hb>!Q_-qG({_8vTOzP+>W?T@WxhfZF&{;2=m&$QLkQf_t5MxtuMQv)m=Zo!L*PFz2dv3v=v4yi2WmLu;%bU|s*m|EY>0Ug%sw#fn zag-g$jHD%*Gv^kSI@7+MyY^sSa?i-O>bl0ZP|8`ZAZa3J3S~G1qBxnR09JsvjwX-0 zpt*BX&29T`ds)h7r#JW@aC>!Fc_Z*ZbBkFQ;d3>1S<0))V3%XaG)^A47` zM6&}$hUe`X^GB{)7h$&++uMYvF&_5S0&QMkPx#n0J(@c=%8G^X?$u*^upvrXll8!2 z_hGQzy6}8HqG9WNCc=I!Him}6TXHB#4^3Pm93Ws*q@!W0e1`lz`kO#RC(iiHJ8Ifh zPK8}WY+V9_*fg~RS!;pa2%G%sq?&-Q`dVO*giSGqDuF8A)D2#RYzypFuqnnMH35nq zC=o7?8}|9JCt(b7gOTEDf&D>ja!nHpm8^%<2M4BvO)FHz-+{A1>NFEhFKGkn-)i1U z7bDdjF}?T=sDJCRNp>e<<2Q(Yf2)r_JdFvLsTlOPsxpYSph>5*yQube$Z4p1)&IXq z(&;v!{*B4^I2BFGnMMzdzg4FlrA+bC>GZ((+v^`TG&KAff?4w6k1b z*pWx(Fp?X(K{*=+!oika)z6YL9MP%eO=v!mc`Lmt#GfI;P2xP2{2eAXrBLPcsynG% zA(FoX*u?Mx#YBn=tB2IT1K65bQIiwpb^_m7r2ehJCKaMmti;$bc~SfwEOPQ$><@#~ Kzjb3;+NC literal 0 HcmV?d00001 diff --git a/images/titlebarGradient.jpg b/images/titlebarGradient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c89cf220b7f20caf20c786a2a530becf3aebedec GIT binary patch literal 760 zcmex=076#t`M;I3|Ffgz&F*5=wC}8JcV`brF=3-)G;06k_F$3*~ z$uR(>nAw>)7&#fZxCI!P7@1iZnVCT@Vq)VgWn^Mz5o8r&Q)CxbV&E_oaWqmE>JStB$oTx!#yOOHOK zG?z?nNnO18@a4yv7HOYLwJfbXJiQ_!qtY`nv&zaVDyv%C+B-VCrc9kSea6gLOO`HM zzGCI7EnBy3-?4Mok)y|spE!By%GGPvZ`{1~Scpbh03eq7bVg8-tRtV<5XxqDUc!Q={@k(V&G%V#b^sRSsTsF8Uz;u*pPq zQm{m_%g05V)J!Eq%v@8{xr&=7yOn_48=6`gX5P{YcJOCSsVPgg9J%u3%haV?k6wNH zRl_|z&7!Pr+OloOu08vfUfw=^`S#=2pMUp=$f)R;v0}%G8!vuXdPZhecFtV6^W@E! zKeep9qOz*GX06(F>ej1Y|8Fty0HcRVkXewyp5X$Y{rTVgKjzoHzU$rp+y3=`h9kef zN6T8c{`k)j|4;e;uIqjV{~3-lW0o&Pfk)ZhF2`uh5km;BfNcKyB|Cu3FA{!isU!`|xeQMMLG|IYtr i|IzO6_5NVxKmQpve1Et0>6P_w>QC5zlmi;||0V!7OAI3b literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index 87b81338..7be45fff 100644 --- a/qml.qrc +++ b/qml.qrc @@ -173,5 +173,8 @@ images/moneroIcon-trans84x84.png images/moneroIcon-trans56x56.png images/question.png + images/expand.png + images/balanceGradient.jpg + images/titlebarGradient.jpg From b34432c6ac27a7a3547b8e157f91300e7f1cb95a Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 15 Nov 2017 23:51:22 +0100 Subject: [PATCH 016/126] Titlebar, first version --- components/TitleBar.qml | 99 ++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 27 deletions(-) diff --git a/components/TitleBar.qml b/components/TitleBar.qml index 2a2ae575..12ad3ce0 100644 --- a/components/TitleBar.qml +++ b/components/TitleBar.qml @@ -29,47 +29,85 @@ import QtQuick 2.2 import QtQuick.Window 2.0 import QtQuick.Layouts 1.1 +import QtGraphicalEffects 1.0 Rectangle { id: titleBar - color: "#000000" + property int mouseX: 0 property bool containsMouse: false property alias basicButtonVisible: goToBasicVersionButton.visible property bool customDecorations: true signal goToBasicVersion(bool yes) - height: customDecorations && !isMobile ? 30 : 0 + height: customDecorations && !isMobile ? 50 : 0 y: -height property string title property alias maximizeButtonVisible: maximizeButton.visible z: 1 - Text { - anchors.centerIn: parent - font.family: "Arial" - font.pixelSize: 15 - color: "#FFFFFF" - text: titleBar.title - visible: customDecorations + Item { + id: test + width: parent.width + height: 50 + z: 1 + + LinearGradient { + anchors.fill: parent + start: Qt.point(0, 0) + end: Qt.point(parent.width, 0) + gradient: Gradient { + GradientStop { position: 1.0; color: "#1a1a1a" } + GradientStop { position: 0.0; color: "black" } + } + } } - Rectangle { + Item{ + id: titlebarlogo + width: 128 + height: 50 + anchors.centerIn: parent + visible: customDecorations + z: 1 + Image { + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: 11 + width: 86 + height: 26 + fillMode: Image.PreserveAspectFit + source: "../images/moneroLogo_white.png" + } + + Image { + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: 11 + width: 28 + height: 28 + source: "../images/moneroIcon-trans28x28.png" + } + } + + // collapse left panel + Rectangle { id: goToBasicVersionButton property bool containsMouse: titleBar.mouseX >= x && titleBar.mouseX <= x + width property bool checked: false anchors.top: parent.top anchors.left: parent.left - color: "#FFE00A" - height: 30 * scaleRatio + color: "black" + height: 50 * scaleRatio width: height visible: isMobile + z: 2 Image { - width: parent.width * 2/3; - height: width; + width: 14 + height: 14 anchors.centerIn: parent - source: "../images/menu.png" + source: "../images/expand.png" } MouseArea { @@ -90,17 +128,20 @@ Rectangle { anchors.top: parent.top anchors.bottom: parent.bottom visible: parent.customDecorations + z: 2 Rectangle { property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse anchors.top: parent.top anchors.bottom: parent.bottom - width: height - color: containsMouse ? "#6B0072" : "#000000" + width: 42 + color: containsMouse ? "#6B0072" : "#00000000" Image { anchors.centerIn: parent - source: "../images/helpIcon.png" + width: 9 + height: 16 + source: "../images/question.png" } MouseArea { @@ -116,12 +157,12 @@ Rectangle { property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse anchors.top: parent.top anchors.bottom: parent.bottom - width: height - color: containsMouse ? "#3665B3" : "#000000" + width: 42 + color: containsMouse ? "#3665B3" : "#00000000" Image { anchors.centerIn: parent - source: "../images/minimizeIcon.png" + source: "../images/minimize.png" } MouseArea { @@ -138,13 +179,15 @@ Rectangle { property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse anchors.top: parent.top anchors.bottom: parent.bottom - width: height - color: containsMouse ? "#FF6C3C" : "#000000" + width: 42 + color: containsMouse ? "#FF6C3C" : "#00000000" Image { anchors.centerIn: parent + height: 16 + width: 16 source: appWindow.visibility === Window.FullScreen ? "../images/backToWindowIcon.png" : - "../images/maximizeIcon.png" + "../images/fullscreen.png" } @@ -162,12 +205,14 @@ Rectangle { property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse anchors.top: parent.top anchors.bottom: parent.bottom - width: height - color: containsMouse ? "#E04343" : "#000000" + width: 42 + color: containsMouse ? "#E04343" : "#00000000" Image { anchors.centerIn: parent - source: "../images/closeIcon.png" + width: 16 + height: 16 + source: "../images/close.png" } MouseArea { From f14dc7066382a9bd6d3d8b9eb8e257da3b09445f Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 15 Nov 2017 23:51:42 +0100 Subject: [PATCH 017/126] Implement subtle gradient behind balance card --- LeftPanel.qml | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index a9fe715e..678cbef3 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -42,6 +42,7 @@ Rectangle { property alias progressBar : progressBar property alias daemonProgressBar : daemonProgressBar property alias minutesToUnlockTxt: unlockedBalanceLabel.text + property int titleBarHeight: 50 signal dashboardClicked() signal historyClicked() @@ -85,13 +86,29 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: (persistentSettings.customDecorations)? 76 : 56 + // @TODO: customDecorations? + anchors.topMargin: (persistentSettings.customDecorations)? 50 : 0 + + Row { + Item { + x: 0 + y: 0 + width: 300 + height: 232 + + Image { + width: 300; height: 232 + source: "images/balanceGradient.jpg" + } + } + } Row { visible: true Item { anchors.left: parent.left anchors.top: parent.top + anchors.topMargin: 20 anchors.leftMargin: 20 anchors.verticalCenter: parent.verticalCenter height: 490 * scaleRatio @@ -102,6 +119,16 @@ Rectangle { fillMode: Image.PreserveAspectFit source: "images/card-background.png" } + } + + Item { + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: 20 + anchors.leftMargin: 20 + anchors.verticalCenter: parent.verticalCenter + height: 490 * scaleRatio + width: 50 * scaleRatio Text { visible: !isMobile @@ -214,7 +241,7 @@ Rectangle { anchors.right: parent.right anchors.bottom: parent.bottom anchors.top: (isMobile)? parent.top : column1.bottom - anchors.topMargin: (isMobile)? 0 : 4 + anchors.topMargin: (isMobile)? 0 : 32 color: "#1C1C1C" From ad68107e1b712ba00a51b1706a9402a7d36862e2 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 16 Nov 2017 13:04:45 +0100 Subject: [PATCH 018/126] New titlebar logo --- components/TitleBar.qml | 16 +++------------- images/titlebarLogo.png | Bin 0 -> 2569 bytes qml.qrc | 1 + 3 files changed, 4 insertions(+), 13 deletions(-) create mode 100644 images/titlebarLogo.png diff --git a/components/TitleBar.qml b/components/TitleBar.qml index 12ad3ce0..c1cc186f 100644 --- a/components/TitleBar.qml +++ b/components/TitleBar.qml @@ -64,29 +64,19 @@ Rectangle { Item{ id: titlebarlogo - width: 128 + width: 125 height: 50 anchors.centerIn: parent visible: customDecorations z: 1 - Image { - anchors.right: parent.right - anchors.top: parent.top - anchors.topMargin: 11 - width: 86 - height: 26 - fillMode: Image.PreserveAspectFit - source: "../images/moneroLogo_white.png" - } - Image { anchors.left: parent.left anchors.top: parent.top anchors.topMargin: 11 - width: 28 + width: 125 height: 28 - source: "../images/moneroIcon-trans28x28.png" + source: "../images/titlebarLogo.png" } } diff --git a/images/titlebarLogo.png b/images/titlebarLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..8ea3ae95601f9b0f9db300878e31dc13640d1ca0 GIT binary patch literal 2569 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 literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index 7be45fff..d1358ba3 100644 --- a/qml.qrc +++ b/qml.qrc @@ -176,5 +176,6 @@ images/expand.png images/balanceGradient.jpg images/titlebarGradient.jpg + images/titlebarLogo.png From 5fdc9d894eb5a0937e5900ac72d0f78fb75a6154 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 16 Nov 2017 18:40:09 +0100 Subject: [PATCH 019/126] New menu button layout - implemented arrow thingy --- LeftPanel.qml | 8 ++ components/MenuButton.qml | 169 ++++++++++++++++++-------------------- images/menuArrow.png | Bin 0 -> 15933 bytes qml.qrc | 1 + 4 files changed, 90 insertions(+), 88 deletions(-) create mode 100755 images/menuArrow.png diff --git a/LeftPanel.qml b/LeftPanel.qml index 678cbef3..faf55a6d 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -289,6 +289,14 @@ Rectangle { } */ + // top border + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.leftMargin: 16 + color: "#313131" + height: 1 + } // ------------- Transfer tab --------------- MenuButton { diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 7c7b0426..600bcd51 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -58,21 +58,89 @@ Rectangle { color: "black" property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 - height: present ? ((appWindow.height >= 800) ? 40 * scaleRatio : 52 * scaleRatio ) : 0 + height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 52 * scaleRatio ) : 0 - Item { - visible: parent.checked ? true : false - width: 300 - height: 40 + // Button gradient whilst checked + // @TODO: replace by .png - gradient not available in 2d renderer + LinearGradient { + visible: button.checked ? true : false + anchors.fill: parent + start: Qt.point(0, 0) + end: Qt.point(300, 0) + gradient: Gradient { + GradientStop { position: 1.0; color: "#333333" } + GradientStop { position: 0.0; color: "black" } + } + } - LinearGradient { - anchors.fill: parent - start: Qt.point(0, 0) - end: Qt.point(300, 0) - gradient: Gradient { - GradientStop { position: 1.0; color: "#333333" } - GradientStop { position: 0.0; color: "black" } - } + // button decorations that are subject to leftMargin offsets + Rectangle { + anchors.left: parent.left + anchors.leftMargin: parent.getOffset() + 20 * scaleRatio + height: parent.height + width: button.checked ? 20: 10 + color: "#00000000" + + // dot if unchecked + Rectangle { + id: dot + anchors.centerIn: parent + width: 8 * scaleRatio + height: 8 * scaleRatio + radius: 4 * scaleRatio + color: button.dotColor + visible: !button.checked + } + + // arrow if checked + Image { + anchors.centerIn: parent + anchors.left: parent.left + source: "../images/menuArrow.png" + visible: button.checked + } + + // button text + Text { + id: label + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.right + anchors.leftMargin: 8 * scaleRatio + font.family: "Arial" + font.bold: true + font.pixelSize: 16 * scaleRatio + color: "#FFFFFF" + } + } + + // menu button right arrow + Image { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 20 * scaleRatio + anchors.leftMargin: parent.getOffset() + source: "../images/right.png" + opacity: button.checked ? 1.0 : 0.4 + } + + Text { + id: symbolText + anchors.centerIn: parent + font.pixelSize: 11 * scaleRatio + font.bold: true + color: button.checked || buttonArea.containsMouse ? "#FFFFFF" : dot.color + visible: appWindow.ctrlPressed + } + + MouseArea { + id: buttonArea + anchors.fill: parent + hoverEnabled: true + onClicked: { + if(parent.checked) + return + button.doClick() + parent.checked = true } } @@ -94,79 +162,4 @@ Rectangle { // we get the value of checked before the change ScriptAction { script: if (under) under.numSelectedChildren += checked > 0 ? -1 : 1 } } - - Item { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.leftMargin: parent.getOffset() - width: 46 * scaleRatio - - Rectangle { - id: dot - anchors.centerIn: parent - width: 8 * scaleRatio - height: width - radius: height / 2 - - Rectangle { - anchors.centerIn: parent - width: 8 * scaleRatio - height: width - radius: height / 2 - color: "#1C1C1C" - visible: !button.checked && !buttonArea.containsMouse - } - } - - Text { - id: symbolText - anchors.centerIn: parent - font.pixelSize: 11 * scaleRatio - font.bold: true - color: button.checked || buttonArea.containsMouse ? "#FFFFFF" : dot.color - visible: appWindow.ctrlPressed - } - } - -// Rectangle { -// anchors.left: parent.left -// anchors.top: parent.top -// anchors.bottom: parent.bottom -// width: 1 -// color: "#DBDBDB" -// visible: parent.checked -// } - - // menu button arrow - Image { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 20 * scaleRatio - anchors.leftMargin: parent.getOffset() - source: "../images/right.png" - } - - // menu button text - Text { - id: label - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: parent.getOffset() + 38 * scaleRatio - font.family: "Arial" - font.pixelSize: 16 * scaleRatio - color: "#FFFFFF" - } - - MouseArea { - id: buttonArea - anchors.fill: parent - hoverEnabled: true - onClicked: { - if(parent.checked) - return - button.doClick() - parent.checked = true - } - } } diff --git a/images/menuArrow.png b/images/menuArrow.png new file mode 100755 index 0000000000000000000000000000000000000000..6443f794e5d85980340d10dac2e138e7e6d3dab1 GIT binary patch literal 15933 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/balanceGradient.jpg images/titlebarGradient.jpg images/titlebarLogo.png + images/menuArrow.png From 229bade38c903ab4c3d2acdaec503ff60f453dc9 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 16 Nov 2017 18:59:10 +0100 Subject: [PATCH 020/126] Added font: SFUIDisplay, updated QRC --- fonts/SFUIDisplay-Bold.otf | Bin 0 -> 154912 bytes fonts/SFUIDisplay-Light.otf | Bin 0 -> 149000 bytes fonts/SFUIDisplay-Medium.otf | Bin 0 -> 153068 bytes fonts/SFUIDisplay-Regular.otf | Bin 0 -> 141260 bytes qml.qrc | 4 ++++ 5 files changed, 4 insertions(+) create mode 100644 fonts/SFUIDisplay-Bold.otf create mode 100644 fonts/SFUIDisplay-Light.otf create mode 100644 fonts/SFUIDisplay-Medium.otf create mode 100644 fonts/SFUIDisplay-Regular.otf diff --git a/fonts/SFUIDisplay-Bold.otf b/fonts/SFUIDisplay-Bold.otf new file mode 100644 index 0000000000000000000000000000000000000000..87827d5392a3bc4a9e382cff30aa21c75b5b38d4 GIT binary patch literal 154912 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 literal 0 HcmV?d00001 diff --git a/fonts/SFUIDisplay-Light.otf b/fonts/SFUIDisplay-Light.otf new file mode 100644 index 0000000000000000000000000000000000000000..b1879c0380ccc559565438ca0aca93d90624b0ff GIT binary patch literal 149000 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

JZeUwC|I{SJdQ9xQ!9| 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ĸhIz@;0ugj;9!nl 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 u_*qMiV8Q^JJ96bqGiG+images/titlebarGradient.jpg images/titlebarLogo.png images/menuArrow.png + fonts/SFUIDisplay-Medium.otf + fonts/SFUIDisplay-Regular.otf + fonts/SFUIDisplay-Light.otf + fonts/SFUIDisplay-Bold.otf From 50eafab5dc84487ac8ff4c962a96d1d3ecfdbc84 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 16 Nov 2017 19:00:47 +0100 Subject: [PATCH 021/126] Have the menu buttons make use of the new font --- components/MenuButton.qml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 600bcd51..928848a6 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -60,6 +60,15 @@ Rectangle { property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 52 * scaleRatio ) : 0 + // Load custom fonts @TODO: should probably do this somewhere else + Text { + FontLoader { id: sfuid; source: "../fonts/SFUIDisplay-Bold.otf"; } + FontLoader { source: "../fonts/SFUIDisplay-Medium.otf"; } + FontLoader { source: "../fonts/SFUIDisplay-Light.otf"; } + FontLoader { source: "../fonts/SFUIDisplay-Regular.otf"; } + font.family: "SFUIDisplay"; + } + // Button gradient whilst checked // @TODO: replace by .png - gradient not available in 2d renderer LinearGradient { @@ -106,7 +115,7 @@ Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.left: parent.right anchors.leftMargin: 8 * scaleRatio - font.family: "Arial" + font.family: "SFUIDisplay" font.bold: true font.pixelSize: 16 * scaleRatio color: "#FFFFFF" From 9819e63fccd290f9804c660bdc0617c026eb2ec7 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 16 Nov 2017 22:05:14 +0100 Subject: [PATCH 022/126] Singleton for future style definition. For now, put the fonts there --- components/MenuButton.qml | 14 +++----------- components/Style.qml | 10 ++++++++++ components/qmldir | 1 + qml.qrc | 2 ++ 4 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 components/Style.qml create mode 100644 components/qmldir diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 928848a6..319170b4 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -26,8 +26,9 @@ // 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 2.5 import QtGraphicalEffects 1.0 +import "." 1.0 Rectangle { id: button @@ -60,15 +61,6 @@ Rectangle { property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 52 * scaleRatio ) : 0 - // Load custom fonts @TODO: should probably do this somewhere else - Text { - FontLoader { id: sfuid; source: "../fonts/SFUIDisplay-Bold.otf"; } - FontLoader { source: "../fonts/SFUIDisplay-Medium.otf"; } - FontLoader { source: "../fonts/SFUIDisplay-Light.otf"; } - FontLoader { source: "../fonts/SFUIDisplay-Regular.otf"; } - font.family: "SFUIDisplay"; - } - // Button gradient whilst checked // @TODO: replace by .png - gradient not available in 2d renderer LinearGradient { @@ -115,7 +107,7 @@ Rectangle { anchors.verticalCenter: parent.verticalCenter anchors.left: parent.right anchors.leftMargin: 8 * scaleRatio - font.family: "SFUIDisplay" + font.family: Style.fontMedium.name font.bold: true font.pixelSize: 16 * scaleRatio color: "#FFFFFF" diff --git a/components/Style.qml b/components/Style.qml new file mode 100644 index 00000000..cab0e062 --- /dev/null +++ b/components/Style.qml @@ -0,0 +1,10 @@ +pragma Singleton + +import QtQuick 2.5 + +QtObject { + property QtObject fontMedium: FontLoader { id: _fontMedium; source: "qrc:/fonts/SFUIDisplay-Medium.otf"; } + property QtObject fontBold: FontLoader { id: _fontBold; source: "qrc:/fonts/SFUIDisplay-Bold.otf"; } + property QtObject fontLight: FontLoader { id: _fontLight; source: "qrc:/fonts/SFUIDisplay-Light.otf"; } + property QtObject fontRegular: FontLoader { id: _fontRegular; source: "qrc:/fonts/SFUIDisplay-Regular.otf"; } +} diff --git a/components/qmldir b/components/qmldir new file mode 100644 index 00000000..81984227 --- /dev/null +++ b/components/qmldir @@ -0,0 +1 @@ +singleton Style 1.0 Style.qml diff --git a/qml.qrc b/qml.qrc index f8d739be..7f5b673c 100644 --- a/qml.qrc +++ b/qml.qrc @@ -182,5 +182,7 @@ fonts/SFUIDisplay-Regular.otf fonts/SFUIDisplay-Light.otf fonts/SFUIDisplay-Bold.otf + components/Style.qml + components/qmldir From 9462899e97bb9057bb0205bb33413710d616a38c Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 18 Nov 2017 16:18:05 +0100 Subject: [PATCH 023/126] Position testnet label --- LeftPanel.qml | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index faf55a6d..6122fae3 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -119,6 +119,31 @@ Rectangle { fillMode: Image.PreserveAspectFit source: "images/card-background.png" } + + Text { + id: testnetLabel + visible: persistentSettings.testnet + text: qsTr("Testnet") + translationManager.emptyString + anchors.top: parent.top + anchors.topMargin: 8 + anchors.left: parent.left + anchors.leftMargin: 190 + font.bold: true + color: "white" + } + + // @TODO: implement + // Text { + // id: viewOnlyLabel + // visible: viewOnly + // text: qsTr("View Only") + translationManager.emptyString + // anchors.top: logo.bottom + // anchors.topMargin: 5 + // anchors.left: parent.left + // anchors.leftMargin: 50 + // font.bold: true + // color: "blue" + // } } Item { @@ -170,29 +195,7 @@ Rectangle { return defaultSize; } } - Text { - id: testnetLabel - visible: persistentSettings.testnet - text: qsTr("Testnet") + translationManager.emptyString - anchors.top: unlockedBalanceText.bottom - anchors.topMargin: 5 - anchors.left: parent.left - anchors.leftMargin: 50 - font.bold: true - color: "red" - } -// @TODO: implement -// Text { -// id: viewOnlyLabel -// visible: viewOnly -// text: qsTr("View Only") + translationManager.emptyString -// anchors.top: logo.bottom -// anchors.topMargin: 5 -// anchors.left: parent.left -// anchors.leftMargin: 50 -// font.bold: true -// color: "blue" -// } + Label { id: unlockedBalanceLabel text: qsTr("Unlocked balance") + translationManager.emptyString From 5360d2c231941076a1072b6628ce1cc6e16ddf90 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 18 Nov 2017 16:21:32 +0100 Subject: [PATCH 024/126] Smaller menubutton height for small screens --- components/MenuButton.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 319170b4..4321d248 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -59,7 +59,7 @@ Rectangle { color: "black" property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 - height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 52 * scaleRatio ) : 0 + height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 38 * scaleRatio ) : 0 // Button gradient whilst checked // @TODO: replace by .png - gradient not available in 2d renderer From e7eb3bdfefd723f3737c9e4318ec2fca06c696b4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 19 Nov 2017 21:11:14 +0100 Subject: [PATCH 025/126] Re-do LineEdit/Input - decoupled placeholder text --- components/Input.qml | 22 ++++++++--------- components/LineEdit.qml | 55 ++++++++++++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/components/Input.qml b/components/Input.qml index 076fd9bc..a660ca84 100644 --- a/components/Input.qml +++ b/components/Input.qml @@ -26,21 +26,21 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import QtQuick.Controls 1.2 -import QtQuick.Controls.Styles 1.2 -import QtQuick 2.2 +import QtQuick.Controls 2.2 +import QtQuick 2.10 +import "." 1.0 TextField { - font.family: "Arial" + font.family: Style.fontRegular.name + font.pixelSize: 22 horizontalAlignment: TextInput.AlignLeft selectByMouse: true - style: TextFieldStyle { - textColor: "#3F3F3F" - placeholderTextColor: "#BABABA" + color: "white" - background: Rectangle { - border.width: 0 - color: "transparent" - } + background: Rectangle { + color: "transparent" + border.width: 1 + border.color: Qt.rgba(1, 1, 1, 0.25) + radius: 4 } } diff --git a/components/LineEdit.qml b/components/LineEdit.qml index c91073a7..0cd71978 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -27,10 +27,11 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 +import "." 1.0 Item { id: item - property alias placeholderText: input.placeholderText + property alias placeholderText: placeholderLabel.text property alias text: input.text property alias validator: input.validator property alias readOnly : input.readOnly @@ -43,21 +44,47 @@ Item { signal accepted(); signal textUpdated(); - height: 37 * scaleRatio + height: 48 * scaleRatio - function getColor(error) { - if (error) - return "#FFDDDD" - else - return "#FFFFFF" + onTextUpdated: { + // check to remove placeholder text when there is content + if(item.isEmpty()){ + placeholderLabel.visible = true + } else { + placeholderLabel.visible = false + } } - Rectangle { - visible: showBorder - anchors.fill: parent - anchors.bottomMargin: 1 * scaleRatio - color: "#DBDBDB" - //radius: 4 + function isEmpty(){ + var val = input.text; + if(val === "") { + return true; + } + else { + return false; + } + } + + function getColor(error) { + // @TODO: replace/remove this (implement as ternary?) + if (error) + return Style.inputBoxBackground + else + return Style.inputBoxBackground + } + + Text { + id: placeholderLabel + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 10 + opacity: 0.25 + font.family: Style.fontRegular.name + font.pixelSize: 20 * scaleRatio + color: "#FFFFFF" + text: "" + visible: item.setPlaceholder() ? false : true + z: 3 } Rectangle { @@ -70,8 +97,6 @@ Item { Input { id: input anchors.fill: parent - anchors.leftMargin: 4 * scaleRatio - anchors.rightMargin: 30 * scaleRatio font.pixelSize: parent.fontSize onEditingFinished: item.editingFinished() onAccepted: item.accepted(); From f15d6f5197c07cb25e97f7fb04d54c5775646224 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 19 Nov 2017 21:14:05 +0100 Subject: [PATCH 026/126] Added some styles, changed some margins, testing with the new LineEdit --- LeftPanel.qml | 2 +- MiddlePanel.qml | 6 ++-- components/Style.qml | 4 +++ pages/Receive.qml | 5 ++- pages/Transfer.qml | 82 ++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 88 insertions(+), 11 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index 6122fae3..4679f1b0 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -127,7 +127,7 @@ Rectangle { anchors.top: parent.top anchors.topMargin: 8 anchors.left: parent.left - anchors.leftMargin: 190 + anchors.leftMargin: 184 font.bold: true color: "white" } diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 6cac3f10..0f816704 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -69,7 +69,7 @@ Rectangle { signal getProofClicked(string txid, string address, string message); signal checkProofClicked(string txid, string address, string message, string signature); - color: "#F0EEEE" + color: "black" onCurrentViewChanged: { if (previousView) { @@ -163,8 +163,8 @@ Rectangle { ColumnLayout { anchors.fill: parent - anchors.margins: 2 - anchors.topMargin: appWindow.persistentSettings.customDecorations ? 30 : 0 + anchors.margins: 18 + anchors.topMargin: appWindow.persistentSettings.customDecorations ? 50 : 0 spacing: 0 Flickable { diff --git a/components/Style.qml b/components/Style.qml index cab0e062..c1bc3938 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -7,4 +7,8 @@ QtObject { property QtObject fontBold: FontLoader { id: _fontBold; source: "qrc:/fonts/SFUIDisplay-Bold.otf"; } property QtObject fontLight: FontLoader { id: _fontLight; source: "qrc:/fonts/SFUIDisplay-Light.otf"; } property QtObject fontRegular: FontLoader { id: _fontRegular; source: "qrc:/fonts/SFUIDisplay-Regular.otf"; } + + property string inputBoxBackground: "black" + property string inputBoxBackgroundError: "#FFDDDD" + property string inputBoxColor: "white" } diff --git a/pages/Receive.qml b/pages/Receive.qml index f839741e..2b070c9f 100644 --- a/pages/Receive.qml +++ b/pages/Receive.qml @@ -44,6 +44,9 @@ import moneroComponents.SubaddressModel 1.0 Rectangle { id: pageReceive color: "#F0EEEE" + property alias addressText : addressLine.text + property alias paymentIdText : paymentIdLine.text + property alias integratedAddressText : integratedAddressLine.text property var model property var current_address property alias addressText : pageReceive.current_address @@ -240,7 +243,7 @@ Rectangle { LineEdit { id: amountLine - fontSize: mainLayout.lineEditFontSize +// fontSize: mainLayout.lineEditFontSize placeholderText: qsTr("Amount to receive") + translationManager.emptyString readOnly: false width: mainLayout.editWidth diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 8e6daebf..10aa5960 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -32,6 +32,7 @@ import QtQuick.Dialogs 1.2 import moneroComponents.PendingTransaction 1.0 import "../components" import moneroComponents.Wallet 1.0 +import "." 1.0 Rectangle { @@ -40,11 +41,8 @@ Rectangle { int priority, string description) signal sweepUnmixableClicked() - color: "#F0EEEE" - property string startLinkText: " (" + - qsTr("Start daemon") + - ")" + - translationManager.emptyString + color: "black" + property string startLinkText: qsTr(" (Start daemon)") + translationManager.emptyString property bool showAdvanced: false function scaleValueToMixinCount(scaleValue) { @@ -118,10 +116,23 @@ Rectangle { anchors.margins: 17 * scaleRatio spacing: 0 + RowLayout{ + Layout.fillWidth: true + Layout.bottomMargin: 20 + + Text { + id: panelHeader + font.family: Style.fontMedium.name + font.pixelSize: 32 * scaleRatio + color: "#FFFFFF" + text: "Send" + height: 150 + } + } + GridLayout { columns: (isMobile)? 1 : 2 Layout.fillWidth: true - ColumnLayout { Layout.fillWidth: true Label { @@ -212,6 +223,65 @@ Rectangle { z: parent.z + 1 } + ColumnLayout { + id: amountRowx + Label { + id: amountLabelx + text: qsTr("Amount") + translationManager.emptyString + width: mainLayout.labelWidth + } + + // this LineEdit is for testing purposes + LineEdit { + id: amountLinex + fontSize: mainLayout.lineEditFontSize + placeholderText: qsTr("Amount to receive") + translationManager.emptyString + readOnly: false + width: mainLayout.editWidth + Layout.fillWidth: true +// validator: DoubleValidator { +// bottom: 0.0 +// top: 18446744.073709551615 +// decimals: 12 +// notation: DoubleValidator.StandardNotation +// locale: "C" +// } + + Rectangle{ + color: "#808080" + border.color: "black" + height: 20 + width: 40 + radius: 3 + + anchors.top: parent.top + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.topMargin: 8 + + Text { + id: xee + font.family: Style.fontBold.name + font.pixelSize: 16 * scaleRatio + color: "#FFFFFF" + text: "Send" + anchors.top: parent.top + 2 + anchors.left: parent.left + 6 + } + } + +// IconButton { +// imageSource: "../images/copyToClipboard.png" +// onClicked: { +// if (integratedAddressLine.text.length > 0) { +// clipboard.setText(integratedAddressLine.text) +// appWindow.showStatusMessage(qsTr("Integrated address copied to clipboard"),3) +// } +// } +// } + } + } + ColumnLayout { Layout.fillWidth: true Label { From f6f26af7cbe231505b2494f6fa538f026b7fa584 Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Mon, 20 Nov 2017 20:16:53 -0500 Subject: [PATCH 027/126] use PNG for menuButton gradiency --- components/MenuButton.qml | 24 +++++++++++------------- images/menuButtonGradient.png | Bin 0 -> 3994 bytes qml.qrc | 1 + 3 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 images/menuButtonGradient.png diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 4321d248..afc2421a 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -61,19 +61,6 @@ Rectangle { property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 38 * scaleRatio ) : 0 - // Button gradient whilst checked - // @TODO: replace by .png - gradient not available in 2d renderer - LinearGradient { - visible: button.checked ? true : false - anchors.fill: parent - start: Qt.point(0, 0) - end: Qt.point(300, 0) - gradient: Gradient { - GradientStop { position: 1.0; color: "#333333" } - GradientStop { position: 0.0; color: "black" } - } - } - // button decorations that are subject to leftMargin offsets Rectangle { anchors.left: parent.left @@ -114,6 +101,17 @@ Rectangle { } } + // button gradient while checked + Image { + width: 160 + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.leftMargin: parent.getOffset() + source: "../images/menuButtonGradient.png" + visible: button.checked + } + // menu button right arrow Image { anchors.verticalCenter: parent.verticalCenter diff --git a/images/menuButtonGradient.png b/images/menuButtonGradient.png new file mode 100644 index 0000000000000000000000000000000000000000..616f72c1afff441de221cae0c78e1761d23d90da GIT binary patch literal 3994 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 ACIA2c literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index 7f5b673c..d7ea0e1d 100644 --- a/qml.qrc +++ b/qml.qrc @@ -178,6 +178,7 @@ images/titlebarGradient.jpg images/titlebarLogo.png images/menuArrow.png + images/menuButtonGradient.png fonts/SFUIDisplay-Medium.otf fonts/SFUIDisplay-Regular.otf fonts/SFUIDisplay-Light.otf From af7ad482c2dc64d8f9bf5f093d61eee88b4818e7 Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Mon, 20 Nov 2017 21:11:52 -0500 Subject: [PATCH 028/126] Move button gradiency Moves the block of code that deals with the gradiency so that it is placed underneath labels and other images rather than on top --- components/MenuButton.qml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index afc2421a..38b83da9 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -61,6 +61,17 @@ Rectangle { property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 38 * scaleRatio ) : 0 + // button gradient while checked + Image { + width: 260 + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.leftMargin: parent.getOffset() + source: "../images/menuButtonGradient.png" + visible: button.checked + } + // button decorations that are subject to leftMargin offsets Rectangle { anchors.left: parent.left @@ -101,17 +112,6 @@ Rectangle { } } - // button gradient while checked - Image { - width: 160 - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 0 - anchors.leftMargin: parent.getOffset() - source: "../images/menuButtonGradient.png" - visible: button.checked - } - // menu button right arrow Image { anchors.verticalCenter: parent.verticalCenter From 2629c767a84a96733faa0596f9141ad3d247b4f1 Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Tue, 21 Nov 2017 08:51:48 -0500 Subject: [PATCH 029/126] adjust images size --- components/MenuButton.qml | 3 ++- images/menuButtonGradient.png | Bin 3994 -> 244 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 38b83da9..560d0fee 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -63,10 +63,11 @@ Rectangle { // button gradient while checked Image { + height: 40 width: 260 anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - anchors.rightMargin: 0 + anchors.rightMargin: -20 anchors.leftMargin: parent.getOffset() source: "../images/menuButtonGradient.png" visible: button.checked diff --git a/images/menuButtonGradient.png b/images/menuButtonGradient.png index 616f72c1afff441de221cae0c78e1761d23d90da..3ac95cb88c089aa7f63b8b25a5eb78138a0b73c6 100644 GIT binary patch delta 200 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 Date: Tue, 21 Nov 2017 08:23:31 -0600 Subject: [PATCH 030/126] Adjust gradient image height --- components/MenuButton.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 560d0fee..0944d596 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -63,7 +63,7 @@ Rectangle { // button gradient while checked Image { - height: 40 + height: parent.height width: 260 anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right From e62fab767ad1f4907d56ecd9b94780a97966703f Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 21 Nov 2017 22:11:41 +0100 Subject: [PATCH 031/126] Added inlineButton for lineEdit and worked on network status progress bar + text --- LeftPanel.qml | 10 ++-- components/InlineButton.qml | 86 +++++++++++++++++++++++++++++++ components/LineEdit.qml | 6 +++ components/NetworkStatusItem.qml | 49 +++++++++++------- components/ProgressBar.qml | 44 +++++++++++++--- images/lightning.png | Bin 0 -> 552 bytes pages/Transfer.qml | 43 +--------------- qml.qrc | 2 + 8 files changed, 170 insertions(+), 70 deletions(-) create mode 100644 components/InlineButton.qml create mode 100644 images/lightning.png diff --git a/LeftPanel.qml b/LeftPanel.qml index 4679f1b0..de8777d0 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -127,9 +127,11 @@ Rectangle { anchors.top: parent.top anchors.topMargin: 8 anchors.left: parent.left - anchors.leftMargin: 184 + anchors.leftMargin: 192 font.bold: true + font.pixelSize: 12 color: "white" + opacity: 0.6 } // @TODO: implement @@ -245,7 +247,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.top: (isMobile)? parent.top : column1.bottom anchors.topMargin: (isMobile)? 0 : 32 - color: "#1C1C1C" + color: "black" Flickable { @@ -572,7 +574,7 @@ Rectangle { anchors.right: parent.right anchors.bottom: (progressBar.visible)? progressBar.top : parent.bottom; connected: Wallet.ConnectionStatus_Disconnected - height: 58 * scaleRatio + height: 40 * scaleRatio } ProgressBar { @@ -590,9 +592,9 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom - height: 35 * scaleRatio syncType: qsTr("Daemon") visible: networkStatus.connected + height: 62 * scaleRatio } } // menuRect diff --git a/components/InlineButton.qml b/components/InlineButton.qml new file mode 100644 index 00000000..9ba7f716 --- /dev/null +++ b/components/InlineButton.qml @@ -0,0 +1,86 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 + +Item { + id: inlineButton + height: 32 * scaleRatio + property string shadowPressedColor: "#B32D00" + property string shadowReleasedColor: "#FF4304" + property string pressedColor: "#FF4304" + property string releasedColor: "#FF6C3C" + property string icon: "" + property string textColor: "#FFFFFF" + property int fontSize: 12 * scaleRatio + property alias text: inlineText.text + signal clicked() + + anchors.top: parent.top + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.topMargin: 8 + + function onClicked(){} + + function doClick() { + // Android workaround + releaseFocus(); + clicked(); + } + + Rectangle{ + color: "#808080" + border.color: "black" + height: 32 + width: inlineText.width + 20 + radius: 4 + + anchors.top: parent.top + anchors.right: parent.right + + Text { + id: inlineText + font.family: Style.fontBold.name + font.pixelSize: 16 * scaleRatio + color: "#FFFFFF" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + + MouseArea { + id: buttonArea + anchors.fill: parent + onClicked: doClick() + } + } + + Keys.onSpacePressed: doClick() + Keys.onReturnPressed: doClick() +} diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 0cd71978..8e9e353e 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -37,6 +37,7 @@ Item { property alias readOnly : input.readOnly property alias cursorPosition: input.cursorPosition property alias echoMode: input.echoMode + property alias inlineButtonText: inlineButtonId.text property int fontSize: 18 * scaleRatio property bool showBorder: true property bool error: false @@ -102,4 +103,9 @@ Item { onAccepted: item.accepted(); onTextChanged: item.textUpdated() } + + InlineButton { + id: inlineButtonId + visible: item.inlineButtonText ? true : false + } } diff --git a/components/NetworkStatusItem.qml b/components/NetworkStatusItem.qml index 440d1bb9..c7950636 100644 --- a/components/NetworkStatusItem.qml +++ b/components/NetworkStatusItem.qml @@ -28,21 +28,23 @@ import QtQuick 2.0 import moneroComponents.Wallet 1.0 +import "." 1.0 Rectangle { id: item + color: "transparent" property var connected: Wallet.ConnectionStatus_Disconnected function getConnectionStatusImage(status) { if (status == Wallet.ConnectionStatus_Connected) - return "../images/statusConnected.png" + return "../images/lightning.png" else return "../images/statusDisconnected.png" } function getConnectionStatusColor(status) { if (status == Wallet.ConnectionStatus_Connected) - return "#FF6C3B" + return "white" else return "#AAAAAA" } @@ -62,39 +64,50 @@ Rectangle { return qsTr("Invalid connection status") } - - color: "#1C1C1C" Row { - height: 60 * scaleRatio + height: 40 * scaleRatio + Item { id: iconItem - anchors.bottom: parent.bottom - width: 50 * scaleRatio - height: 50 * scaleRatio + anchors.top: parent.top + width: 40 * scaleRatio + height: 40 * scaleRatio Image { - anchors.centerIn: parent + anchors.top: parent.top + anchors.topMargin: 6 + anchors.right: parent.right + anchors.rightMargin: 11 source: getConnectionStatusImage(item.connected) } } - Column { - anchors.bottom: parent.bottom - height: 53 * scaleRatio - spacing: 3 * scaleRatio + Item { + anchors.top: parent.top + anchors.left: iconItem.right + height: 40 * scaleRatio + width: 260 * scaleRatio Text { + id: statusText anchors.left: parent.left - font.family: "Arial" - font.pixelSize: 12 * scaleRatio - color: "#545454" + anchors.top: parent.top + anchors.topMargin: 0 + font.family: Style.fontMedium.name + font.bold: true + font.pixelSize: 13 * scaleRatio + color: "white" + opacity: 0.5 text: qsTr("Network status") + translationManager.emptyString } Text { + id: statusTextVal anchors.left: parent.left - font.family: "Arial" - font.pixelSize: 18 * scaleRatio + anchors.top: parent.top + anchors.topMargin: 14 + font.family: Style.fontMedium.name + font.pixelSize: 20 * scaleRatio color: getConnectionStatusColor(item.connected) text: getConnectionStatusString(item.connected) + translationManager.emptyString } diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml index 04b92b3a..e6e571e0 100644 --- a/components/ProgressBar.qml +++ b/components/ProgressBar.qml @@ -28,13 +28,15 @@ import QtQuick 2.0 import moneroComponents.Wallet 1.0 +import "." 1.0 Rectangle { id: item property int fillLevel: 0 property string syncType // Wallet or Daemon property string syncText: qsTr("%1 blocks remaining: ").arg(syncType) - color: "#1C1C1C" + visible: false + color: "transparent" function updateProgress(currentBlock,targetBlock, blocksToSync, statusTxt){ if(targetBlock > 0) { @@ -50,29 +52,57 @@ Rectangle { } Item { + anchors.topMargin: 10 * scaleRatio anchors.leftMargin: 15 * scaleRatio anchors.rightMargin: 15 * scaleRatio anchors.fill: parent + + Text { + id: progressText + anchors.top: item.top + anchors.topMargin: 6 + font.family: Style.fontMedium.name + font.pixelSize: 13 * scaleRatio + font.bold: true + color: "white" + text: qsTr("Synchronizing blocks") + height:18 * scaleRatio + } + + Text { + id: progressTextValue + anchors.top: item.top + anchors.topMargin: 6 + anchors.right: parent.right + font.family: Style.fontMedium.name + font.pixelSize: 13 * scaleRatio + font.bold: true + color: "white" + height:18 * scaleRatio + } + + Rectangle { id: bar anchors.left: parent.left anchors.right: parent.right - anchors.top: parent.top - height: 22 * scaleRatio - radius: 2 * scaleRatio - color: "#FFFFFF" + anchors.top: progressText.bottom + anchors.topMargin: 4 + height: 8 * scaleRatio + radius: 8 * scaleRatio + color: "#333333" // progressbar bg Rectangle { id: fillRect anchors.top: parent.top anchors.bottom: parent.bottom anchors.left: parent.left - anchors.margins: 2 * scaleRatio height: bar.height property int maxWidth: parent.width - 4 * scaleRatio width: (maxWidth * fillLevel) / 100 + radius: 8 color: { - if(item.fillLevel < 99 ) return "#FF6C3C" + if(item.fillLevel < 99 ) return "#FA6800" //if(item.fillLevel < 99) return "#FFE00A" return "#36B25C" } diff --git a/images/lightning.png b/images/lightning.png new file mode 100644 index 0000000000000000000000000000000000000000..36d55fb80c9396fa29cb19c0dae8ada2712f69fb GIT binary patch literal 552 zcmV+@0@wYCP)Px$;z>k7R5%fRQawvtK@>grz1d()Oer=N!V*vjMiJ7AKOp6jN)QBh-4%a;2q~-r z63K@qg(A4QufvtVI!CnUG9?X><`oP>(0E7lj72QN6=;h&3spl{2vSDb_|p z1N;74=)e-n;|9M>FGge)za5v3Rg1QUAz$ox?pRf^!#P8;yhOfA>SPjvW>GF*9g8yyTS;RD6-2 zrv_WaQ<9^uz*ZJz9Y1`LpQnaqyVDNEN1V#GF9`F_3GAQZKPJXpC 0) { -// clipboard.setText(integratedAddressLine.text) -// appWindow.showStatusMessage(qsTr("Integrated address copied to clipboard"),3) -// } -// } -// } + inlineButtonText: "Testy" } } diff --git a/qml.qrc b/qml.qrc index d7ea0e1d..c8725fd1 100644 --- a/qml.qrc +++ b/qml.qrc @@ -185,5 +185,7 @@ fonts/SFUIDisplay-Bold.otf components/Style.qml components/qmldir + components/InlineButton.qml + images/lightning.png From 9f0874ee064d586ed467ea94eb21d8bb09626d3f Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 21 Nov 2017 23:51:06 +0100 Subject: [PATCH 032/126] Removing unused import --- components/MenuButton.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 0944d596..555a03b9 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -27,7 +27,6 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.5 -import QtGraphicalEffects 1.0 import "." 1.0 Rectangle { From 8fbd8b99d7d04299d981b7f29256aeddfb7dec7e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 22 Nov 2017 00:14:38 +0100 Subject: [PATCH 033/126] leftPanel gradient background --- LeftPanel.qml | 31 ++++++++++++++----------------- components/MenuButton.qml | 2 +- images/balanceGradient.jpg | Bin 4201 -> 0 bytes images/leftPanelBg.jpg | Bin 0 -> 4637 bytes qml.qrc | 2 +- 5 files changed, 16 insertions(+), 19 deletions(-) delete mode 100644 images/balanceGradient.jpg create mode 100644 images/leftPanelBg.jpg diff --git a/LeftPanel.qml b/LeftPanel.qml index de8777d0..fd9b880c 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -74,13 +74,23 @@ Rectangle { } width: (isMobile)? appWindow.width : 300 - color: "black" + color: "transparent" anchors.bottom: parent.bottom anchors.top: parent.top + Image { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: panel.height + source: "images/leftPanelBg.jpg" + z: 1 + } + // card with monero logo Column { visible: true + z: 2 id: column1 height: 200 anchors.left: parent.left @@ -89,20 +99,6 @@ Rectangle { // @TODO: customDecorations? anchors.topMargin: (persistentSettings.customDecorations)? 50 : 0 - Row { - Item { - x: 0 - y: 0 - width: 300 - height: 232 - - Image { - width: 300; height: 232 - source: "images/balanceGradient.jpg" - } - } - } - Row { visible: true Item { @@ -115,7 +111,7 @@ Rectangle { width: 50 * scaleRatio Image { - width: 259; height:170 + width: 259; height: 170 fillMode: Image.PreserveAspectFit source: "images/card-background.png" } @@ -242,12 +238,13 @@ Rectangle { Rectangle { id: menuRect + z: 2 anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.top: (isMobile)? parent.top : column1.bottom anchors.topMargin: (isMobile)? 0 : 32 - color: "black" + color: "transparent" Flickable { diff --git a/components/MenuButton.qml b/components/MenuButton.qml index 555a03b9..f3ba56f6 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -56,7 +56,7 @@ Rectangle { return offset } - color: "black" + color: "transparent" property bool present: !under || under.checked || checked || under.numSelectedChildren > 0 height: present ? ((appWindow.height >= 800) ? 44 * scaleRatio : 38 * scaleRatio ) : 0 diff --git a/images/balanceGradient.jpg b/images/balanceGradient.jpg deleted file mode 100644 index 24ae02cca0ae9e8c48b410ce4e77b4eca48fdf73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4201 zcmb_fNl+6(6z!QwG9fHxFoEbzP!ukfxS(DvK~T8?CP6K0O2DiTQZO=@W$xL?>z)%b|)6gG;0Pu(}V(j}Ej2vrX0B?@4 zL^6P7IrS=fz!{7tdC>}3hT~WRYvMU{VM`d66AZvOD|W%k9Mkm83B?t*)Y^L9?nzI) zm)rGbVO+tN*?TI-=433&JJ!%zSaN^ys=3F{U0V{ruBh}u_pmvsD#GHJQC*jr)!63h zan76hb>!Q_-qG({_8vTOzP+>W?T@WxhfZF&{;2=m&$QLkQf_t5MxtuMQv)m=Zo!L*PFz2dv3v=v4yi2WmLu;%bU|s*m|EY>0Ug%sw#fn zag-g$jHD%*Gv^kSI@7+MyY^sSa?i-O>bl0ZP|8`ZAZa3J3S~G1qBxnR09JsvjwX-0 zpt*BX&29T`ds)h7r#JW@aC>!Fc_Z*ZbBkFQ;d3>1S<0))V3%XaG)^A47` zM6&}$hUe`X^GB{)7h$&++uMYvF&_5S0&QMkPx#n0J(@c=%8G^X?$u*^upvrXll8!2 z_hGQzy6}8HqG9WNCc=I!Him}6TXHB#4^3Pm93Ws*q@!W0e1`lz`kO#RC(iiHJ8Ifh zPK8}WY+V9_*fg~RS!;pa2%G%sq?&-Q`dVO*giSGqDuF8A)D2#RYzypFuqnnMH35nq zC=o7?8}|9JCt(b7gOTEDf&D>ja!nHpm8^%<2M4BvO)FHz-+{A1>NFEhFKGkn-)i1U z7bDdjF}?T=sDJCRNp>e<<2Q(Yf2)r_JdFvLsTlOPsxpYSph>5*yQube$Z4p1)&IXq z(&;v!{*B4^I2BFGnMMzdzg4FlrA+bC>GZ((+v^`TG&KAff?4w6k1b z*pWx(Fp?X(K{*=+!oika)z6YL9MP%eO=v!mc`Lmt#GfI;P2xP2{2eAXrBLPcsynG% zA(FoX*u?Mx#YBn=tB2IT1K65bQIiwpb^_m7r2ehJCKaMmti;$bc~SfwEOPQ$><@#~ KzjbfVDx4T4`<7znqG zPAHwukQ`mhtq+d1SKohlwefKL)KJ&rOspfI_G!c49!#wfbZ3 z$;Zl(n!hkQ<$lJEQ)=v9|S)!w}$XY+qEdh?&4pS6@eLSlg8FZv{<%C7^ep ziq11R5CN;aC``}FVyIb=#U4?RCE12R6s?c~DWpIuDNvFWC`AgCCI!ln0%b{o{-2{A znp70wbJTkm`&?X@Q+wr}Gs1G|jo7+^X|kq(B)` zpsa4kOK6LwTOkEfblJM)?206is!L?{UXm0jrSoKFlqLnrXcm9?TCBs4-@!#0?rr0B z2Zl<@wXzN_=8ny8ELa3(ttdMV7_RcP5@$8McGD5dZ>&SsNSQ+$o^5vM1X46Rrm=-j zsH8wiO(L_+Q=~v?O|r}9tgrC|%4j^91jcPGg3%_R8pX%8MNFS%UkR+uGlJD l)Ob_TgpK+zZ$swqWxTzwpj58Hghh+r*{3$H_DF%={sEa$lQ{qY literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index c8725fd1..25c50f86 100644 --- a/qml.qrc +++ b/qml.qrc @@ -174,7 +174,6 @@ images/moneroIcon-trans56x56.png images/question.png images/expand.png - images/balanceGradient.jpg images/titlebarGradient.jpg images/titlebarLogo.png images/menuArrow.png @@ -187,5 +186,6 @@ components/qmldir components/InlineButton.qml images/lightning.png + images/leftPanelBg.jpg From bb836dae385e6358283e67af818688a5a6815509 Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Tue, 21 Nov 2017 18:49:34 -0500 Subject: [PATCH 034/126] Use jpg for gradiency --- components/TitleBar.qml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/components/TitleBar.qml b/components/TitleBar.qml index c1cc186f..1c7a61db 100644 --- a/components/TitleBar.qml +++ b/components/TitleBar.qml @@ -51,14 +51,12 @@ Rectangle { height: 50 z: 1 - LinearGradient { - anchors.fill: parent - start: Qt.point(0, 0) - end: Qt.point(parent.width, 0) - gradient: Gradient { - GradientStop { position: 1.0; color: "#1a1a1a" } - GradientStop { position: 0.0; color: "black" } - } + // use jpg for gradiency + Image { + anchors.fill: parent + height: parent.height + width: parent.width + source: "../images/titlebarGradient.jpg" } } From 2e89f86b9fce8c8f1ebff0f0aad53d21303352f1 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 22 Nov 2017 21:48:25 +0100 Subject: [PATCH 035/126] Removing unused import --- components/TitleBar.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/components/TitleBar.qml b/components/TitleBar.qml index 1c7a61db..5fe5ffa5 100644 --- a/components/TitleBar.qml +++ b/components/TitleBar.qml @@ -29,7 +29,6 @@ import QtQuick 2.2 import QtQuick.Window 2.0 import QtQuick.Layouts 1.1 -import QtGraphicalEffects 1.0 Rectangle { id: titleBar From dc445edaae6dd7cb98b5337566aa4a5495e97b6b Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 23 Nov 2017 15:28:52 +0100 Subject: [PATCH 036/126] Hide 'unlocked balance' when no funds are available --- LeftPanel.qml | 4 ++++ main.qml | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/LeftPanel.qml b/LeftPanel.qml index fd9b880c..51d0d70d 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -36,6 +36,8 @@ Rectangle { id: panel property alias unlockedBalanceText: unlockedBalanceText.text + property alias unlockedBalanceVisible: unlockedBalanceText.visible + property alias unlockedBalanceLabelVisible: unlockedBalanceLabel.visible property alias balanceLabelText: balanceLabel.text property alias balanceText: balanceText.text property alias networkStatus : networkStatus @@ -176,6 +178,7 @@ Rectangle { Text { id: unlockedBalanceText + visible: false anchors.left: parent.left anchors.leftMargin: 20 anchors.top: parent.top @@ -196,6 +199,7 @@ Rectangle { Label { id: unlockedBalanceLabel + visible: false text: qsTr("Unlocked balance") + translationManager.emptyString anchors.left: parent.left anchors.leftMargin: 20 diff --git a/main.qml b/main.qml index 3b57a523..d23069d0 100644 --- a/main.qml +++ b/main.qml @@ -381,6 +381,23 @@ ApplicationWindow { function onWalletUpdate() { console.log(">>> wallet updated") updateBalance(); + var unlockedBalance = walletManager.displayAmount(currentWallet.unlockedBalance); + var unlockedBalanceFloat = parseFloat(unlockedBalance); + + if(unlockedBalanceFloat === 0){ + // no available funds; hide the 'unlocked balance' label + leftPanel.unlockedBalanceVisible = false + leftPanel.unlockedBalanceLabelVisible = false + } else { + leftPanel.unlockedBalanceVisible = true + leftPanel.unlockedBalanceLabelVisible = true + leftPanel.unlockedBalanceText.text = unlockedBalance + } + + // showing middlePanel unlockedBalance regardless + middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = unlockedBalance; + middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance); + // Update history if new block found since last update if(foundNewBlock) { foundNewBlock = false; From 82553b0df20e1597fec83b72fcc8799477e762ae Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 23 Nov 2017 15:30:25 +0100 Subject: [PATCH 037/126] NetworkStatus section development --- LeftPanel.qml | 6 +++++- components/NetworkStatusItem.qml | 32 +++++++++++++++---------------- images/lightning-white.png | Bin 0 -> 362 bytes images/moneroIcon-28x28.png | Bin 0 -> 792 bytes qml.qrc | 2 ++ 5 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 images/lightning-white.png create mode 100644 images/moneroIcon-28x28.png diff --git a/LeftPanel.qml b/LeftPanel.qml index 51d0d70d..d9df22da 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -573,9 +573,11 @@ Rectangle { id: networkStatus anchors.left: parent.left anchors.right: parent.right + anchors.leftMargin: 4 + anchors.rightMargin: 4 anchors.bottom: (progressBar.visible)? progressBar.top : parent.bottom; connected: Wallet.ConnectionStatus_Disconnected - height: 40 * scaleRatio + height: progressBar.visible ? 40 * scaleRatio : 60 * scaleRatio } ProgressBar { @@ -595,6 +597,8 @@ Rectangle { anchors.bottom: parent.bottom syncType: qsTr("Daemon") visible: networkStatus.connected + anchors.leftMargin: 4 * scaleRatio + anchors.rightMargin: 4 * scaleRatio height: 62 * scaleRatio } } // menuRect diff --git a/components/NetworkStatusItem.qml b/components/NetworkStatusItem.qml index c7950636..984ffd03 100644 --- a/components/NetworkStatusItem.qml +++ b/components/NetworkStatusItem.qml @@ -35,20 +35,6 @@ Rectangle { color: "transparent" property var connected: Wallet.ConnectionStatus_Disconnected - function getConnectionStatusImage(status) { - if (status == Wallet.ConnectionStatus_Connected) - return "../images/lightning.png" - else - return "../images/statusDisconnected.png" - } - - function getConnectionStatusColor(status) { - if (status == Wallet.ConnectionStatus_Connected) - return "white" - else - return "#AAAAAA" - } - function getConnectionStatusString(status) { if (status == Wallet.ConnectionStatus_Connected) { if(!appWindow.daemonSynced) @@ -72,13 +58,27 @@ Rectangle { anchors.top: parent.top width: 40 * scaleRatio height: 40 * scaleRatio + opacity: { + if(item.connected == Wallet.ConnectionStatus_Connected){ + return 1 + } else { + return 0.5 + } + } Image { anchors.top: parent.top anchors.topMargin: 6 anchors.right: parent.right anchors.rightMargin: 11 - source: getConnectionStatusImage(item.connected) + source: { + if(item.connected == Wallet.ConnectionStatus_Connected){ + return "../images/lightning.png" + } else { + return "../images/lightning-white.png" + } + } + //getConnectionStatusImage(item.connected) } } @@ -108,7 +108,7 @@ Rectangle { anchors.topMargin: 14 font.family: Style.fontMedium.name font.pixelSize: 20 * scaleRatio - color: getConnectionStatusColor(item.connected) + color: "white" text: getConnectionStatusString(item.connected) + translationManager.emptyString } } diff --git a/images/lightning-white.png b/images/lightning-white.png new file mode 100644 index 0000000000000000000000000000000000000000..ae1d6fc9699b0d7caa0658c59db3f4673efe94d3 GIT binary patch literal 362 zcmV-w0hRuVP)okbE5R1~!p;kVg^VYqj9 z4s5aTox{woWCS?I&Z&j#z>ibdu?js0kARw0cybE+7T$F5H_)&Omrmit!pp#)fq#Le z!c7I8JxMj=D_>+;_7bnp0B_E5+SYNp4!((PmKSa%Z5YRSmNW_8#{$+#&zXRJB7Oy$ z0>+7jt>VJdz-;gw8TedYfV&9419Kj38SC3+>jx1Ys4T#JfIoowGQ1M4cdFJ81AL{b z01r9-1Qx3BYOvl-SucLpwNe5+0$;#l3SP_CcT?9pz)*?#2Z)|;^k>S3SpWb407*qo IM6N<$f*A&r*8l(j literal 0 HcmV?d00001 diff --git a/images/moneroIcon-28x28.png b/images/moneroIcon-28x28.png new file mode 100644 index 0000000000000000000000000000000000000000..4ef14fd16dbb56809e70d8838bbdf0cc1a98d223 GIT binary patch literal 792 zcmV+z1LypSP)!plczWGtm|5yzdA9! z!wKmfx$ydyRC}3OU@EIDp>+Ehn6$K}?9jWYd|chF3Di$?W*jzD>E{6Z2G}*MKC?j5Xv8gCK?a|X@u}yR7#fdyxy6Wo2hNlC*QdQ zFoguk?OB@`gEX}?25WwdDs35ujeMKQXJa8j>_=FUMBS(rUPNAw=2lPX&nz%i0JF+c z(a3s+>q4#YBIfc;y- zy)ZWhjY7~f+dNR87z#ln(C#b6E1-Tc_or_+UY)kKwko2fSTdR9>guZ66xAr)R0G%7 z*V*3QzK2?Gzud!?mzT+8GL=2yuPtz`&{YkM$KwFZ%*+%}=@~A(KRrG5#M~vlHrOpE ze%3!8kF&G0bFcmE?2K3}=83s+V%w3ugmba?wJ-{+xnl3NwKYV9>FH@-m~_9!w6y+D zu)vFiExjWbs+t0SxBBYpDk4HhM+dQ3jC49(v9B4JgMqpHV@gCWZ1*7w{PcT#t*oqI zSr(4t)N<-Y0qoqJCA*uOn@PuUe3ulJu%n|R0)aqjb8>cecDLvP9vvO+1kP2p!56UH z0)2;vhs77L+b}62=>}qHU^0&tfi8Lsgxyg!VrF6Yo0J9bpnW2etOHBB%XnNcomponents/InlineButton.qml images/lightning.png images/leftPanelBg.jpg + images/moneroIcon-28x28.png + images/lightning-white.png From 63132dc1db02b099de32ea494696aee5f61e0d1d Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 23 Nov 2017 17:35:46 +0100 Subject: [PATCH 038/126] Keeping the progressbar color orange --- components/ProgressBar.qml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml index e6e571e0..4b415051 100644 --- a/components/ProgressBar.qml +++ b/components/ProgressBar.qml @@ -101,12 +101,8 @@ Rectangle { property int maxWidth: parent.width - 4 * scaleRatio width: (maxWidth * fillLevel) / 100 radius: 8 - color: { - if(item.fillLevel < 99 ) return "#FA6800" - //if(item.fillLevel < 99) return "#FFE00A" - return "#36B25C" - } - + // could change color based on progressbar status; if(item.fillLevel < 99 ) + color: "#FA6800" } Rectangle { From 36ac2ee86dd159ce5c78381104cef1401377dcfe Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 23 Nov 2017 19:29:25 +0100 Subject: [PATCH 039/126] Inline button/icon for input boxes --- components/InlineButton.qml | 4 +++- components/Input.qml | 3 --- components/LineEdit.qml | 24 +++++++++++++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/components/InlineButton.qml b/components/InlineButton.qml index 9ba7f716..da8120c3 100644 --- a/components/InlineButton.qml +++ b/components/InlineButton.qml @@ -47,7 +47,9 @@ Item { anchors.rightMargin: 8 anchors.topMargin: 8 - function onClicked(){} + function onClicked(){ + console.log("debug click"); + } function doClick() { // Android workaround diff --git a/components/Input.qml b/components/Input.qml index a660ca84..b7e39eb2 100644 --- a/components/Input.qml +++ b/components/Input.qml @@ -39,8 +39,5 @@ TextField { background: Rectangle { color: "transparent" - border.width: 1 - border.color: Qt.rgba(1, 1, 1, 0.25) - radius: 4 } } diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 8e9e353e..964af52f 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -38,6 +38,7 @@ Item { property alias cursorPosition: input.cursorPosition property alias echoMode: input.echoMode property alias inlineButtonText: inlineButtonId.text + property alias inlineIcon: inlineIcon.visible property int fontSize: 18 * scaleRatio property bool showBorder: true property bool error: false @@ -78,7 +79,7 @@ Item { id: placeholderLabel anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 10 + anchors.leftMargin: inlineIcon.visible ? 50 : 10 opacity: 0.25 font.family: Style.fontRegular.name font.pixelSize: 20 * scaleRatio @@ -95,9 +96,30 @@ Item { //radius: 4 } + Rectangle { + color: "transparent" + border.width: 1 + border.color: Qt.rgba(1, 1, 1, 0.25) + radius: 4 + anchors.fill: parent + } + + Image { + id: inlineIcon + width: 28 * scaleRatio + height: 28 * scaleRatio + anchors.top: parent.top + anchors.topMargin: 10 * scaleRatio + anchors.left: parent.left + anchors.leftMargin: 12 * scaleRatio + source: "../images/moneroIcon-28x28.png" + visible: false + } + Input { id: input anchors.fill: parent + anchors.leftMargin: inlineIcon.visible ? 38 : 0 font.pixelSize: parent.fontSize onEditingFinished: item.editingFinished() onAccepted: item.accepted(); From 6d21b9919d5fc100eb3565fbe6038007c45ce078 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 25 Nov 2017 22:53:07 +0100 Subject: [PATCH 040/126] InlineButton development --- components/InlineButton.qml | 13 +++-- components/Input.qml | 1 + components/LineEdit.qml | 8 +-- pages/Transfer.qml | 104 +++++++++++++++--------------------- 4 files changed, 54 insertions(+), 72 deletions(-) diff --git a/components/InlineButton.qml b/components/InlineButton.qml index da8120c3..9e3f3c04 100644 --- a/components/InlineButton.qml +++ b/components/InlineButton.qml @@ -47,10 +47,6 @@ Item { anchors.rightMargin: 8 anchors.topMargin: 8 - function onClicked(){ - console.log("debug click"); - } - function doClick() { // Android workaround releaseFocus(); @@ -58,10 +54,11 @@ Item { } Rectangle{ - color: "#808080" + id: rect + color: rect.enabled ? "#808080" : "#3b3b3b" border.color: "black" height: 32 - width: inlineText.width + 20 + width: inlineText.width + 22 radius: 4 anchors.top: parent.top @@ -70,14 +67,16 @@ Item { Text { id: inlineText font.family: Style.fontBold.name + font.bold: true font.pixelSize: 16 * scaleRatio - color: "#FFFFFF" + color: "black" anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter } MouseArea { id: buttonArea + cursorShape: Qt.PointingHandCursor anchors.fill: parent onClicked: doClick() } diff --git a/components/Input.qml b/components/Input.qml index b7e39eb2..6643af14 100644 --- a/components/Input.qml +++ b/components/Input.qml @@ -33,6 +33,7 @@ import "." 1.0 TextField { font.family: Style.fontRegular.name font.pixelSize: 22 + font.bold: true horizontalAlignment: TextInput.AlignLeft selectByMouse: true color: "white" diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 964af52f..c6cd65de 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -37,6 +37,7 @@ Item { property alias readOnly : input.readOnly property alias cursorPosition: input.cursorPosition property alias echoMode: input.echoMode + property alias inlineButton: inlineButtonId property alias inlineButtonText: inlineButtonId.text property alias inlineIcon: inlineIcon.visible property int fontSize: 18 * scaleRatio @@ -70,9 +71,9 @@ Item { function getColor(error) { // @TODO: replace/remove this (implement as ternary?) if (error) - return Style.inputBoxBackground + return "transparent" else - return Style.inputBoxBackground + return "transparent" } Text { @@ -85,7 +86,7 @@ Item { font.pixelSize: 20 * scaleRatio color: "#FFFFFF" text: "" - visible: item.setPlaceholder() ? false : true + visible: input.text ? false : true z: 3 } @@ -128,6 +129,7 @@ Item { InlineButton { id: inlineButtonId + onClicked: inlineButtonId.onClicked visible: item.inlineButtonText ? true : false } } diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 6816db7c..2647dbaf 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -30,8 +30,8 @@ import QtQuick 2.0 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.2 import moneroComponents.PendingTransaction 1.0 -import "../components" import moneroComponents.Wallet 1.0 +import "../components" import "." 1.0 @@ -41,10 +41,18 @@ Rectangle { int priority, string description) signal sweepUnmixableClicked() - color: "black" + color: "transparent" property string startLinkText: qsTr(" (Start daemon)") + translationManager.emptyString property bool showAdvanced: false + Image { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: panel.height + source: "../images/leftPanelBg.jpg" + } + function scaleValueToMixinCount(scaleValue) { var scaleToMixinCount = [6,7,8,9,10,11,12,13,14,16,18,20,22,25]; if (scaleValue < scaleToMixinCount.length) { @@ -119,6 +127,7 @@ Rectangle { RowLayout{ Layout.fillWidth: true Layout.bottomMargin: 20 + height: 150 Text { id: panelHeader @@ -144,22 +153,16 @@ Rectangle { Layout.fillWidth: true id: amountRow Layout.minimumWidth: 200 - Item { - visible: !isMobile - width: 37 * scaleRatio - height: 37 * scaleRatio - Image { - anchors.centerIn: parent - source: "../images/moneroIcon.png" - } - } // Amount input LineEdit { - Layout.fillWidth: true id: amountLine + Layout.fillWidth: true + inlineIcon: true placeholderText: qsTr("") + translationManager.emptyString - width:100 + width: 100 + inlineButtonText: qsTr("All") + translationManager.emptyString + inlineButton.onClicked: amountLine.text = "(all)" validator: DoubleValidator { bottom: 0.0 top: 18446744.073709551615 @@ -168,21 +171,7 @@ Rectangle { locale: "C" } } - - StandardButton { - id: amountAllButton - width: 60 * scaleRatio - text: qsTr("All") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - enabled : true - onClicked: amountLine.text = "(all)" - } } - - } ColumnLayout { @@ -197,7 +186,20 @@ Rectangle { // ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low } // For translations to work, the strings need to be listed in // the file components/StandardDropdown.qml too. +<<<<<<< HEAD +======= + + // 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 } + } + +>>>>>>> InlineButton development // Priorites after v5 ListModel { id: priorityModelV5 @@ -215,45 +217,32 @@ Rectangle { id: priorityDropdown shadowReleasedColor: "#FF4304" shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + releasedColor: "black" + pressedColor: "#404040" } } // Make sure dropdown is on top z: parent.z + 1 } - ColumnLayout { - id: amountRowx - Label { - id: amountLabelx - text: qsTr("Amount") + translationManager.emptyString - width: mainLayout.labelWidth - } - - // this LineEdit is for testing purposes - LineEdit { - id: amountLinex - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Amount to receive") + translationManager.emptyString - readOnly: false - width: mainLayout.editWidth - Layout.fillWidth: true - inlineButtonText: "Testy" - } - } - ColumnLayout { Layout.fillWidth: true Label { id: addressLabel textFormat: Text.RichText +<<<<<<< HEAD text: "" + qsTr("Address") + " ( " + qsTr("Paste in or select from Address book") + " )" + translationManager.emptyString +======= + text: qsTr("\ + Address ( Paste in or select from Address book )") + + translationManager.emptyString + +>>>>>>> InlineButton development onLinkActivated: appWindow.showPageRequest("AddressBook") Layout.fillWidth: true } @@ -282,19 +271,9 @@ Rectangle { Layout.fillWidth: true anchors.topMargin: 5 * scaleRatio placeholderText: "4..." - // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } - } - - StandardButton { - id: resolveButton - width: 60 * scaleRatio - text: qsTr("Resolve") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - enabled : isValidOpenAliasAddress(addressLine.text) - onClicked: { + inlineButtonText: qsTr("Resolve") + translationManager.emptyString + inlineButton.enabled: isValidOpenAliasAddress(addressLine.text) + inlineButton.onClicked: { var result = walletManager.resolveOpenAlias(addressLine.text) if (result) { var parts = result.split("|") @@ -325,6 +304,7 @@ Rectangle { oa_message(qsTr("No address found")) } } + // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } } } From c3e1b51ac4bcc2f5cf74bcc769bf776a06f02c9a Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 25 Nov 2017 23:41:28 +0100 Subject: [PATCH 041/126] Dropdown button development - removing the second column --- components/StandardDropdown.qml | 70 +++++---------------------------- 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/components/StandardDropdown.qml b/components/StandardDropdown.qml index 5281b846..91a514eb 100644 --- a/components/StandardDropdown.qml +++ b/components/StandardDropdown.qml @@ -41,7 +41,7 @@ Item { signal changed(); - height: 37 * scaleRatio + height: 48 * scaleRatio onExpandedChanged: if(expanded) appWindow.currentItem = dropdown function hide() { dropdown.expanded = false } @@ -60,7 +60,6 @@ Item { // Workaroud for suspected memory leak in 5.8 causing malloc crash on app exit function update() { firstColText.text = column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column1) + translationManager.emptyString : "" - secondColText.text = column.currentIndex < repeater.model.rowCount() ? qsTr(repeater.model.get(column.currentIndex).column2) + translationManager.emptyString : "" } Item { @@ -68,42 +67,15 @@ Item { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - height: 37 * scaleRatio + height: 48 * scaleRatio Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: parent.height - 1 - y: dropdown.expanded || droplist.height > 0 ? 0 : 1 - color: dropdown.expanded || droplist.height > 0 ? dropdown.shadowPressedColor : dropdown.shadowReleasedColor - //radius: 4 - } - - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: parent.height - 1 - y: dropdown.expanded || droplist.height > 0 ? 1 : 0 - color: dropdown.expanded || droplist.height > 0 ? dropdown.pressedColor : dropdown.releasedColor - //radius: 4 - } - - Rectangle { - anchors.left: parent.left - anchors.bottom: parent.bottom - height: 3 * scaleRatio - width: 3 * scaleRatio - color: dropdown.pressedColor - visible: dropdown.expanded || droplist.height > 0 - } - - Rectangle { - anchors.right: parent.right - anchors.bottom: parent.bottom - height: 3 * scaleRatio - width: 3 * scaleRatio - color: dropdown.pressedColor - visible: dropdown.expanded || droplist.height > 0 + color: "transparent" + border.width: 1 + border.color: Qt.rgba(1, 1, 1, 0.25) + radius: 4 + anchors.fill: parent + z: 4 } Text { @@ -112,31 +84,9 @@ Item { anchors.left: parent.left anchors.leftMargin: 12 * scaleRatio elide: Text.ElideRight - font.family: "Arial" + font.family: Style.fontRegular.name font.bold: true - font.pixelSize: 12 * scaleRatio - color: "#FFFFFF" - } - - Text { - id: secondColText - anchors.verticalCenter: parent.verticalCenter - anchors.right: separator.left - anchors.rightMargin: 12 * scaleRatio - width: dropdown.expanded ? w : (separator.x - 12) - (firstColText.x + firstColText.width + 5) - font.family: "Arial" - font.pixelSize: 12 * scaleRatio - color: "#FFFFFF" - property int w: 0 - Component.onCompleted: w = implicitWidth - } - - Rectangle { - id: separator - anchors.right: dropIndicator.left - anchors.verticalCenter: parent.verticalCenter - height: 18 * scaleRatio - width: 1 + font.pixelSize: 16 * scaleRatio color: "#FFFFFF" } From 98479c4dc4bb7af7d05badee8e7fdef67c982456 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 26 Nov 2017 00:02:43 +0100 Subject: [PATCH 042/126] MiddlePanel background gradient --- MiddlePanel.qml | 8 +++++++- images/middlePanelBg.jpg | Bin 0 -> 5503 bytes qml.qrc | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 images/middlePanelBg.jpg diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 0f816704..65982b79 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -69,7 +69,13 @@ Rectangle { signal getProofClicked(string txid, string address, string message); signal checkProofClicked(string txid, string address, string message, string signature); - color: "black" + Image { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "../images/middlePanelBg.jpg" + } onCurrentViewChanged: { if (previousView) { diff --git a/images/middlePanelBg.jpg b/images/middlePanelBg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b169616ac1e6de3937af225b078d30c1aee5acee GIT binary patch literal 5503 zcmcInX>e256~6M5?n2#UyO**kELu&a~K;u?0#qI=G_oOAA@e%eJIo}Ke-4lx)EWET7p`d_k*Bt#AgzDY*-l#Gc+JQ7Wb>@b;< zl9H2>Oera;sVOOG`okbeQlc?2#bio(C^aSZq4dFUq^Glo#J@CtrvF{!j5d&rWP`=< zW66*~5;6=@hJk)cjARTwW7tOsNrHSKV{sT0r390KBqgV$4l+RUlJ+iKfZR>&=EEcb zQcExd>T7lc#TaCU4qdnh z*vT9==7|}@$3DMSo_b?{ZR2C(e8F$Gz46`=eabm`(WD2=`2i`@izH2AX=V^BQL;)( zipRb)Xy@`#ODsJb|8gndDq3`mlDBqRyUyM67TkKf;_mW2;WSF}<<3RNwKpmwH;RwL zFB~6JVscblI@?!SKi@Z3nbcPzpAH1W&yAvFtF^-nOI6;vUwM65Z@|6%-{nCipV~e|7z*Qmsj)&(2}sLXWpsUisNSUi#ft z-?b0NojrZTTSS``^P2F@d`HvFzGdcl-U8=IbH2%P()^;`eaKlYnG2lNnXdbCai*&) zTMn8FO_pPJcax(XRG~{-R`oxHnS%TPL~0H!XJY4(lFx?<_7>I zb53)(f|C6eiqGtzt@_A|GhN+I2reEiaMrN36>a?Q!pY&Q+42P%IayU#93WWlw9DZ} zi0#wH&dqc$<@psjKQdYBIrD`Kb_mD@A?g^sa=|a-Kf*SgWy=a;hQKOjes&0v=TH)1 zyN$*Dgv&f1c|KuxZ}!^k?ob{`7C_yAGbSDq2W%{qFo7zjDmjCv1J=k z=|~l`n!z(sS0F$U5)LT~f5JDWpWnUKn_GXgCQ?@|%A=t4GD^x{?fsACASw(pvpVua zqEI89wk>#job!wE^c`#Lv)VoxL_nTF%~I;jD*>9?g};CbmE_|K40Q z2TAIU{bm#=*et5o$Pme7B1@>Psvxo@MM@(?aCyuHq0u47)U{` zn2S}^FbASNLzI*1Y2Ku`6IdEMz|&A4n=BBp90KC(!3n4*xA#Tjl@*$^%gq80i=fzLcu6_D6D?@=NgYT+ycIM5`1`UB!IO zA#(YcXZb+J;20AEBRrhiI1Sce%m({mA6N<{9l%rPmAMdB>;s@_aGMO&pq}x=UgU66g-80qjYQkVk#nnyW!A zb68&m+kb^Hx3KM9!5qHTMm77z7uyzEl^5bL^7alcWPydQjAFdR`yTKt_Fe3oAGZNV z`y&)gtM`phSrG>^)Xz(XswvwtU{7Z~6*os70H?NeO-%?j_0igtm2uHjWN}j~D7qq8 zsvGRH7{@QnYutM1s!!*e+)B-E>AbQAEUIoC{?6(QjITBr?Nlqr5{EDnzLhmu*c%$| zf%N@F=ao1v+m#J^beaiOj(rLwFVI;d4K(yrU-7536RSOpl8iXNo1hie8Updax%L+I*G*T7npopB^atbyGM91#fyEwPZd|EM4X zyD)Y;=Tj;)p!UZ0E|iM3-~~7=z;;;9(GA)Igom1pR@%_l7_$9ezQ~lUb+p!Aqonq7ug69&{0}>MJEi~t literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index 84c2f6c3..d17b7dd6 100644 --- a/qml.qrc +++ b/qml.qrc @@ -189,5 +189,6 @@ images/leftPanelBg.jpg images/moneroIcon-28x28.png images/lightning-white.png + images/middlePanelBg.jpg From a07fd467184b08fa0f1bf0c12053c5c7a97173c4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 4 Dec 2017 23:34:21 +0100 Subject: [PATCH 043/126] Update MiddlePanel background gradient --- images/middlePanelBg.jpg | Bin 5503 -> 12594 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/middlePanelBg.jpg b/images/middlePanelBg.jpg index b169616ac1e6de3937af225b078d30c1aee5acee..9957f58e75851ab06486c8c1dc25971ddfe220cb 100644 GIT binary patch literal 12594 zcmb_i4SW;ld6zMX^Rc0_q)F3&m6WbDNdwKYG{nKaw5+8cTilKoQY>3Z*hbfkYM9Cx z3F!?@Q>9@+Wce`bX4JGxosU|A5s+}p{MYH?PFj6%GbVPD=I3oeHDLfg3<*fXU6Y; ziZA?Jbn}cEMKfkx_~N7fQh41q`--Ali#}IeG}|^~c2V){qQWuTOxtG)`-*;Hv)L}6 zQCx(7&i#~JartF4uPnZ5Mv?7me0+H^-hci(8@?(onQ=wYmA0#{{+Mk>QSr>8;$m9S zjLWa|6wN4}Is39dyZq*oYd&SW;*M*-_!sj&e&x5mblpRrzVrIOUAyTM4?q3qOJ3MH z@|nM^z3PTH4&61sZ`l`ql=;_R{MEPDefcYQFJ1N7?<`;O$^Uxux5v-^-D5v|=Er~k z%UvB^>01{4!>H%hd&<80wXZ+$-Ic4q_mAJNTVKDy`}j|SPyF=BXP_1=p zRnto^zw+AdJ+YS7wtf2#Bs$-E`|$hSV$YG^o#;O~aBA@Mm^!XyCvw<+QSpqKGm9^q zIdkUamtVF9OP)RR=0Cgaj>~PIy5@`DD*20tu3dY@mp09N`s085!o%0ydF9Sezj0_u z?a1|gKl;l*|JP-oSoK$#U;Ni+?z-XIU-4>mN#65@dN)d#*;|HQVJ zS~`19W$*dgcmHw2Pyg-Z*0+ufPTX4d^_AcEKKZj(+TQ-%>0IG=wm*S;X3Q?0ZR2e3 z6>L(QR-+B`BCkh1opw!<*`88EZ0mPxJI4w(e-_{Ui)X7nP_UKM$XgwXAoD#G% zp!%OY@7S}V;EA+uGPAmd@AH1{_%Fjv!m{XEc^hswb16Jbx%ef=gvBhTMR@UE$M}5N z)HB1!e5HJCu_0tfm1z31=~~BrfHuYgGwsS z*Q;BvF4*ve-yP_q6*cKfcC)TUqcy6$bxy&yvtX;YZY$*{)OYLw`RGQv>I0wFP@|W< z<<35)JRl#djp+`boT^@b@lJ=Xrk6Dez19mHftjAZLGdQ;cvxv6hYh%~2Uzih_4TTx zusUjQaK7$Pnv-4FS=dPqRxaM>P4~od1zVb2)NdIwf&YHdj0xUZv6|MRY{9m%GMAQk zub3@6Nj{glasf_St5Ue!Vd}WrH9k)gI>cASn@vs;Qr1Nu_K;#|x=c&oX*#x43Vz-f zayBQrjK_sUj=6lve(}}*8liA#(zeb=3$_gf+fNHNHwD9eES@jeLcFSkoo8T;$b*h? z?maxMPrR2L0Bi5}=XT3d1KsF1{8;9@k`mNKJ%NRk*V+oUJq6nn^Ud3oo~BY>tY!+LkjRYs(1OUW)5kM~0}wvtyQ5 z9f7|4%Cv0RiIV(sscVqFM2c$8AeOT#kq!-xY1qCJM(E~P)XXJ}5M?vHJ_RRf=b|gJ z+zbLc%=x%C8M$w5mOFbd+oLHJ{MR$`HdqGByOvgS8{G-(JjFtsGDnwcCN`*VOBvUA zci!}$!jtXUO=eCCeK;uSMSC3zQ-tFbQ=Js}2!px4$d|fvEFK$>gvDxf#M5&aue460__dcc6;9(VL9$GrTy;*7O$ zJcsMZFXbqc$AD!B+}_#B(K5~XD4Chwd)_xuTKQhK17^zM>QP)=nQhWxoc9gFdBqSM zV$P?{+0Kir3@z`L+D1%&t@Rjf0={<@4j=jiN)bgC0&Bof6S_ShcN|2}k60;0>8G$W z1si1uY5;A4Y@!;urew6VIPxIn-@ue*Mb02zZn4sm?Lg+i?-d4KcR%I&jl1LRseF|r zydeq;CjHV}u+0PZwEr$euK-loP6KggR5k3U7A}!!2 zP#{$##B5lvhs?6mq%3p6v~FDMLeNY0j5hpA!0GLu5YkecR1K3&4Rs6mT(ZHWDipJR zabY57A)N4_r+ouz8@7~;7!;&-JTJv1Qm=|Ft0M(lhoPDc1f)MS_#edmtnmJ!PqVl~ zu`(*8Ntwv)N~#ec>q3UZJt=rwR-_MPX#t9^<4j_}{IVi7SjL9GQ+US)RXUe}mX~*M z660xK+pZtTvkpV(0=gzb&NGR8NNUfC&PO>EAITYXC@v+w9d!l<{`~C*YTyR)_d+Dh zl)7teAzfo2Qs0$^+@_#Q!Yp2VknyY&k+0mUTF|-9;X-({RH*&kqvB0=on@u`Qk4E+ zGl&V?HHB~}cuC#uaJJYsgs2j8ECkrd^o`14IHM0?BM{0{zzI!!SJZP%zzQr1)Lm+b zytjYVM8WoSkvZxPr2EB}2l_=e^ry`%EAq?cc*hq_sD2P4bzaW>}%pnx5HIBg=6_07*U4H#P1fkoFAj~b|jRmS7w-FL30 z$k^uS%CTiA4NX$Z#OkQ02bM)1%s<8M#sep&=Qk2=2yufvE!ZA1JB;9f6lwr$mr&yF zrT`7dtf4y8q$l-ZtZdo4jq76B85QC5SXyfFD7!)ybC}}xb0!|KU|oDWu|MW8IV0|2~KO|aWhi((Q(oto${^F}7p$2U(FGK!r0TdT~w z&75gaf^RC=K8C7iR>L~-S=OU#rLWzw9T0*rmtgv%-hO1272>p4%5)G)jZhb+%zBB~ zG405XV`HC19a<)OQGgKWxBJ zszemUTjzjFjl~4}0)ER}_&^ik(*1tDS+oed^U;A(lNZ2NXtOb-fV{t8>(R%(sXJ?0 z8A2j5WyJ&`)xG!&HyRpV@)R&huU9)=<}Jhnekty(*-Kp-I3GY=`MDknQSTLsPXO1jnW^id-@yEw*3$Jl^2xp+Nn-eJnjVb~l(R z{x?b{acdI%6!kZ*qwo2Pp66^f4@dwN#L2PR9cgnZ&}ohGW~+Q8p98I0VZ^L(w;~ao zAuTIMy_&OScM_eFs15zhb9$N8WK9D}uww7_Ky@uS_CyKyUcpwWNkFlkVlZ4C%7!vA zV(%2e$SlOc1{86`UA{66-igoZ2J#&B8zMH>0C)i#vl4TdR@m$sp&kzd zWz15we-s9pW-a0;k0CY_=H2eV2bDF^SxDs$Lk{DO>xwCIde$O_b#!2(!x>kka-eKN`)DeVL$!1T|(7Fs1|GB=%>$Iqa zau(=f5tbn^qkj*u4(VlCNFBgXIE-?jsk5^GgTJ zTe5ljeJiyO4s_gsYF~bCt>b?5sTrh6xo=8pSSzlx5Cw6C+%ZR}M~QkpJtv7LDJv#h zB5WUBpe|ZCtQ>nJ@;ZQ|%5bZOepY7Og1x}C4)ZP`VleD%!Mm{=Kl92*(PvEdF2q#g z7Q5|t6YFB3QltA-aaEoZLGqB3D1%4KhFFl>a#@SnV8*o*kAPd$<=H;A)7+!IvV~uE zU^`5G`1hv9!U<@o3T<3yssKFb80YBKCSvrRfkjw{38N}#Qdm24O?=!y6_`#Rw>r+y zlFbUW2Bg@Ww`uq=u`nQqp5O!3Ad5cjJBST!I0i*z(*$5nb;$Y%L;^IMER?VOFpB>k z69srJq}#P0`Lh&83C^V@&LWLAz6>5ysXL-NBNtN?+_Z4gI8lrC?KDSCealj`!^M&N z*7?FCW_XD8>LOxOlkUF)HXAoJWB@hlOF-*EUo*0RR%BzFS~e`Dv7@JaYQ0AYSA$0f zxL*G~NVAoC86*L#>O&^_rV3U{!CSqFDrX%LRDLSyixoN{jBm!qK4+d><>b zsLWH2Y?I(QohPYCvD(O*bA|eXJhb(Ct6#ehlw7B^0h1D0W2wbEETxOG?72|d{4D!9 zmGRI)_^2|GUxq-E+_U%)L=bnALqx-mbccN}JUN9|4NKt!g`=OPK)O*a46y~EK=$j% zFW^cI*^;r`<3P|h?YXicD=napr8qL-;<6z>*GnbiAw+GzcpG}cfe>J{yxvQ!NLSv{ zl)qM$*d%zcGlIn0@rVOuXdqK=beA4wA=wpAxQ1AwOM)n|mqo|Y6w*G`D>^~AyK{Kb zWF_%{r9Nnf(Ub+PTi6N8wlOW;-`$>Ua$+a(N$P@+ed$nC{{c2V%Zfh*EkVWZe<4ti zE+C8r3P6A+-4R#}k2JfJXi9{aQ07i=C@rUwuDeGF3LtaMA_Kk+DhJzmH33xtOu+{6 zhAn}ofggv}w^QmRSo?Z6*q$HE2dT7n!U_%a;O+jhe#lJ@u$1_K)Uv{2k$Mt+LXE`= zZY$*o=$t}Rmhs_i6Yo_cXyt`DEULzMwH+}Ug;Am}@_Ms{by9T*BnJ)zn5zOX+yq~* zSA~O-gr3Z@p9;_!}1Zi0WHRHf0ixaE5RpJK?<-pQ$~0E-MyO9P$gUU zrp{%t0NPrQeNxvrXjRD)7#Melb}dX8?@(G`3kG?@UZsx7jq#wl)F_wVQ6sJ7xbwy* zpre?2x?teX^Htkh{Act=S2K?5DPm|r6>30!=*m0%3KzUqc3+2@)!fJWhw7z%8A zTR%*oKwF~66QdyqT|kj@-ON4~Z?zuy9GYqfMXG}Lhn_F%r$%HRIS17bP)#grfV3Dh z>>BTo%|t5n4itJYv1C`ie7MoaH8`7T>EydkD4@jY#$-vUF>u>}TaB6tBS78WEKn$F zc$MGqI@wlvDONf`hC&JK6a_CDdgzE4_pbvWPc0Cn zHDoH08OlLOJrMpkmdnu%A`tJ3VF%GJ4;sFJ8zCt`?uTxXf+fNU1XR9FD;5`KMP0IV@YX6&K{PJJ)|cYfAy#1w zibBO+)T3xVWVq3Cu68z~C}Ytw0(~3}a7S>`W$RHs(ZE2Kr6xG*XyON=9vKa9)^H~ceoE&vNA1}C@J|M38EE#|rolEII=UaZeT+2kNQ6>NYfrQRx zY2J-m+&m&TwoIan02cy)PyaKJw3i)#d;Hl_-nrURWz+E}?S%0f_H_QP&pB*g0x50fa)3_iyJr&d7~CwkV|yjguWT=Xk|?vIsyl zF7-`ND?uY9SOw7tfpzYbxrjzqD3*3oGpHAVh}|e4qms==Bh<7}sLLJAE5Q3=p!rlM zdaWm+iKpDd1O2!HiW}o4SSknsmp}(KfN9aDv=sM$pRYB;eM*X-%-4gE<>-Ymy_7jZ z+6&6DdKEyo0mvgHq?h$FAmnH^9m+P5cAWK&a}^MSa=wh|zXVv*rl-UoSmqQfVu>+~ zr82PPb+pz4M~{-ephYM3?9X%50%9it5PPa+XVIB~LvSukSkBeDX>f*6M23u|4Hg)E zLxzsJcO9Uxeka6{Jt#dK2&~hmt(>q(Lu(NPT?TUv$*Jv)btPPeOPlaoDL?LcYbi}0 zTEIGDB17BM4G++>ZLF!(FiUxnVNg&<;`&*62bXrCf}PF*340uUMm_p{Kp@0!(gCJV zPNoFc1x5>Qc)>h%um{k`O3-`R{)+JC08D}50=m3`?%d>@%mg9~@7@kT&g24d(Wk@l+^O>JSnOIwL@o3i5fW)m&5RYOm_R_oi2 znf3$58d&7CX&l(z=sQbYGJ2^#OmrsoDG~=$Bi*zEw(rCjJpZl+#YIVgU&~~#G>zGn9b!}Df3}+TjE2XARTZ|MaueJJHMGpA06Vx!>=NtEXF=Cv?ge;>h zF+K<^rH)ssK=7(&58F4Y>>g(L>(hkk7b!mLlDMh0sV)gjWSLpcqk@R146yL2Ha z5LKT82_p!;usZU3p2c!&-4hOeBvM97S{B)GiL5=>VK0yA$C6q5_+p=0rj@qR6sK8U^r1qM{|*SWb!#06va(L#aUYc;~SFi=bs#vu7xvr@a_7 zL=vKT7oFO`0Rc48Iq9*)Vzw{rP1f8XcbmcxcU;(BuArFZmtq@F!}Wcys|WL>YD`mu zr*MuboO5bb`0b(B*q$8g6s*>&0b^)l78GTf82vi#>8vv657KE0Pp9Qi>}<;OBtpAc zc3sM{5bw=-!1k64sCa2L$0|{9C)CJX6gm+U3cLRS3Tj)oB`Y3)n1QnZr7*{AHmK%- zds*Men0y#R(t%78I__?RDiAWGi-ZAw-=tK0TL5(fjW0n(5Y;qvsvI5S#$3PoCY|Qc zNv>EHtnM8&GYKn%ht|Mc8(9K1+8X6du>k+!Lis;_K+LV3qH|r0liB_SCBjt`s4qnZ zz~X*}y&w}~R>ynEP96!jptT6|1T9JvQPKlwgez3!fq#(585SwkAWGx!o*SZ!LO;6N zI=+Fo9`z0tBWaH=&h;Djq>+WxQ6Ri%wgk$GV32p*PMK$cS%onUls4~98*-jY3{tXL zogaFatJk@cGB#-;_=ZR`|-oj3F+X^|L17o9gL63Qd(`s2uD7cWyQqSi00ER)+$oLH1I%9UoM!kmfML5}G@!CHekS^57^Hvi;!QO>vrYBIG zgH4uf>PKIUp~JJ&F{cM6Y=cfX05NW(7ub|U-TYn{VjWa85}ZxjxkEw5iT zcl{%QiZG2}ydDWdSEwGAoH8_mCRaJ~M}hP-n^+%!d-a-2%`5`?5_X{4tiyNpH1#+x zWGa)?r=oOmLyI(JSvSB|i^}Nua?(Mo@jZy-n3VdfH?NyK1h)j)71TSy8o(sEUei9A zrX;)o?W_g>5j9?>&{RPXM-^!`j&1B^%}Ma3Jz8{EbQK8YZaPt*eW0h{4k67d5!8P~ zp}MpUXzx(aBsg;lbgx%Z)xPpthbxPtS2`v|FUeq2&!I~LtFGWXKw~OEg{&58>vdcv zIzl^QRhZ0zo#ge*TwmAR+8DMGcVvWsiUTvx2@-P!0A1GRS7Ba=Q71S#noBxz7IFr` zGyCZH7l=1_r6QzpUgLdvaxONFR7@!b%7?4N|NQ~T&y-ys!}54mGnx6tp=@Xnqyxy; z5jn%6C82CM8w$+D1R=jD15g~M?CQt%Tp8f!8dH*jrTl5{5SW163kA>~IAC>3y?Ku7 zQ;ycF%B>;}8o35*+N~wo&YA*LJWa$72)6sRh7*F;v&&Q=Y$egyWU!5 z;XoRs;K^oRfP(Un<<|Ns_#^7G6FuLK0~i&5*}ImdOFx=%fT0fx-fYqJM67Lv>WZ)dsDSquZN` zk#WhY;)9VhzcGcrgotAwuL5aJ*b?L=kNl&xo%h!NM*>WH1|5Ps!S)4McSU|o_)n-Qvn#@R6MG zz8Pq>|GZ#x;xwRCwb(n7b2L$KVKkpRl+T^yBv%Rt9YUIPCPccSfODjZ&~b`MtXb)3 zo<(P*&Y*y!0;SDL9LLL;=uLfq*-;tCjWNmygqJDDzE`ll3P6PupiEJ-)?mdkLDe6? Or>G=+^jn0&k^ctrPAQE5 literal 5503 zcmcInX>e256~6M5?n2#UyO**kELu&a~K;u?0#qI=G_oOAA@e%eJIo}Ke-4lx)EWET7p`d_k*Bt#AgzDY*-l#Gc+JQ7Wb>@b;< zl9H2>Oera;sVOOG`okbeQlc?2#bio(C^aSZq4dFUq^Glo#J@CtrvF{!j5d&rWP`=< zW66*~5;6=@hJk)cjARTwW7tOsNrHSKV{sT0r390KBqgV$4l+RUlJ+iKfZR>&=EEcb zQcExd>T7lc#TaCU4qdnh z*vT9==7|}@$3DMSo_b?{ZR2C(e8F$Gz46`=eabm`(WD2=`2i`@izH2AX=V^BQL;)( zipRb)Xy@`#ODsJb|8gndDq3`mlDBqRyUyM67TkKf;_mW2;WSF}<<3RNwKpmwH;RwL zFB~6JVscblI@?!SKi@Z3nbcPzpAH1W&yAvFtF^-nOI6;vUwM65Z@|6%-{nCipV~e|7z*Qmsj)&(2}sLXWpsUisNSUi#ft z-?b0NojrZTTSS``^P2F@d`HvFzGdcl-U8=IbH2%P()^;`eaKlYnG2lNnXdbCai*&) zTMn8FO_pPJcax(XRG~{-R`oxHnS%TPL~0H!XJY4(lFx?<_7>I zb53)(f|C6eiqGtzt@_A|GhN+I2reEiaMrN36>a?Q!pY&Q+42P%IayU#93WWlw9DZ} zi0#wH&dqc$<@psjKQdYBIrD`Kb_mD@A?g^sa=|a-Kf*SgWy=a;hQKOjes&0v=TH)1 zyN$*Dgv&f1c|KuxZ}!^k?ob{`7C_yAGbSDq2W%{qFo7zjDmjCv1J=k z=|~l`n!z(sS0F$U5)LT~f5JDWpWnUKn_GXgCQ?@|%A=t4GD^x{?fsACASw(pvpVua zqEI89wk>#job!wE^c`#Lv)VoxL_nTF%~I;jD*>9?g};CbmE_|K40Q z2TAIU{bm#=*et5o$Pme7B1@>Psvxo@MM@(?aCyuHq0u47)U{` zn2S}^FbASNLzI*1Y2Ku`6IdEMz|&A4n=BBp90KC(!3n4*xA#Tjl@*$^%gq80i=fzLcu6_D6D?@=NgYT+ycIM5`1`UB!IO zA#(YcXZb+J;20AEBRrhiI1Sce%m({mA6N<{9l%rPmAMdB>;s@_aGMO&pq}x=UgU66g-80qjYQkVk#nnyW!A zb68&m+kb^Hx3KM9!5qHTMm77z7uyzEl^5bL^7alcWPydQjAFdR`yTKt_Fe3oAGZNV z`y&)gtM`phSrG>^)Xz(XswvwtU{7Z~6*os70H?NeO-%?j_0igtm2uHjWN}j~D7qq8 zsvGRH7{@QnYutM1s!!*e+)B-E>AbQAEUIoC{?6(QjITBr?Nlqr5{EDnzLhmu*c%$| zf%N@F=ao1v+m#J^beaiOj(rLwFVI;d4K(yrU-7536RSOpl8iXNo1hie8Updax%L+I*G*T7npopB^atbyGM91#fyEwPZd|EM4X zyD)Y;=Tj;)p!UZ0E|iM3-~~7=z;;;9(GA)Igom1pR@%_l7_$9ezQ~lUb+p!Aqonq7ug69&{0}>MJEi~t From 901e77e6f1d7c29502498278bd3f3a04fd0df240 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 5 Dec 2017 01:27:34 +0100 Subject: [PATCH 044/126] LineEdit: added placeholder label, added input label --- components/LineEdit.qml | 134 +++++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 50 deletions(-) diff --git a/components/LineEdit.qml b/components/LineEdit.qml index c6cd65de..c4bfdfc2 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -31,8 +31,8 @@ import "." 1.0 Item { id: item - property alias placeholderText: placeholderLabel.text property alias text: input.text + property alias placeholderText: placeholderLabel.text property alias validator: input.validator property alias readOnly : input.readOnly property alias cursorPosition: input.cursorPosition @@ -43,11 +43,20 @@ Item { property int fontSize: 18 * scaleRatio property bool showBorder: true property bool error: false + property alias labelText: inputLabel.text + property alias labelColor: inputLabel.color + property alias labelTextFormat: inputLabel.textFormat + property string tipText: "" + property int labelFontSize: 16 * scaleRatio + property bool labelFontBold: false + property alias labelWrapMode: inputLabel.wrapMode + property alias labelHorizontalAlignment: inputLabel.horizontalAlignment + signal labelLinkActivated(); signal editingFinished() signal accepted(); signal textUpdated(); - height: 48 * scaleRatio + height: (inputLabel.height + inputItem.height + 10) * scaleRatio onTextUpdated: { // check to remove placeholder text when there is content @@ -77,59 +86,84 @@ Item { } Text { - id: placeholderLabel - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: inlineIcon.visible ? 50 : 10 - opacity: 0.25 - font.family: Style.fontRegular.name - font.pixelSize: 20 * scaleRatio - color: "#FFFFFF" - text: "" - visible: input.text ? false : true - z: 3 - } - - Rectangle { - anchors.fill: parent - anchors.topMargin: 1 * scaleRatio - color: getColor(error) - //radius: 4 - } - - Rectangle { - color: "transparent" - border.width: 1 - border.color: Qt.rgba(1, 1, 1, 0.25) - radius: 4 - anchors.fill: parent - } - - Image { - id: inlineIcon - width: 28 * scaleRatio - height: 28 * scaleRatio + id: inputLabel anchors.top: parent.top anchors.topMargin: 10 * scaleRatio anchors.left: parent.left - anchors.leftMargin: 12 * scaleRatio - source: "../images/moneroIcon-28x28.png" - visible: false + font.family: Style.fontRegular.name + font.pixelSize: labelFontSize + font.bold: labelFontBold + textFormat: Text.RichText + color: "white" + onLinkActivated: item.labelLinkActivated() } - Input { - id: input - anchors.fill: parent - anchors.leftMargin: inlineIcon.visible ? 38 : 0 - font.pixelSize: parent.fontSize - onEditingFinished: item.editingFinished() - onAccepted: item.accepted(); - onTextChanged: item.textUpdated() - } + Item{ + id: inputItem + height: 48 * scaleRatio + anchors.top: inputLabel.bottom + anchors.topMargin: 6 + width: parent.width - InlineButton { - id: inlineButtonId - onClicked: inlineButtonId.onClicked - visible: item.inlineButtonText ? true : false + Text { + id: placeholderLabel + visible: input.text ? false : true + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: inlineIcon.visible ? 50 : 10 + opacity: 0.25 + color: "#FFFFFF" + font.family: Style.fontRegular.name + font.pixelSize: 20 * scaleRatio + text: "" + z: 3 + } + + Rectangle { + anchors.fill: parent + anchors.topMargin: 1 * scaleRatio + color: getColor(error) + //radius: 4 + } + + Rectangle { + color: "transparent" + border.width: 1 + border.color: Qt.rgba(1, 1, 1, 0.25) + radius: 4 + anchors.fill: parent + } + + Image { + id: inlineIcon + width: 28 * scaleRatio + height: 28 * scaleRatio + anchors.top: parent.top + anchors.topMargin: 10 * scaleRatio + anchors.left: parent.left + anchors.leftMargin: 12 * scaleRatio + source: "../images/moneroIcon-28x28.png" + visible: false + } + + Input { + id: input + anchors.fill: parent + anchors.leftMargin: inlineIcon.visible ? 38 : 0 + font.pixelSize: item.fontSize + onEditingFinished: item.editingFinished() + onAccepted: item.accepted(); + onTextChanged: item.textUpdated() + } + + InlineButton { + id: inlineButtonId + onClicked: inlineButtonId.onClicked + visible: item.inlineButtonText ? true : false + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.top: parent.top + anchors.topMargin: 8 + } } } From 6d31c48522bb52b5dd18717c44362de1e9b5b0a2 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 5 Dec 2017 01:28:24 +0100 Subject: [PATCH 045/126] LineEdit: cursor: pointer for QML rich text on input labels --- components/LineEdit.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/LineEdit.qml b/components/LineEdit.qml index c4bfdfc2..5f636a06 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -96,6 +96,12 @@ Item { textFormat: Text.RichText color: "white" onLinkActivated: item.labelLinkActivated() + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } } Item{ From 02380fbf1a1e200e45e4fb05f6748deda3233c80 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 00:52:40 +0100 Subject: [PATCH 046/126] Changing testnet label color to be red --- LeftPanel.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index d9df22da..a999f9ad 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -128,8 +128,8 @@ Rectangle { anchors.leftMargin: 192 font.bold: true font.pixelSize: 12 - color: "white" - opacity: 0.6 + color: "red" + opacity: 1 } // @TODO: implement From b09dfc2511088211e996b0f22948d01b8c5c95b8 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 00:53:40 +0100 Subject: [PATCH 047/126] Added some Style properties --- components/Style.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/Style.qml b/components/Style.qml index c1bc3938..2cab3cfe 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -11,4 +11,8 @@ QtObject { property string inputBoxBackground: "black" property string inputBoxBackgroundError: "#FFDDDD" property string inputBoxColor: "white" + property string buttonBackgroundColor: "#FA6800" + property string buttonBackgroundColorDisabled: "#3B3B3B" + property string buttonTextColor: "white" + property string buttonTextColorDisabled: "black" } From 3d65a5d90d4deb6bcd76c5c033137509267d1ad4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 00:54:34 +0100 Subject: [PATCH 048/126] LineEdit; included copy button --- components/LineEdit.qml | 49 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 5f636a06..debc396d 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -40,6 +40,7 @@ Item { property alias inlineButton: inlineButtonId property alias inlineButtonText: inlineButtonId.text property alias inlineIcon: inlineIcon.visible + property alias copyButton: copyButton.visible property int fontSize: 18 * scaleRatio property bool showBorder: true property bool error: false @@ -51,12 +52,12 @@ Item { property bool labelFontBold: false property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment - signal labelLinkActivated(); + signal labelLinkActivated(); // input label, rich text signal signal editingFinished() signal accepted(); signal textUpdated(); - height: (inputLabel.height + inputItem.height + 10) * scaleRatio + height: (inputLabel.height + inputItem.height + 2) * scaleRatio onTextUpdated: { // check to remove placeholder text when there is content @@ -88,8 +89,8 @@ Item { Text { id: inputLabel anchors.top: parent.top - anchors.topMargin: 10 * scaleRatio anchors.left: parent.left + anchors.topMargin: 2 font.family: Style.fontRegular.name font.pixelSize: labelFontSize font.bold: labelFontBold @@ -104,6 +105,48 @@ Item { } } + Rectangle{ + id: copyButton + color: "#808080" + radius: 3 + height: 20 + width: 44 + anchors.right: parent.right + visible: false + + Text { + id: copyButtonText + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.family: Style.fontRegular.name + font.pixelSize: 12 + font.bold: true + text: "Copy" + color: "black" + } + + MouseArea { + cursorShape: Qt.PointingHandCursor + anchors.fill: parent + hoverEnabled: true + onClicked: { + if (addressLine.text.length > 0) { + console.log(addressLine.text + " copied to clipboard") + clipboard.setText(addressLine.text) + appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3) + } + } + onEntered: { + copyButton.color = "#707070"; + copyButtonText.opacity = 0.8; + } + onExited: { + copyButtonText.opacity = 1.0; + copyButton.color = "#808080"; + } + } + } + Item{ id: inputItem height: 48 * scaleRatio From 01f7b6cbfb6d61c9a4b776aa8e4b1b5484a34bd1 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 14:09:37 +0100 Subject: [PATCH 049/126] Transfer page QML development --- pages/Transfer.qml | 237 ++++++++++++++++++++++++++------------------- 1 file changed, 137 insertions(+), 100 deletions(-) diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 2647dbaf..ae6ab7fa 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -29,6 +29,7 @@ import QtQuick 2.0 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.2 +import moneroComponents.Clipboard 1.0 import moneroComponents.PendingTransaction 1.0 import moneroComponents.Wallet 1.0 import "../components" @@ -45,13 +46,7 @@ Rectangle { property string startLinkText: qsTr(" (Start daemon)") + translationManager.emptyString property bool showAdvanced: false - Image { - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - height: panel.height - source: "../images/leftPanelBg.jpg" - } + Clipboard { id: clipboard } function scaleValueToMixinCount(scaleValue) { var scaleToMixinCount = [6,7,8,9,10,11,12,13,14,16,18,20,22,25]; @@ -118,36 +113,22 @@ Rectangle { ColumnLayout { id: pageRoot - anchors.top: parent.top + anchors.margins: (isMobile)? 17 : 40 + anchors.topMargin: 40 * scaleRatio + anchors.left: parent.left + anchors.top: parent.top anchors.right: parent.right - anchors.margins: 17 * scaleRatio - spacing: 0 - RowLayout{ - Layout.fillWidth: true - Layout.bottomMargin: 20 - height: 150 - - Text { - id: panelHeader - font.family: Style.fontMedium.name - font.pixelSize: 32 * scaleRatio - color: "#FFFFFF" - text: "Send" - height: 150 - } - } + spacing: 20 * scaleRatio GridLayout { columns: (isMobile)? 1 : 2 Layout.fillWidth: true + columnSpacing: 48 + ColumnLayout { Layout.fillWidth: true - Label { - id: amountLabel - text: qsTr("Amount") + translationManager.emptyString - } RowLayout { Layout.fillWidth: true @@ -159,6 +140,7 @@ Rectangle { id: amountLine Layout.fillWidth: true inlineIcon: true + labelText: qsTr("Amount") + translationManager.emptyString placeholderText: qsTr("") + translationManager.emptyString width: 100 inlineButtonText: qsTr("All") + translationManager.emptyString @@ -186,20 +168,7 @@ Rectangle { // ListElement { column1: qsTr("LOW") + translationManager.emptyString ; column2: ""; priority: PendingTransaction.Priority_Low } // For translations to work, the strings need to be listed in // the file components/StandardDropdown.qml too. -<<<<<<< HEAD - -======= - // 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 } - } - ->>>>>>> InlineButton development // Priorites after v5 ListModel { id: priorityModelV5 @@ -209,7 +178,6 @@ Rectangle { ListElement { column1: qsTr("Normal (x1 fee)") ; column2: ""; priority: 2 } ListElement { column1: qsTr("Fast (x5 fee)") ; column2: ""; priority: 3 } ListElement { column1: qsTr("Fastest (x41.5 fee)") ; column2: ""; priority: 4 } - } StandardDropdown { @@ -217,53 +185,81 @@ Rectangle { id: priorityDropdown shadowReleasedColor: "#FF4304" shadowPressedColor: "#B32D00" - releasedColor: "black" - pressedColor: "#404040" + releasedColor: "#363636" + pressedColor: "#202020" } } // Make sure dropdown is on top z: parent.z + 1 } - ColumnLayout { + // recipient address input + RowLayout { + id: addressLineRow Layout.fillWidth: true - Label { - id: addressLabel - textFormat: Text.RichText -<<<<<<< HEAD - text: "" + - qsTr("Address") + - " ( " + - qsTr("Paste in or select from Address book") + - " )" + - translationManager.emptyString -======= - text: qsTr("\ - Address ( Paste in or select from Address book )") - + translationManager.emptyString ->>>>>>> InlineButton development - onLinkActivated: appWindow.showPageRequest("AddressBook") - Layout.fillWidth: true - } - // recipient address input - RowLayout { - id: addressLineRow - Layout.fillWidth: true + ColumnLayout { + Rectangle{ + id: inputLabelRect + color: "transparent" + Layout.fillWidth: true + height: inputLabel.height + 10 - StandardButton { - id: qrfinderButton - text: qsTr("QR Code") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - visible : appWindow.qrScannerEnabled - enabled : visible - width: visible ? 60 * scaleRatio : 0 - onClicked: { - cameraUi.state = "Capture" - cameraUi.qrcode_decoded.connect(updateFromQrCode) + Text { + id: inputLabel + anchors.top: parent.top + anchors.left: parent.left + font.family: Style.fontRegular.name + font.pixelSize: 16 * scaleRatio + font.bold: labelFontBold + textFormat: Text.RichText + color: "white" + onLinkActivated: { appWindow.showPageRequest("AddressBook") } + text: qsTr("\ + Address ( Address book )") + + translationManager.emptyString + } + + Rectangle{ + id: copyButton + color: "#808080" + radius: 3 + height: 20 + width: copyButtonText.width + 8 + anchors.right: parent.right + visible: addressLine.text !== "" + + Text { + id: copyButtonText + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.family: Style.fontRegular.name + font.pixelSize: 12 + font.bold: true + text: qsTr("Copy") + translationManager.emptyString + color: "black" + } + + MouseArea { + cursorShape: Qt.PointingHandCursor + anchors.fill: parent + hoverEnabled: true + onClicked: { + if (addressLine.text.length > 0) { + console.log(addressLine.text + " copied to clipboard"); + clipboard.setText(addressLine.text); + appWindow.showStatusMessage(qsTr("Address copied to clipboard"), 3); + } + } + onEntered: { + copyButton.color = "#707070"; + copyButtonText.opacity = 0.8; + } + onExited: { + copyButtonText.opacity = 1.0; + copyButton.color = "#808080"; + } + } } } LineEdit { @@ -292,55 +288,98 @@ Rectangle { addressLine.cursorPosition = 0 oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed")) } else { - oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed")) + oa_message(qsTr("No address found")) } - } else { - oa_message(qsTr("Internal error")) - } - } else { - oa_message(qsTr("Internal error")) } - } else { - oa_message(qsTr("No address found")) + onEntered: { + resolveButton.color = "#707070"; + resolveButtonText.opacity = 0.8; + } + onExited: { + resolveButtonText.opacity = 1.0; + resolveButton.color = "#808080"; + } } } - // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } + } + + InputMulti { +// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } + id: addressLine + readOnly: false + anchors.top: inputLabelRect.bottom + placeholderText: "4..." + Layout.fillWidth: true + + Rectangle { + color: "transparent" + border.width: 1 + border.color: { + if(addressLine.error && addressLine.text !== ""){ + return Qt.rgba(255, 0, 0, 0.45); + } else if(addressLine.activeFocus){ + return Qt.rgba(255, 255, 255, 0.35); + } else { + return Qt.rgba(255, 255, 255, 0.25); + } + } + radius: 4 + anchors.fill: parent + } } } - Label { - id: paymentIdLabel - text: qsTr("Payment ID ( Optional )") + translationManager.emptyString + StandardButton { + id: qrfinderButton + text: qsTr("QR Code") + translationManager.emptyString + shadowReleasedColor: "#FF4304" + shadowPressedColor: "#B32D00" + releasedColor: "#FF6C3C" + pressedColor: "#FF4304" + visible : appWindow.qrScannerEnabled + enabled : visible + width: visible ? 60 * scaleRatio : 0 + onClicked: { + cameraUi.state = "Capture" + cameraUi.qrcode_decoded.connect(updateFromQrCode) + } } + } + RowLayout { // payment id input LineEdit { id: paymentIdLine + labelText: qsTr("Payment ID ( Optional )") + translationManager.emptyString placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString Layout.fillWidth: true } + } - Label { - text: qsTr("Description ( Optional )") - + translationManager.emptyString - } - + RowLayout { LineEdit { id: descriptionLine + labelText: qsTr("Description ( Optional )") + translationManager.emptyString placeholderText: qsTr("Saved to local wallet history") + translationManager.emptyString Layout.fillWidth: true } + } + RowLayout { StandardButton { id: sendButton Layout.bottomMargin: 17 * scaleRatio Layout.topMargin: 17 * scaleRatio text: qsTr("Send") + translationManager.emptyString +<<<<<<< HEAD shadowReleasedColor: "#FF4304" shadowPressedColor: "#B32D00" releasedColor: "#FF6C3C" pressedColor: "#FF4304" enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype) +======= + enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet) +>>>>>>> Transfer page QML development onClicked: { console.log("Transfer: paymentClicked") var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority @@ -390,7 +429,7 @@ Rectangle { anchors.leftMargin: 17 * scaleRatio anchors.topMargin: 17 * scaleRatio anchors.bottomMargin: 17 * scaleRatio - spacing: 10 * scaleRatio + spacing: 20 * scaleRatio enabled: !viewOnly || pageRoot.enabled RowLayout { @@ -433,8 +472,6 @@ Rectangle { } } - - PrivacyLevel { visible: persistentSettings.transferShowAdvanced && !isMobile id: privacyLevelItem From bfd2a63aca982465f3f7f473b580e6b440372fdc Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 14:10:45 +0100 Subject: [PATCH 050/126] Lowering default font size to 18 for input boxes --- components/Input.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/Input.qml b/components/Input.qml index 6643af14..55a9cde5 100644 --- a/components/Input.qml +++ b/components/Input.qml @@ -29,10 +29,12 @@ import QtQuick.Controls 2.2 import QtQuick 2.10 import "." 1.0 +import "../components" + TextField { font.family: Style.fontRegular.name - font.pixelSize: 22 + font.pixelSize: 18 * scaleRatio font.bold: true horizontalAlignment: TextInput.AlignLeft selectByMouse: true From fb40d137f87e569cc968911d97212b897b8294c9 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 14:11:06 +0100 Subject: [PATCH 051/126] Hover effects for inlineButton --- components/InlineButton.qml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/components/InlineButton.qml b/components/InlineButton.qml index 9e3f3c04..11439369 100644 --- a/components/InlineButton.qml +++ b/components/InlineButton.qml @@ -42,11 +42,6 @@ Item { property alias text: inlineText.text signal clicked() - anchors.top: parent.top - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.topMargin: 8 - function doClick() { // Android workaround releaseFocus(); @@ -76,9 +71,18 @@ Item { MouseArea { id: buttonArea - cursorShape: Qt.PointingHandCursor + cursorShape: rect.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + hoverEnabled: true anchors.fill: parent onClicked: doClick() + onEntered: { + rect.color = "#707070"; + rect.opacity = 0.8; + } + onExited: { + rect.opacity = 1.0; + rect.color = "#808080"; + } } } From d77e045f5d9e411c9f646e4b1ea2c18d1540ae09 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 14:50:43 +0100 Subject: [PATCH 052/126] Added InputMulti - multiline inputbox --- components/InputMulti.qml | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 components/InputMulti.qml diff --git a/components/InputMulti.qml b/components/InputMulti.qml new file mode 100644 index 00000000..3bc194fd --- /dev/null +++ b/components/InputMulti.qml @@ -0,0 +1,53 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick.Controls 2.2 + +import QtQuick 2.10 +import "." 1.0 + + +TextArea { + property bool error: false + property bool addressValidation: false + id: textArea + font.family: Style.fontRegular.name + font.pixelSize: 18 * scaleRatio + font.bold: true + horizontalAlignment: TextInput.AlignLeft + selectByMouse: true + color: "white" + wrapMode: Text.WrapAnywhere + onTextChanged: { + if(addressValidation){ + // js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }` + textArea.text = textArea.text.replace(/[^a-z0-9]/gi,''); + TextArea.cursorPosition = textArea.text.length; + } + } +} From df21e36f5b9f356061a5665040b1675f16efabb4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 16:14:58 +0100 Subject: [PATCH 053/126] Removing copy button for addressLine, fixing margins for advanced options --- pages/Transfer.qml | 47 +++------------------------------------------- 1 file changed, 3 insertions(+), 44 deletions(-) diff --git a/pages/Transfer.qml b/pages/Transfer.qml index ae6ab7fa..8e82001a 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -262,51 +262,11 @@ Rectangle { } } } - LineEdit { - id: addressLine - Layout.fillWidth: true - anchors.topMargin: 5 * scaleRatio - placeholderText: "4..." - inlineButtonText: qsTr("Resolve") + translationManager.emptyString - inlineButton.enabled: isValidOpenAliasAddress(addressLine.text) - inlineButton.onClicked: { - var result = walletManager.resolveOpenAlias(addressLine.text) - if (result) { - var parts = result.split("|") - if (parts.length == 2) { - var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype) - if (parts[0] === "true") { - if (address_ok) { - addressLine.text = parts[1] - addressLine.cursorPosition = 0 - } - else - oa_message(qsTr("No valid address found at this OpenAlias address")) - } else if (parts[0] === "false") { - if (address_ok) { - addressLine.text = parts[1] - addressLine.cursorPosition = 0 - oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed")) - } else { - oa_message(qsTr("No address found")) - } - } - onEntered: { - resolveButton.color = "#707070"; - resolveButtonText.opacity = 0.8; - } - onExited: { - resolveButtonText.opacity = 1.0; - resolveButton.color = "#808080"; - } - } - } - } InputMulti { -// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } id: addressLine readOnly: false + addressValidation: true anchors.top: inputLabelRect.bottom placeholderText: "4..." Layout.fillWidth: true @@ -426,9 +386,8 @@ Rectangle { anchors.top: pageRoot.bottom anchors.left: parent.left anchors.right: parent.right - anchors.leftMargin: 17 * scaleRatio - anchors.topMargin: 17 * scaleRatio - anchors.bottomMargin: 17 * scaleRatio + anchors.margins: (isMobile)? 17 : 40 + anchors.topMargin: 40 * scaleRatio spacing: 20 * scaleRatio enabled: !viewOnly || pageRoot.enabled From 8c44c4c8426a4368e063ae1286276b2fd5519468 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 22:52:36 +0100 Subject: [PATCH 054/126] Adressbook QML development --- components/AddressBookTable.qml | 6 +++--- pages/AddressBook.qml | 30 ++++++++---------------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/components/AddressBookTable.qml b/components/AddressBookTable.qml index e542900c..b27e2082 100644 --- a/components/AddressBookTable.qml +++ b/components/AddressBookTable.qml @@ -37,13 +37,13 @@ ListView { footer: Rectangle { height: 127 width: listView.width - color: "#FFFFFF" + color: "transparent" Text { anchors.centerIn: parent font.family: "Arial" font.pixelSize: 14 - color: "#545454" + color: "#808080" text: qsTr("No more results") + translationManager.emptyString } } @@ -164,7 +164,7 @@ ListView { anchors.right: parent.right anchors.bottom: parent.bottom height: 1 - color: "#DBDBDB" + color: "#808080" } } } diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml index 4b406af8..0e4f6b4c 100644 --- a/pages/AddressBook.qml +++ b/pages/AddressBook.qml @@ -34,7 +34,7 @@ import moneroComponents.AddressBookModel 1.0 Rectangle { id: root - color: "#F0EEEE" + color: "transparent" property var model ColumnLayout { @@ -44,12 +44,6 @@ Rectangle { anchors.right: parent.right spacing: 10 * scaleRatio - Label { - id: addressLabel - anchors.left: parent.left - text: qsTr("Address") + translationManager.emptyString - } - RowLayout { StandardButton { id: qrfinderButton @@ -70,32 +64,25 @@ Rectangle { LineEdit { Layout.fillWidth: true; id: addressLine + labelText: qsTr("Address") + translationManager.emptyString error: true; placeholderText: qsTr("4...") + translationManager.emptyString } } - Label { - id: paymentIdLabel - text: qsTr("Payment ID (Optional)") + translationManager.emptyString - tipText: qsTr("Payment ID

A unique user name used in
the address book. It is not a
transfer of information sent
during the transfer") - + translationManager.emptyString - } - LineEdit { id: paymentIdLine Layout.fillWidth: true; + labelText: qsTr("Payment ID (Optional)") + translationManager.emptyString placeholderText: qsTr("Paste 64 hexadecimal characters") + translationManager.emptyString - } - - Label { - id: descriptionLabel - text: qsTr("Description (Optional)") + translationManager.emptyString +// tipText: qsTr("Payment ID

A unique user name used in
the address book. It is not a
transfer of information sent
during the transfer") +// + translationManager.emptyString } LineEdit { id: descriptionLine Layout.fillWidth: true; + labelText: qsTr("Description (Optional)") + translationManager.emptyString placeholderText: qsTr("Give this entry a name or description") + translationManager.emptyString } @@ -132,7 +119,6 @@ Rectangle { } } } - } Rectangle { @@ -141,7 +127,7 @@ Rectangle { anchors.right: parent.right anchors.bottom: parent.bottom height: parent.height - addButton.y - addButton.height - 36 * scaleRatio - color: "#FFFFFF" + color: "transparent" Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.InQuad } @@ -152,7 +138,7 @@ Rectangle { anchors.right: parent.right anchors.top: parent.top height: 1 - color: "#DBDBDB" + color: "#808080" } Scroll { From 8295b9dffd71e859f3738a8b58e0d1c1fea7b9d9 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 22:54:55 +0100 Subject: [PATCH 055/126] Checkbox QML development --- components/CheckBox.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/CheckBox.qml b/components/CheckBox.qml index 0ae8cb04..5e7066b1 100644 --- a/components/CheckBox.qml +++ b/components/CheckBox.qml @@ -52,9 +52,10 @@ RowLayout { anchors.left: parent.left width: 25 * scaleRatio height: checkBox.height - 1 - //radius: 4 + radius: 3 y: 0 - color: "#DBDBDB" + color: "transparent" + border.color: Qt.rgba(1, 1, 1, 0.25) } Rectangle { @@ -64,7 +65,7 @@ RowLayout { height: checkBox.height - 1 //radius: 4 y: 1 - color: "#FFFFFF" + color: "transparent" Image { anchors.centerIn: parent From 3d5fee0a2f20d0456f9ec80c4c1779df0fa6e392 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 6 Dec 2017 22:55:39 +0100 Subject: [PATCH 056/126] StandardButton/StandardDropdown QML development --- components/StandardButton.qml | 48 +++++++++++++++++---------------- components/StandardDropdown.qml | 13 +++++---- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/components/StandardButton.qml b/components/StandardButton.qml index 99917752..b7c020e9 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -28,17 +28,18 @@ import QtQuick 2.0 import QtQuick.Layouts 1.1 +import "." 1.0 Item { id: button height: 37 * scaleRatio - property string shadowPressedColor: "#B32D00" - property string shadowReleasedColor: "#FF4304" - property string pressedColor: "#FF4304" - property string releasedColor: "#FF6C3C" + property string shadowPressedColor: Style.buttonBackgroundColor + property string shadowReleasedColor: Style.buttonBackgroundColor + property string pressedColor: Style.buttonBackgroundColor + property string releasedColor: Style.buttonBackgroundColor property string icon: "" - property string textColor: "#FFFFFF" - property int fontSize: 12 * scaleRatio + property string textColor: button.enabled? Style.buttonTextColor: Style.buttonTextColorDisabled + property int fontSize: 18 * scaleRatio property alias text: label.text signal clicked() @@ -56,30 +57,31 @@ Item { anchors.right: parent.right height: parent.height - 1 y: buttonArea.pressed ? 0 : 1 - //radius: 4 - color: { - parent.enabled ? (buttonArea.pressed ? parent.shadowPressedColor : parent.shadowReleasedColor) - : Qt.lighter(parent.shadowReleasedColor) - } + radius: 3 + color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled +// color: { +// parent.enabled ? (buttonArea.pressed ? parent.shadowPressedColor : parent.shadowReleasedColor) +// : Qt.lighter(parent.shadowReleasedColor) +// } border.color: Qt.darker(parent.releasedColor) border.width: parent.focus ? 1 : 0 } - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: parent.height - 1 - y: buttonArea.pressed ? 1 : 0 - color: { - parent.enabled ? (buttonArea.pressed ? parent.pressedColor : parent.releasedColor) - : Qt.lighter(parent.releasedColor) +// Rectangle { +// anchors.left: parent.left +// anchors.right: parent.right +// height: parent.height - 1 +// y: buttonArea.pressed ? 1 : 0 +// color: { +// parent.enabled ? (buttonArea.pressed ? parent.pressedColor : parent.releasedColor) +// : Qt.lighter(parent.releasedColor) - } - //radius: 4 +// } +// //radius: 4 - } +// } Text { id: label @@ -87,7 +89,7 @@ Item { anchors.left: parent.left anchors.right: parent.right horizontalAlignment: Text.AlignHCenter - font.family: "Arial" + font.family: Style.fontBold.name font.bold: true font.pixelSize: button.fontSize color: parent.textColor diff --git a/components/StandardDropdown.qml b/components/StandardDropdown.qml index 91a514eb..2818541e 100644 --- a/components/StandardDropdown.qml +++ b/components/StandardDropdown.qml @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 +import "." 1.0 Item { id: dropdown @@ -175,10 +176,10 @@ Item { anchors.right: col2Text.left anchors.leftMargin: 12 * scaleRatio anchors.rightMargin: column2.length > 0 ? 12 * scaleRatio: 0 - font.family: "Arial" + font.family: Style.fontRegular.name font.bold: true - font.pixelSize: 12 * scaleRatio - color: "#FFFFFF" + font.pixelSize: 14 * scaleRatio + color: itemArea.containsMouse || index === column.currentIndex || itemArea.containsMouse ? "#FA6800" : "#FFFFFF" text: qsTr(column1) + translationManager.emptyString } @@ -187,8 +188,8 @@ Item { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: 45 * scaleRatio - font.family: "Arial" - font.pixelSize: 12 * scaleRatio + font.family: Style.fontRegular.name + font.pixelSize: 14 * scaleRatio color: "#FFFFFF" text: column2 } @@ -211,6 +212,8 @@ Item { id: itemArea anchors.fill: parent hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { dropdown.expanded = false column.currentIndex = index From 5cd38c5aa7085cc53c566203987a4c2135e21a35 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 7 Dec 2017 16:12:21 +0100 Subject: [PATCH 057/126] Updating QRC --- qml.qrc | 1 + 1 file changed, 1 insertion(+) diff --git a/qml.qrc b/qml.qrc index d17b7dd6..8155a77d 100644 --- a/qml.qrc +++ b/qml.qrc @@ -190,5 +190,6 @@ images/moneroIcon-28x28.png images/lightning-white.png images/middlePanelBg.jpg + components/InputMulti.qml From 5028491ab3791673fbb21abdeec978da83f222ee Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 7 Dec 2017 16:22:30 +0100 Subject: [PATCH 058/126] Added new checkbox checked icon --- components/CheckBox.qml | 6 +++--- images/checkedIcon-black.png | Bin 0 -> 17932 bytes pages/Transfer.qml | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) create mode 100755 images/checkedIcon-black.png diff --git a/components/CheckBox.qml b/components/CheckBox.qml index 5e7066b1..4ca687b4 100644 --- a/components/CheckBox.qml +++ b/components/CheckBox.qml @@ -55,7 +55,7 @@ RowLayout { radius: 3 y: 0 color: "transparent" - border.color: Qt.rgba(1, 1, 1, 0.25) + border.color: checkBox.checked ? Qt.rgba(1, 1, 1, 0.35) : Qt.rgba(1, 1, 1, 0.25) } Rectangle { @@ -69,8 +69,8 @@ RowLayout { Image { anchors.centerIn: parent - source: checkBox.checked ? checkBox.checkedIcon : - checkBox.uncheckedIcon + source: checkBox.checkedIcon + visible: checkBox.checked } MouseArea { diff --git a/images/checkedIcon-black.png b/images/checkedIcon-black.png new file mode 100755 index 0000000000000000000000000000000000000000..a1c5a1f4f73d34214d919eac7854bf099e0a4974 GIT binary patch literal 17932 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 WnrL? Date: Thu, 7 Dec 2017 16:35:42 +0100 Subject: [PATCH 059/126] Replacing checkbox, using default values from component --- components/CheckBox.qml | 2 +- pages/History.qml | 2 -- pages/Mining.qml | 4 ---- pages/Transfer.qml | 9 --------- qml.qrc | 1 + wizard/WizardConfigure.qml | 6 ------ wizard/WizardDaemonSettings.qml | 4 ---- wizard/WizardDonation.qml | 4 ---- wizard/WizardOptions.qml | 23 +---------------------- 9 files changed, 3 insertions(+), 52 deletions(-) diff --git a/components/CheckBox.qml b/components/CheckBox.qml index 4ca687b4..8486eedc 100644 --- a/components/CheckBox.qml +++ b/components/CheckBox.qml @@ -32,7 +32,7 @@ import QtQuick.Layouts 1.1 RowLayout { id: checkBox property alias text: label.text - property string checkedIcon + property string checkedIcon: "../images/checkedIcon-black.png" property string uncheckedIcon property bool checked: false property alias background: backgroundRect.color diff --git a/pages/History.qml b/pages/History.qml index 5ea27ca7..1642f3bc 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -291,8 +291,6 @@ Rectangle { anchors.left: filterButton.right anchors.bottom: filterButton.bottom anchors.leftMargin: 17 - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" onClicked: { if(checked) tableRect.height = Qt.binding(function(){ return tableRect.collapsedHeight }) else tableRect.height = Qt.binding(function(){ return tableRect.middleHeight }) diff --git a/pages/Mining.qml b/pages/Mining.qml index 0f0b370b..be2b1805 100644 --- a/pages/Mining.qml +++ b/pages/Mining.qml @@ -102,8 +102,6 @@ Rectangle { checked: persistentSettings.allow_background_mining onClicked: {persistentSettings.allow_background_mining = checked} text: qsTr("Background mining (experimental)") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" } } @@ -118,8 +116,6 @@ Rectangle { checked: !persistentSettings.miningIgnoreBattery onClicked: {persistentSettings.miningIgnoreBattery = !checked} text: qsTr("Enable mining when running on battery") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" } } diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 83e6d0a2..7296d190 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -331,15 +331,7 @@ Rectangle { Layout.bottomMargin: 17 * scaleRatio Layout.topMargin: 17 * scaleRatio text: qsTr("Send") + translationManager.emptyString -<<<<<<< HEAD - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype) -======= enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet) ->>>>>>> Transfer page QML development onClicked: { console.log("Transfer: paymentClicked") var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority @@ -399,7 +391,6 @@ Rectangle { persistentSettings.transferShowAdvanced = !persistentSettings.transferShowAdvanced } text: qsTr("Show advanced options") + translationManager.emptyString - checkedIcon: "../images/checkedIcon-black.png" } } diff --git a/qml.qrc b/qml.qrc index 8155a77d..18aa7da3 100644 --- a/qml.qrc +++ b/qml.qrc @@ -191,5 +191,6 @@ images/lightning-white.png images/middlePanelBg.jpg components/InputMulti.qml + images/checkedIcon-black.png diff --git a/wizard/WizardConfigure.qml b/wizard/WizardConfigure.qml index 88d10a31..c7184f95 100644 --- a/wizard/WizardConfigure.qml +++ b/wizard/WizardConfigure.qml @@ -100,8 +100,6 @@ Item { background: "#F0EEEE" fontColor: "#4A4646" fontSize: 18 - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: true } @@ -129,8 +127,6 @@ Item { background: "#F0EEEE" fontColor: "#4A4646" fontSize: 18 - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: true } @@ -160,8 +156,6 @@ Item { background: "#F0EEEE" fontColor: "#4A4646" fontSize: 18 - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: true } diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index ca15fc44..419e3cd5 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -127,8 +127,6 @@ ColumnLayout { background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: !appWindow.persistentSettings.useRemoteNode && !isAndroid && !isIOS visible: !isAndroid && !isIOS onClicked: { @@ -189,8 +187,6 @@ ColumnLayout { background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: appWindow.persistentSettings.useRemoteNode onClicked: { checked = true diff --git a/wizard/WizardDonation.qml b/wizard/WizardDonation.qml index 1fccbebb..a5ebb6cc 100644 --- a/wizard/WizardDonation.qml +++ b/wizard/WizardDonation.qml @@ -114,8 +114,6 @@ Item { background: "#F0EEEE" fontColor: "#4A4646" fontSize: 18 - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: true } @@ -179,8 +177,6 @@ Item { background: "#F0EEEE" fontColor: "#4A4646" fontSize: 18 - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" checked: true } diff --git a/wizard/WizardOptions.qml b/wizard/WizardOptions.qml index 7a9ffa62..d0e6b930 100644 --- a/wizard/WizardOptions.qml +++ b/wizard/WizardOptions.qml @@ -248,28 +248,7 @@ ColumnLayout { background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" - checked: appWindow.persistentSettings.nettype === NetworkType.TESTNET; - onClicked: { - persistentSettings.nettype = testNet.checked ? NetworkType.TESTNET : NetworkType.MAINNET - stageNet.checked = false; - console.log("Network type set to ", persistentSettings.nettype === NetworkType.TESTNET ? "Testnet" : "Mainnet") - } - } - } - - Rectangle { - width: 100 * scaleRatio - CheckBox { - id: stageNet - text: qsTr("Stagenet") + translationManager.emptyString - background: "#FFFFFF" - fontColor: "#4A4646" - fontSize: 16 * scaleRatio - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" - checked: appWindow.persistentSettings.nettype === NetworkType.STAGENET; + checked: appWindow.persistentSettings.testnet; onClicked: { persistentSettings.nettype = stageNet.checked ? NetworkType.STAGENET : NetworkType.MAINNET testNet.checked = false; From 22792df5cdafec98da0a6045ee7c0f81ebed5ce2 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 7 Dec 2017 17:01:16 +0100 Subject: [PATCH 060/126] Hide the custom titlebar when custom decorations are turned off --- main.qml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/main.qml b/main.qml index d23069d0..d8b4b0c2 100644 --- a/main.qml +++ b/main.qml @@ -237,7 +237,10 @@ ApplicationWindow { persistentSettings.nettype); } + // Hide titlebar based on persistentSettings.customDecorations + titleBar.visible = persistentSettings.customDecorations; } + function closeWallet() { // Disconnect all listeners @@ -928,11 +931,14 @@ ApplicationWindow { x = 0 if (y < 0) y = 0 - persistentSettings.customDecorations = custom + persistentSettings.customDecorations = custom; + titleBar.visible = custom; // hides custom titlebar based on customDecorations + if (custom) - appWindow.flags = Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint + appWindow.flags = Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint; else - appWindow.flags = Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint | Qt.WindowMaximizeButtonHint + appWindow.flags = Qt.WindowSystemMenuHint | Qt.Window | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint | Qt.WindowMaximizeButtonHint; + appWindow.hide() appWindow.x = x appWindow.y = y From 868fbe2f2d19681c84c432b472e86328c7c6e61d Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 7 Dec 2017 17:33:46 +0100 Subject: [PATCH 061/126] Move default font color to Style.qml --- components/Input.qml | 3 +-- components/InputMulti.qml | 2 +- components/Label.qml | 6 ++++-- components/LineEdit.qml | 2 +- components/Style.qml | 3 +++ components/TextBlock.qml | 4 ++++ pages/Transfer.qml | 21 +++------------------ 7 files changed, 17 insertions(+), 24 deletions(-) diff --git a/components/Input.qml b/components/Input.qml index 55a9cde5..c168e8e6 100644 --- a/components/Input.qml +++ b/components/Input.qml @@ -29,7 +29,6 @@ import QtQuick.Controls 2.2 import QtQuick 2.10 import "." 1.0 -import "../components" TextField { @@ -38,7 +37,7 @@ TextField { font.bold: true horizontalAlignment: TextInput.AlignLeft selectByMouse: true - color: "white" + color: Style.defaultFontColor background: Rectangle { color: "transparent" diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 3bc194fd..0f030f2d 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -41,7 +41,7 @@ TextArea { font.bold: true horizontalAlignment: TextInput.AlignLeft selectByMouse: true - color: "white" + color: Style.defaultFontColor wrapMode: Text.WrapAnywhere onTextChanged: { if(addressValidation){ diff --git a/components/Label.qml b/components/Label.qml index 3de0eadb..86618c9e 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -29,6 +29,8 @@ import QtQuick 2.0 import QtQuick.Layouts 1.1 +import "." 1.0 + Item { id: item property alias text: label.text @@ -49,10 +51,10 @@ Item { anchors.bottom: parent.bottom anchors.bottomMargin: 2 * scaleRatio anchors.left: parent.left - font.family: "Arial" + font.family: Style.fontRegular.name font.pixelSize: fontSize font.bold: fontBold - color: "white" + color: Style.defaultFontColor onLinkActivated: item.linkActivated() } diff --git a/components/LineEdit.qml b/components/LineEdit.qml index debc396d..b1ef6ee6 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -95,7 +95,7 @@ Item { font.pixelSize: labelFontSize font.bold: labelFontBold textFormat: Text.RichText - color: "white" + color: Style.defaultFontColor onLinkActivated: item.labelLinkActivated() MouseArea { diff --git a/components/Style.qml b/components/Style.qml index 2cab3cfe..b7077095 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -8,6 +8,7 @@ QtObject { property QtObject fontLight: FontLoader { id: _fontLight; source: "qrc:/fonts/SFUIDisplay-Light.otf"; } property QtObject fontRegular: FontLoader { id: _fontRegular; source: "qrc:/fonts/SFUIDisplay-Regular.otf"; } + property string defaultFontColor: "white" property string inputBoxBackground: "black" property string inputBoxBackgroundError: "#FFDDDD" property string inputBoxColor: "white" @@ -15,4 +16,6 @@ QtObject { property string buttonBackgroundColorDisabled: "#3B3B3B" property string buttonTextColor: "white" property string buttonTextColorDisabled: "black" + property string dividerColor: "white" + property real dividerOpacity: 0.25 } diff --git a/components/TextBlock.qml b/components/TextBlock.qml index 684b6240..875a4bf7 100644 --- a/components/TextBlock.qml +++ b/components/TextBlock.qml @@ -1,6 +1,10 @@ import QtQuick 2.0 +import "." 1.0 + TextEdit { + color: Style.defaultFontColor + font.family: Style.fontRegular.name wrapMode: Text.Wrap readOnly: true selectByMouse: true diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 7296d190..80604763 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -213,7 +213,7 @@ Rectangle { font.pixelSize: 16 * scaleRatio font.bold: labelFontBold textFormat: Text.RichText - color: "white" + color: Style.defaultFontColor onLinkActivated: { appWindow.showPageRequest("AddressBook") } text: qsTr("\ Address ( Address book )") @@ -292,10 +292,6 @@ Rectangle { StandardButton { id: qrfinderButton text: qsTr("QR Code") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible : appWindow.qrScannerEnabled enabled : visible width: visible ? 60 * scaleRatio : 0 @@ -398,7 +394,8 @@ Rectangle { visible: persistentSettings.transferShowAdvanced Layout.fillWidth: true height: 1 - color: "#DEDEDE" + color: Style.dividerColor + opacity: Style.dividerOpacity Layout.bottomMargin: 30 * scaleRatio } @@ -450,10 +447,6 @@ Rectangle { StandardButton { id: sweepUnmixableButton text: qsTr("Sweep Unmixable") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled : pageRoot.enabled onClicked: { console.log("Transfer: sweepUnmixableClicked") @@ -464,10 +457,6 @@ Rectangle { StandardButton { id: saveTxButton text: qsTr("Create tx file") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: appWindow.viewOnly enabled: pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype) onClicked: { @@ -486,10 +475,6 @@ Rectangle { StandardButton { id: signTxButton text: qsTr("Sign tx file") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: !appWindow.viewOnly onClicked: { console.log("Transfer: sign tx clicked") From 948669edbc6eecc84d6f5193fd3093d814bcdab4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 7 Dec 2017 17:34:12 +0100 Subject: [PATCH 062/126] Move default divider/button colors to Style.qml --- pages/Settings.qml | 70 ++++++++-------------------------------------- 1 file changed, 11 insertions(+), 59 deletions(-) diff --git a/pages/Settings.qml b/pages/Settings.qml index f9d1e3bc..37ed928e 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -41,7 +41,7 @@ Rectangle { property bool viewOnly: false id: page - color: "#F0EEEE" + color: "transparent" Clipboard { id: clipboard } @@ -62,7 +62,6 @@ Rectangle { Label { id: manageWalletLabel Layout.fillWidth: true - color: "#4A4949" text: qsTr("Manage wallet") + translationManager.emptyString Layout.topMargin: 10 * scaleRatio } @@ -71,7 +70,8 @@ Rectangle { Rectangle { Layout.fillWidth: true height: 1 - color: "#DEDEDE" + color: Style.dividerColor + opacity: Style.dividerOpacity } GridLayout { @@ -79,10 +79,6 @@ Rectangle { StandardButton { id: closeWalletButton text: qsTr("Close wallet") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: true onClicked: { console.log("closing wallet button clicked") @@ -94,10 +90,6 @@ Rectangle { enabled: !viewOnly id: createViewOnlyWalletButton text: qsTr("Create view only wallet") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: true onClicked: { wizard.openCreateViewOnlyWalletPage(); @@ -143,10 +135,6 @@ Rectangle { id: rescanSpentButton enabled: !persistentSettings.useRemoteNode text: qsTr("Rescan wallet balance") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { if (!currentWallet.rescanSpent()) { console.error("Error: ", currentWallet.errorString); @@ -199,10 +187,6 @@ Rectangle { enabled: persistentSettings.useRemoteNode Layout.fillWidth: false text: qsTr("Local Node") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { appWindow.disconnectRemoteNode(); } @@ -213,10 +197,6 @@ Rectangle { enabled: !persistentSettings.useRemoteNode Layout.fillWidth: false text: qsTr("Remote Node") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { appWindow.connectRemoteNode(); } @@ -229,7 +209,6 @@ Rectangle { Layout.topMargin: 20 Label { id: manageDaemonLabel - color: "#4A4949" text: qsTr("Manage Daemon") + translationManager.emptyString } @@ -237,14 +216,13 @@ Rectangle { id: daemonAdvanced Layout.leftMargin: 15 text: qsTr("Show advanced") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" } } Rectangle { Layout.fillWidth: true height: 1 - color: "#DEDEDE" + color: Style.dividerColor + opacity: Style.dividerOpacity } GridLayout { @@ -255,10 +233,6 @@ Rectangle { visible: !appWindow.daemonRunning id: startDaemonButton text: qsTr("Start Local Node") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { // Update bootstrap daemon address persistentSettings.bootstrapNodeAddress = bootstrapNodeEdit.daemonAddrText ? bootstrapNodeEdit.getAddress() : ""; @@ -273,10 +247,6 @@ Rectangle { visible: appWindow.daemonRunning id: stopDaemonButton text: qsTr("Stop Local Node") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { appWindow.stopDaemon() } @@ -286,10 +256,6 @@ Rectangle { visible: true id: daemonStatusButton text: qsTr("Show status") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { daemonManager.sendCommand("status",currentWallet.nettype); daemonConsolePopup.open(); @@ -302,7 +268,6 @@ Rectangle { visible: !isMobile && !persistentSettings.useRemoteNode Label { id: blockchainFolderLabel - color: "#4A4949" text: qsTr("Blockchain location") + translationManager.emptyString } LineEdit { @@ -332,7 +297,6 @@ Rectangle { id: daemonFlagsRow Label { id: daemonFlagsLabel - color: "#4A4949" text: qsTr("Local daemon startup flags") + translationManager.emptyString } LineEdit { @@ -350,7 +314,6 @@ Rectangle { Label { id: daemonLoginLabel Layout.fillWidth: true - color: "#4A4949" text: qsTr("Node login (optional)") + translationManager.emptyString } @@ -401,7 +364,6 @@ Rectangle { visible: persistentSettings.useRemoteNode ColumnLayout { Label { - color: "#4A4949" text: qsTr("Remote node") + translationManager.emptyString } RemoteNodeEdit { @@ -419,10 +381,6 @@ Rectangle { StandardButton { id: remoteNodeSave text: qsTr("Connect") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { // Update daemon login persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); @@ -441,7 +399,6 @@ Rectangle { RowLayout { visible: !isMobile Label { - color: "#4A4949" text: qsTr("Layout settings") + translationManager.emptyString anchors.topMargin: 30 * scaleRatio Layout.topMargin: 30 * scaleRatio @@ -451,7 +408,8 @@ Rectangle { visible: !isMobile Layout.fillWidth: true height: 1 - color: "#DEDEDE" + color: Style.dividerColor + opacity: Style.dividerOpacity } RowLayout { @@ -461,8 +419,6 @@ Rectangle { checked: persistentSettings.customDecorations onClicked: appWindow.setCustomWindowDecorations(checked) text: qsTr("Custom decorations") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" - uncheckedIcon: "../images/uncheckedIcon.png" } } @@ -470,7 +426,6 @@ Rectangle { RowLayout { Label { - color: "#4A4949" text: qsTr("Log level") + translationManager.emptyString anchors.topMargin: 30 * scaleRatio Layout.topMargin: 30 * scaleRatio @@ -479,7 +434,8 @@ Rectangle { Rectangle { Layout.fillWidth: true height: 1 - color: "#DEDEDE" + color: Style.dividerColor + opacity: Style.dividerOpacity } ColumnLayout { ComboBox { @@ -518,7 +474,6 @@ Rectangle { // Version RowLayout { Label { - color: "#4A4949" text: qsTr("Debug info") + translationManager.emptyString fontSize: 16 anchors.topMargin: 30 * scaleRatio @@ -528,7 +483,8 @@ Rectangle { Rectangle { Layout.fillWidth: true height: 1 - color: "#DEDEDE" + color: Style.dividerColor + opacity: Style.dividerOpacity } TextBlock { Layout.topMargin: 8 @@ -572,10 +528,6 @@ Rectangle { Layout.fillWidth: false Layout.leftMargin: 30 text: qsTr("Save") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { currentWallet.walletCreationHeight = restoreHeight.text From f48cd1b82b758c7b4e396e523172f66b9b371c5b Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 7 Dec 2017 18:19:30 +0100 Subject: [PATCH 063/126] Checkbox/Standard button development --- components/CheckBox.qml | 2 ++ components/StandardButton.qml | 27 +++++++++++++++++++-------- components/Style.qml | 4 ++++ pages/Settings.qml | 1 + 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/components/CheckBox.qml b/components/CheckBox.qml index 8486eedc..f0b8ed9c 100644 --- a/components/CheckBox.qml +++ b/components/CheckBox.qml @@ -88,6 +88,8 @@ RowLayout { color: "#525252" wrapMode: Text.Wrap Layout.fillWidth: true + anchors.left: backgroundRect.right + anchors.leftMargin: !isMobile ? 10 : 8 MouseArea { anchors.fill: parent onClicked: { diff --git a/components/StandardButton.qml b/components/StandardButton.qml index b7c020e9..440505ee 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -39,12 +39,12 @@ Item { property string releasedColor: Style.buttonBackgroundColor property string icon: "" property string textColor: button.enabled? Style.buttonTextColor: Style.buttonTextColorDisabled - property int fontSize: 18 * scaleRatio + property int fontSize: 16 * scaleRatio property alias text: label.text signal clicked() // Dynamic label width - Layout.minimumWidth: (label.contentWidth > 50)? label.contentWidth + 10 : 60 + Layout.minimumWidth: (label.contentWidth > 50)? label.contentWidth + 22 : 60 function doClick() { // Android workaround @@ -56,16 +56,27 @@ Item { anchors.left: parent.left anchors.right: parent.right height: parent.height - 1 - y: buttonArea.pressed ? 0 : 1 radius: 3 color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled -// color: { -// parent.enabled ? (buttonArea.pressed ? parent.shadowPressedColor : parent.shadowReleasedColor) -// : Qt.lighter(parent.shadowReleasedColor) -// } border.color: Qt.darker(parent.releasedColor) border.width: parent.focus ? 1 : 0 + MouseArea{ + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + propagateComposedEvents: true + + onEntered: { + if(button.enabled) parent.color = Style.buttonBackgroundColorHover; + else parent.color = Style.buttonBackgroundColorDisabledHover; + } + onExited: { + if(button.enabled) parent.color = Style.buttonBackgroundColor; + else parent.color = Style.buttonBackgroundColorDisabled; + } + } } // Rectangle { @@ -91,7 +102,7 @@ Item { horizontalAlignment: Text.AlignHCenter font.family: Style.fontBold.name font.bold: true - font.pixelSize: button.fontSize + font.pixelSize: buttonArea.pressed ? button.fontSize - 1 : button.fontSize color: parent.textColor visible: parent.icon === "" // font.capitalization : Font.Capitalize diff --git a/components/Style.qml b/components/Style.qml index b7077095..256f5397 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -12,8 +12,12 @@ QtObject { property string inputBoxBackground: "black" property string inputBoxBackgroundError: "#FFDDDD" property string inputBoxColor: "white" + property string buttonBackgroundColor: "#FA6800" + property string buttonBackgroundColorHover: "#E65E00" property string buttonBackgroundColorDisabled: "#3B3B3B" + property string buttonBackgroundColorDisabledHover: "#4F4F4F" + property string buttonTextColor: "white" property string buttonTextColorDisabled: "black" property string dividerColor: "white" diff --git a/pages/Settings.qml b/pages/Settings.qml index 37ed928e..7b3c847a 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -274,6 +274,7 @@ Rectangle { id: blockchainFolder Layout.preferredWidth: 200 Layout.fillWidth: true + labelText: qsTr("Blockchain location") + translationManager.emptyString text: persistentSettings.blockchainDataDir placeholderText: qsTr("(optional)") + translationManager.emptyString From 328eb32a24eef9a59da7bd2e2f1bf22959783f45 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 8 Dec 2017 01:51:22 +0100 Subject: [PATCH 064/126] Various QML development --- components/InlineButton.qml | 9 ++++--- components/LineEdit.qml | 43 +++++++++++++++------------------ components/StandardDropdown.qml | 4 +-- components/Style.qml | 4 +-- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/components/InlineButton.qml b/components/InlineButton.qml index 11439369..77f88f3d 100644 --- a/components/InlineButton.qml +++ b/components/InlineButton.qml @@ -28,10 +28,11 @@ import QtQuick 2.0 import QtQuick.Layouts 1.1 +import "." 1.0 Item { id: inlineButton - height: 32 * scaleRatio + height: rect.height * scaleRatio property string shadowPressedColor: "#B32D00" property string shadowReleasedColor: "#FF4304" property string pressedColor: "#FF4304" @@ -50,10 +51,10 @@ Item { Rectangle{ id: rect - color: rect.enabled ? "#808080" : "#3b3b3b" + color: Style.buttonBackgroundColorDisabled border.color: "black" - height: 32 - width: inlineText.width + 22 + height: 28 * scaleRatio + width: inlineText.width + 22 * scaleRatio radius: 4 anchors.top: parent.top diff --git a/components/LineEdit.qml b/components/LineEdit.qml index b1ef6ee6..f1299519 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -40,7 +40,7 @@ Item { property alias inlineButton: inlineButtonId property alias inlineButtonText: inlineButtonId.text property alias inlineIcon: inlineIcon.visible - property alias copyButton: copyButton.visible + property bool copyButton: false property int fontSize: 18 * scaleRatio property bool showBorder: true property bool error: false @@ -78,14 +78,6 @@ Item { } } - function getColor(error) { - // @TODO: replace/remove this (implement as ternary?) - if (error) - return "transparent" - else - return "transparent" - } - Text { id: inputLabel anchors.top: parent.top @@ -106,13 +98,13 @@ Item { } Rectangle{ - id: copyButton + id: copyButtonRect color: "#808080" radius: 3 height: 20 width: 44 anchors.right: parent.right - visible: false + visible: copyButton && input.text !== "" ? true : false Text { id: copyButtonText @@ -137,19 +129,19 @@ Item { } } onEntered: { - copyButton.color = "#707070"; + copyButtonRect.color = "#707070"; copyButtonText.opacity = 0.8; } onExited: { + copyButtonRect.color = "#808080"; copyButtonText.opacity = 1.0; - copyButton.color = "#808080"; } } } Item{ id: inputItem - height: 48 * scaleRatio + height: 40 * scaleRatio anchors.top: inputLabel.bottom anchors.topMargin: 6 width: parent.width @@ -161,9 +153,9 @@ Item { anchors.left: parent.left anchors.leftMargin: inlineIcon.visible ? 50 : 10 opacity: 0.25 - color: "#FFFFFF" + color: Style.defaultFontColor font.family: Style.fontRegular.name - font.pixelSize: 20 * scaleRatio + font.pixelSize: 18 * scaleRatio text: "" z: 3 } @@ -171,24 +163,29 @@ Item { Rectangle { anchors.fill: parent anchors.topMargin: 1 * scaleRatio - color: getColor(error) - //radius: 4 + color: "transparent" } Rectangle { color: "transparent" border.width: 1 - border.color: Qt.rgba(1, 1, 1, 0.25) + border.color: { + if(input.activeFocus){ + return Qt.rgba(255, 255, 255, 0.35); + } else { + return Qt.rgba(255, 255, 255, 0.25); + } + } radius: 4 anchors.fill: parent } Image { id: inlineIcon - width: 28 * scaleRatio - height: 28 * scaleRatio + width: 26 * scaleRatio + height: 26 * scaleRatio anchors.top: parent.top - anchors.topMargin: 10 * scaleRatio + anchors.topMargin: 8 * scaleRatio anchors.left: parent.left anchors.leftMargin: 12 * scaleRatio source: "../images/moneroIcon-28x28.png" @@ -212,7 +209,7 @@ Item { anchors.right: parent.right anchors.rightMargin: 8 anchors.top: parent.top - anchors.topMargin: 8 + anchors.topMargin: 6 } } } diff --git a/components/StandardDropdown.qml b/components/StandardDropdown.qml index 2818541e..f22cbab0 100644 --- a/components/StandardDropdown.qml +++ b/components/StandardDropdown.qml @@ -42,7 +42,7 @@ Item { signal changed(); - height: 48 * scaleRatio + height: 40 * scaleRatio onExpandedChanged: if(expanded) appWindow.currentItem = dropdown function hide() { dropdown.expanded = false } @@ -68,7 +68,7 @@ Item { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - height: 48 * scaleRatio + height: 40 * scaleRatio Rectangle { color: "transparent" diff --git a/components/Style.qml b/components/Style.qml index 256f5397..5e1dd26f 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -15,8 +15,8 @@ QtObject { property string buttonBackgroundColor: "#FA6800" property string buttonBackgroundColorHover: "#E65E00" - property string buttonBackgroundColorDisabled: "#3B3B3B" - property string buttonBackgroundColorDisabledHover: "#4F4F4F" + property string buttonBackgroundColorDisabled: "#707070" + property string buttonBackgroundColorDisabledHover: "#808080" property string buttonTextColor: "white" property string buttonTextColorDisabled: "black" From de3fd183d8c40178b25bac255051fd645492204f Mon Sep 17 00:00:00 2001 From: cryptochangements34 Date: Thu, 7 Dec 2017 21:49:12 -0500 Subject: [PATCH 065/126] Re-style AddressBookTable --- components/AddressBookTable.qml | 8 ++++---- pages/AddressBook.qml | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/AddressBookTable.qml b/components/AddressBookTable.qml index b27e2082..de724bb8 100644 --- a/components/AddressBookTable.qml +++ b/components/AddressBookTable.qml @@ -53,7 +53,7 @@ ListView { id: delegate height: 64 width: listView.width - color: index % 2 ? "#F8F8F8" : "#FFFFFF" + color: index % 2 ? "#ee6000" : "#3e3e3e" z: listView.count - index function collapseDropdown() { dropdown.expanded = false } @@ -66,7 +66,7 @@ ListView { font.family: "Arial" font.bold: true font.pixelSize: 19 - color: "#444444" + color: "#ffffff" elide: Text.ElideRight text: description @@ -87,7 +87,7 @@ ListView { anchors.rightMargin: 40 font.family: "Arial" font.pixelSize: 16 - color: "#545454" + color: "#ffffff" text: address } @@ -100,7 +100,7 @@ ListView { width: 139 font.family: "Arial" font.pixelSize: 12 - color: "#535353" + color: "#ffffff" text: qsTr("Payment ID:") + translationManager.emptyString } diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml index 0e4f6b4c..b1c2bad9 100644 --- a/pages/AddressBook.qml +++ b/pages/AddressBook.qml @@ -156,6 +156,7 @@ Rectangle { anchors.right: parent.right anchors.top: parent.top anchors.bottom: parent.bottom + anchors.topMargin: 14 anchors.leftMargin: 14 anchors.rightMargin: 14 onContentYChanged: flickableScroll.flickableContentYChanged() From e5357c8a0b55a23d065021092db6118a03f29533 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 9 Dec 2017 00:01:10 +0100 Subject: [PATCH 066/126] Receive page development --- components/LineEdit.qml | 61 +++------- pages/AddressBook.qml | 4 +- pages/Receive.qml | 165 +++++++++++++++++++++----- pages/Transfer.qml | 250 ++++++++++++++++++++++++++-------------- qml.qrc | 2 + 5 files changed, 316 insertions(+), 166 deletions(-) diff --git a/components/LineEdit.qml b/components/LineEdit.qml index f1299519..d52db763 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -43,6 +43,7 @@ Item { property bool copyButton: false property int fontSize: 18 * scaleRatio property bool showBorder: true + property bool fontBold: true property bool error: false property alias labelText: inputLabel.text property alias labelColor: inputLabel.color @@ -53,7 +54,7 @@ Item { property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment signal labelLinkActivated(); // input label, rich text signal - signal editingFinished() + signal editingFinished(); signal accepted(); signal textUpdated(); @@ -82,7 +83,7 @@ Item { id: inputLabel anchors.top: parent.top anchors.left: parent.left - anchors.topMargin: 2 + anchors.topMargin: 2 * scaleRatio font.family: Style.fontRegular.name font.pixelSize: labelFontSize font.bold: labelFontBold @@ -97,53 +98,25 @@ Item { } } - Rectangle{ - id: copyButtonRect - color: "#808080" - radius: 3 - height: 20 - width: 44 + LabelButton { + id: copyButtonId + text: qsTr("Copy") anchors.right: parent.right - visible: copyButton && input.text !== "" ? true : false - - Text { - id: copyButtonText - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - font.family: Style.fontRegular.name - font.pixelSize: 12 - font.bold: true - text: "Copy" - color: "black" - } - - MouseArea { - cursorShape: Qt.PointingHandCursor - anchors.fill: parent - hoverEnabled: true - onClicked: { - if (addressLine.text.length > 0) { - console.log(addressLine.text + " copied to clipboard") - clipboard.setText(addressLine.text) - appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3) - } - } - onEntered: { - copyButtonRect.color = "#707070"; - copyButtonText.opacity = 0.8; - } - onExited: { - copyButtonRect.color = "#808080"; - copyButtonText.opacity = 1.0; + onClicked: { + if (input.text.length > 0) { + console.log(input.text + " copied to clipboard") + clipboard.setText(input.text) + appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) } } + visible: input.text && copyButton ? true : false } Item{ id: inputItem height: 40 * scaleRatio anchors.top: inputLabel.bottom - anchors.topMargin: 6 + anchors.topMargin: 6 * scaleRatio width: parent.width Text { @@ -151,7 +124,7 @@ Item { visible: input.text ? false : true anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: inlineIcon.visible ? 50 : 10 + anchors.leftMargin: inlineIcon.visible ? 50 * scaleRatio : 10 * scaleRatio opacity: 0.25 color: Style.defaultFontColor font.family: Style.fontRegular.name @@ -197,6 +170,7 @@ Item { anchors.fill: parent anchors.leftMargin: inlineIcon.visible ? 38 : 0 font.pixelSize: item.fontSize + font.bold: fontBold onEditingFinished: item.editingFinished() onAccepted: item.accepted(); onTextChanged: item.textUpdated() @@ -204,12 +178,11 @@ Item { InlineButton { id: inlineButtonId - onClicked: inlineButtonId.onClicked visible: item.inlineButtonText ? true : false anchors.right: parent.right - anchors.rightMargin: 8 + anchors.rightMargin: 8 * scaleRatio anchors.top: parent.top - anchors.topMargin: 6 + anchors.topMargin: 6 * scaleRatio } } } diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml index b1c2bad9..4613e260 100644 --- a/pages/AddressBook.qml +++ b/pages/AddressBook.qml @@ -38,11 +38,11 @@ Rectangle { property var model ColumnLayout { - anchors.margins: 17 * scaleRatio + anchors.margins: (isMobile)? 17 : 40 anchors.left: parent.left anchors.top: parent.top anchors.right: parent.right - spacing: 10 * scaleRatio + spacing: 26 * scaleRatio RowLayout { StandardButton { diff --git a/pages/Receive.qml b/pages/Receive.qml index 2b070c9f..18c5ef72 100644 --- a/pages/Receive.qml +++ b/pages/Receive.qml @@ -26,8 +26,8 @@ // 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 2.7 +import QtQuick.Controls 2.2 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.2 @@ -43,7 +43,7 @@ import moneroComponents.SubaddressModel 1.0 Rectangle { id: pageReceive - color: "#F0EEEE" + color: "transparent" property alias addressText : addressLine.text property alias paymentIdText : paymentIdLine.text property alias integratedAddressText : integratedAddressLine.text @@ -156,14 +156,14 @@ Rectangle { anchors.top: parent.top anchors.right: parent.right - spacing: 20 * scaleRatio + spacing: 26 * scaleRatio property int labelWidth: 120 * scaleRatio property int editWidth: 400 * scaleRatio property int lineEditFontSize: 12 * scaleRatio property int qrCodeSize: 240 * scaleRatio - ColumnLayout { +<<<<<<< HEAD id: addressRow Label { id: addressLabel @@ -224,43 +224,123 @@ Rectangle { inputDialog.inputText = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex) inputDialog.onAcceptedCallback = function() { appWindow.currentWallet.subaddress.setLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex, inputDialog.inputText) +======= + id: addressLineRow + + LineEditMulti { + id: addressLine + inputLabelText: qsTr("Address") + translationManager.emptyString + placeholderText: qsTr("ReadOnly wallet address displayed here") + translationManager.emptyString; + readOnly: true + Layout.fillWidth: true + copyButton: true + } + } + + GridLayout { + id: paymentIdRow + columns:2 + + // @TODO: copy button copies the wrong input box + LineEdit { + id: paymentIdLine + placeholderText: qsTr("16 hexadecimal characters") + translationManager.emptyString; + readOnly: false + onTextChanged: updatePaymentId(paymentIdLine.text) + inlineButtonText: "Generate" + inlineButton.onClicked: updatePaymentId() + width: mainLayout.editWidth + Layout.fillWidth: true + copyButton: true + labelText: qsTr("Payment ID") + qsTr("\ + ( help ) ") + + translationManager.emptyString + onLabelLinkActivated: { + trackingHowToUseDialog.title = qsTr("Tracking payments") + translationManager.emptyString; + trackingHowToUseDialog.text = qsTr( + "

This is a simple sales tracker:

" + + "

Click Generate to create a random payment id for a new customer

" + + "

Let your customer scan that QR code to make a payment (if that customer has software which " + + "supports QR code scanning).

" + + "

This page will automatically scan the blockchain and the tx pool " + + "for incoming transactions using this QR code. If you input an amount, it will also check " + + "that incoming transactions total up to that amount.

" + + "It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " + + "confirmed in short order, but there is still a possibility they might not, so for larger " + + "values you may want to wait for one or more confirmation(s).

" + ) + trackingHowToUseDialog.icon = StandardIcon.Information + trackingHowToUseDialog.open() + } + } + + // @TODO: CLEAR BUTTON should be present as labelButton +// StandardButton { +// id: clearPaymentId +// enabled: !!paymentIdLine.text +// shadowReleasedColor: "#FF4304" +// shadowPressedColor: "#B32D00" +// releasedColor: "#FF6C3C" +// pressedColor: "#FF4304" +// text: qsTr("Clear") + translationManager.emptyString; +// onClicked: updatePaymentId("") +// } + } + + ColumnLayout { + id: integratedAddressRow + + LineEditMulti { + id: integratedAddressLine + inputLabelText: qsTr("Integrated address") + translationManager.emptyString + placeholderText: qsTr("Generate payment ID for integrated address") + translationManager.emptyString + readOnly: true + Layout.fillWidth: true + copyButton: true + } + } + + GridLayout { + columns: (isMobile)? 1 : 2 + Layout.fillWidth: true + columnSpacing: 32 + + ColumnLayout { + Layout.fillWidth: true + + RowLayout { + Layout.fillWidth: true + Layout.minimumWidth: 200 + LineEdit { + id: amountLine + placeholderText: qsTr("Amount to receive") + translationManager.emptyString + readOnly: false + inlineIcon: true + labelText: qsTr("Amount") + Layout.fillWidth: true + validator: DoubleValidator { + bottom: 0.0 + top: 18446744.073709551615 + decimals: 12 + notation: DoubleValidator.StandardNotation + locale: "C" +>>>>>>> Receive page development } inputDialog.onRejectedCallback = null; inputDialog.open() } } } - } - - ColumnLayout { - id: amountRow - Label { - id: amountLabel - text: qsTr("Amount") + translationManager.emptyString - width: mainLayout.labelWidth - } - - - LineEdit { - id: amountLine -// fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Amount to receive") + translationManager.emptyString - readOnly: false - width: mainLayout.editWidth + ColumnLayout { Layout.fillWidth: true - validator: DoubleValidator { - bottom: 0.0 - top: 18446744.073709551615 - decimals: 12 - notation: DoubleValidator.StandardNotation - locale: "C" - } } } RowLayout { id: trackingRow + Layout.fillWidth: true visible: !isAndroid && !isIOS +<<<<<<< HEAD Label { id: trackingLabel textFormat: Text.RichText @@ -288,16 +368,39 @@ Rectangle { trackingHowToUseDialog.open() } } +======= +>>>>>>> Receive page development TextEdit { id: trackingLine anchors.top: trackingRow.top + horizontalAlignment: TextInput.AlignLeft + Layout.fillWidth: true textFormat: Text.RichText text: "" readOnly: true - width: mainLayout.editWidth - Layout.fillWidth: true selectByMouse: true + color: Style.defaultFontColor + font.family: Style.fontRegular.name + font.pixelSize: 16 * scaleRatio + leftPadding: 12 * scaleRatio + rightPadding: 12 * scaleRatio + topPadding: 8 * scaleRatio + bottomPadding: 8 * scaleRatio + + Rectangle { + color: "transparent" + border.width: 1 + border.color: { + if(trackingLine.activeFocus){ + return Qt.rgba(255, 255, 255, 0.35); + } else { + return Qt.rgba(255, 255, 255, 0.25); + } + } + radius: 4 + anchors.fill: parent + } } } diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 80604763..ee0d7aa4 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -113,19 +113,19 @@ Rectangle { ColumnLayout { id: pageRoot - anchors.margins: (isMobile)? 17 : 40 + anchors.margins: (isMobile)? 17 : 20 anchors.topMargin: 40 * scaleRatio anchors.left: parent.left anchors.top: parent.top anchors.right: parent.right - spacing: 20 * scaleRatio + spacing: 26 * scaleRatio GridLayout { columns: (isMobile)? 1 : 2 Layout.fillWidth: true - columnSpacing: 48 + columnSpacing: 32 ColumnLayout { Layout.fillWidth: true @@ -198,97 +198,169 @@ Rectangle { id: addressLineRow Layout.fillWidth: true - ColumnLayout { - Rectangle{ - id: inputLabelRect - color: "transparent" - Layout.fillWidth: true - height: inputLabel.height + 10 + LineEditMulti{ + id: addressLine + spacing: 0 +// @TODO: +// - fix wrong copy @ receive.qml +// - resolve button click @ multiline @ transfer.qml - Text { - id: inputLabel - anchors.top: parent.top - anchors.left: parent.left - font.family: Style.fontRegular.name - font.pixelSize: 16 * scaleRatio - font.bold: labelFontBold - textFormat: Text.RichText - color: Style.defaultFontColor - onLinkActivated: { appWindow.showPageRequest("AddressBook") } - text: qsTr("\ - Address ( Address book )") - + translationManager.emptyString - } - - Rectangle{ - id: copyButton - color: "#808080" - radius: 3 - height: 20 - width: copyButtonText.width + 8 - anchors.right: parent.right - visible: addressLine.text !== "" - - Text { - id: copyButtonText - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - font.family: Style.fontRegular.name - font.pixelSize: 12 - font.bold: true - text: qsTr("Copy") + translationManager.emptyString - color: "black" - } - - MouseArea { - cursorShape: Qt.PointingHandCursor - anchors.fill: parent - hoverEnabled: true - onClicked: { - if (addressLine.text.length > 0) { - console.log(addressLine.text + " copied to clipboard"); - clipboard.setText(addressLine.text); - appWindow.showStatusMessage(qsTr("Address copied to clipboard"), 3); - } - } - onEntered: { - copyButton.color = "#707070"; - copyButtonText.opacity = 0.8; - } - onExited: { - copyButtonText.opacity = 1.0; - copyButton.color = "#808080"; - } - } - } - } - - InputMulti { - id: addressLine - readOnly: false - addressValidation: true - anchors.top: inputLabelRect.bottom - placeholderText: "4..." - Layout.fillWidth: true - - Rectangle { - color: "transparent" - border.width: 1 - border.color: { - if(addressLine.error && addressLine.text !== ""){ - return Qt.rgba(255, 0, 0, 0.45); - } else if(addressLine.activeFocus){ - return Qt.rgba(255, 255, 255, 0.35); - } else { - return Qt.rgba(255, 255, 255, 0.25); + inputLabelText: qsTr("\ + Address ( Address book )") + + translationManager.emptyString + labelButtonText: qsTr("Resolve") + translationManager.emptyString + placeholderText: "4.." + onInputLabelLinkActivated: { appWindow.showPageRequest("AddressBook") } + onLabelButtonClicked: { + var result = walletManager.resolveOpenAlias(addressLine.text) + if (result) { + var parts = result.split("|") + if (parts.length == 2) { + var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.testnet) + if (parts[0] === "true") { + if (address_ok) { + addressLine.text = parts[1] + addressLine.cursorPosition = 0 } + else + oa_message(qsTr("No valid address found at this OpenAlias address")) + } else if (parts[0] === "false") { + if (address_ok) { + addressLine.text = parts[1] + addressLine.cursorPosition = 0 + oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed")) + } else { + oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed")) + } + } else { + oa_message(qsTr("Internal error")) } - radius: 4 - anchors.fill: parent + } else { + oa_message(qsTr("Internal error")) + } + } else { + oa_message(qsTr("No address found")) } } } +// ColumnLayout { +// spacing: 0 +// Rectangle{ +// id: inputLabelRect +// color: "transparent" +// Layout.fillWidth: true +// height: inputLabel.height + 10 + +// Text { +// id: inputLabel +// anchors.top: parent.top +// anchors.left: parent.left +// font.family: Style.fontRegular.name +// font.pixelSize: 16 * scaleRatio +// font.bold: labelFontBold +// textFormat: Text.RichText +// color: Style.defaultFontColor +// onLinkActivated: { appWindow.showPageRequest("AddressBook") } +// text: qsTr("\ +// Address ( Address book )") +// + translationManager.emptyString +// } + +// Rectangle{ +// id: resolveButton +// color: "#808080" +// radius: 3 +// height: 20 +// width: resolveButtonText.width + 8 +// anchors.right: copyButton.left +// anchors.rightMargin: 6 +// visible: isValidOpenAliasAddress(addressLine.text) + +// Text { +// id: resolveButtonText +// anchors.verticalCenter: parent.verticalCenter +// anchors.horizontalCenter: parent.horizontalCenter +// font.family: Style.fontRegular.name +// font.pixelSize: 12 +// font.bold: true +// text: qsTr("Resolve") + translationManager.emptyString +// color: "black" +// } + +// MouseArea { +// cursorShape: Qt.PointingHandCursor +// anchors.fill: parent +// hoverEnabled: true +// onClicked: { +// var result = walletManager.resolveOpenAlias(addressLine.text) +// if (result) { +// var parts = result.split("|") +// if (parts.length == 2) { +// var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.testnet) +// if (parts[0] === "true") { +// if (address_ok) { +// addressLine.text = parts[1] +// addressLine.cursorPosition = 0 +// } +// else +// oa_message(qsTr("No valid address found at this OpenAlias address")) +// } else if (parts[0] === "false") { +// if (address_ok) { +// addressLine.text = parts[1] +// addressLine.cursorPosition = 0 +// oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed")) +// } else { +// oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed")) +// } +// } else { +// oa_message(qsTr("Internal error")) +// } +// } else { +// oa_message(qsTr("Internal error")) +// } +// } else { +// oa_message(qsTr("No address found")) +// } +// } +// onEntered: { +// resolveButton.color = "#707070"; +// resolveButtonText.opacity = 0.8; +// } +// onExited: { +// resolveButtonText.opacity = 1.0; +// resolveButton.color = "#808080"; +// } +// } +// } +// } + +// InputMulti { +// id: addressLine +// readOnly: false +// addressValidation: true +// anchors.top: inputLabelRect.bottom +// placeholderText: "4..." +// Layout.fillWidth: true + +// Rectangle { +// color: "transparent" +// border.width: 1 +// border.color: { +// if(addressLine.error && addressLine.text !== ""){ +// return Qt.rgba(255, 0, 0, 0.45); +// } else if(addressLine.activeFocus){ +// return Qt.rgba(255, 255, 255, 0.35); +// } else { +// return Qt.rgba(255, 255, 255, 0.25); +// } +// } +// radius: 4 +// anchors.fill: parent +// } +// } +// } + StandardButton { id: qrfinderButton text: qsTr("QR Code") + translationManager.emptyString @@ -374,9 +446,9 @@ Rectangle { anchors.top: pageRoot.bottom anchors.left: parent.left anchors.right: parent.right - anchors.margins: (isMobile)? 17 : 40 + anchors.margins: (isMobile)? 17 : 20 anchors.topMargin: 40 * scaleRatio - spacing: 20 * scaleRatio + spacing: 26 * scaleRatio enabled: !viewOnly || pageRoot.enabled RowLayout { diff --git a/qml.qrc b/qml.qrc index 18aa7da3..bb32bfbf 100644 --- a/qml.qrc +++ b/qml.qrc @@ -192,5 +192,7 @@ images/middlePanelBg.jpg components/InputMulti.qml images/checkedIcon-black.png + components/LineEditMulti.qml + components/LabelButton.qml From a1cdb572e2d80eb86de79939613bd09857ca951d Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 9 Dec 2017 00:02:25 +0100 Subject: [PATCH 067/126] Added 2 components: LineEditMulti.qml && LabelButton.qml - multiline line edits --- components/LabelButton.qml | 73 ++++++++++++++++++++ components/LineEditMulti.qml | 125 +++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 components/LabelButton.qml create mode 100644 components/LineEditMulti.qml diff --git a/components/LabelButton.qml b/components/LabelButton.qml new file mode 100644 index 00000000..38b05fbc --- /dev/null +++ b/components/LabelButton.qml @@ -0,0 +1,73 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import "." 1.0 + + +Rectangle { + signal clicked(); + property alias text: labelButtonText.text + + id: labelButton + color: "#808080" + radius: 3 + height: 20 + width: labelButtonText.width + 14 + anchors.right: copyButton.left + anchors.rightMargin: 6 + visible: isValidOpenAliasAddress(addressLine.text) + + Text { + id: labelButtonText + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.family: Style.fontRegular.name + font.pixelSize: 12 + font.bold: true + text: "" + color: "black" + } + + MouseArea { + cursorShape: Qt.PointingHandCursor + anchors.fill: parent + hoverEnabled: true + onClicked: labelButton.clicked() + onEntered: { + labelButton.color = "#707070"; + labelButtonText.opacity = 0.8; + } + onExited: { + labelButton.color = "#808080"; + labelButtonText.opacity = 1.0; + } + } +} + diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml new file mode 100644 index 00000000..91078e24 --- /dev/null +++ b/components/LineEditMulti.qml @@ -0,0 +1,125 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import "." 1.0 + + +ColumnLayout { + property alias text: multiLine.text + property alias placeholderText: placeholderLabel.text + property alias inputLabelText: inputLabel.text + property alias error: multiLine.error + property alias readOnly: multiLine.readOnly + property alias addressValidation: multiLine.addressValidation + property alias labelButtonText: labelButton.text + property bool labelButtonVisible: false + property bool copyButton: false + signal labelButtonClicked(); + signal inputLabelLinkActivated(); + + spacing: 0 + Rectangle{ + id: inputLabelRect + color: "transparent" + Layout.fillWidth: true + height: inputLabel.height + 10 + + Text { + id: inputLabel + anchors.top: parent.top + anchors.left: parent.left + font.family: Style.fontRegular.name + font.pixelSize: 16 * scaleRatio + font.bold: labelFontBold + textFormat: Text.RichText + color: Style.defaultFontColor + onLinkActivated: inputLabelLinkActivated() + } + + LabelButton { + id: labelButton + onClicked: labelButtonClicked() + visible: labelButtonVisible + } + + LabelButton { + id: copyButtonId + visible: copyButton + text: qsTr("Copy") + anchors.right: labelButton.visible ? inputLabel.right : parent.right + anchors.rightMargin: labelButton.visible? 4 : 0 + onClicked: { + if (multiLine.text.length > 0) { + console.log(multiLine.text + " copied to clipboard") + clipboard.setText(multiLine.text) + appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) + } + } + } + } + + InputMulti { + id: multiLine + readOnly: false + addressValidation: true + anchors.top: inputLabelRect.bottom + Layout.fillWidth: true + + Text { + id: placeholderLabel + visible: multiLine.text ? false : true + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 10 + opacity: 0.25 + color: Style.defaultFontColor + font.family: Style.fontRegular.name + font.pixelSize: 18 * scaleRatio + text: "" + z: 3 + } + + Rectangle { + color: "transparent" + border.width: 1 + border.color: { + if(multiLine.error && multiLine.text !== ""){ + return Qt.rgba(255, 0, 0, 0.45); + } else if(multiLine.activeFocus){ + return Qt.rgba(255, 255, 255, 0.35); + } else { + return Qt.rgba(255, 255, 255, 0.25); + } + } + radius: 4 + anchors.fill: parent + } + } +} From d654ec164770b41b0f25cac5dcbd05f72a32723e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 9 Dec 2017 00:02:43 +0100 Subject: [PATCH 068/126] Settings page WIP --- pages/Settings.qml | 132 +++++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 40 deletions(-) diff --git a/pages/Settings.qml b/pages/Settings.qml index 7b3c847a..c4213870 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -51,27 +51,33 @@ Rectangle { ColumnLayout { id: mainLayout - anchors.margins: 17 * scaleRatio + anchors.margins: (isMobile)? 17 : 40 anchors.left: parent.left anchors.top: parent.top anchors.right: parent.right - spacing: 10 * scaleRatio + spacing: 26 * scaleRatio //! Manage wallet RowLayout { + Layout.fillWidth: true Label { id: manageWalletLabel + fontSize: 22 * scaleRatio Layout.fillWidth: true text: qsTr("Manage wallet") + translationManager.emptyString Layout.topMargin: 10 * scaleRatio } - } - Rectangle { - Layout.fillWidth: true - height: 1 - color: Style.dividerColor - opacity: Style.dividerOpacity + Rectangle { + anchors.top: manageWalletLabel.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + Layout.fillWidth: true + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + } } GridLayout { @@ -209,21 +215,21 @@ Rectangle { Layout.topMargin: 20 Label { id: manageDaemonLabel + fontSize: 22 * scaleRatio text: qsTr("Manage Daemon") + translationManager.emptyString } - CheckBox { - id: daemonAdvanced - Layout.leftMargin: 15 - text: qsTr("Show advanced") + translationManager.emptyString + Rectangle { + anchors.top: manageDaemonLabel.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + Layout.fillWidth: true + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: Style.dividerColor - opacity: Style.dividerOpacity - } GridLayout { visible: !isMobile && !persistentSettings.useRemoteNode @@ -292,12 +298,19 @@ Rectangle { } } + RowLayout{ + CheckBox { + id: daemonAdvanced + text: qsTr("Show advanced") + translationManager.emptyString + } + } RowLayout { visible: daemonAdvanced.checked && !isMobile && !persistentSettings.useRemoteNode id: daemonFlagsRow Label { id: daemonFlagsLabel + fontSize: 16 * scaleRatio text: qsTr("Local daemon startup flags") + translationManager.emptyString } LineEdit { @@ -314,10 +327,10 @@ Rectangle { visible: (daemonAdvanced.checked || isMobile) && persistentSettings.useRemoteNode Label { id: daemonLoginLabel + fontSize: 16 * scaleRatio Layout.fillWidth: true text: qsTr("Node login (optional)") + translationManager.emptyString } - } ColumnLayout { @@ -330,7 +343,6 @@ Rectangle { placeholderText: qsTr("Username") + translationManager.emptyString } - LineEdit { id: daemonPassword Layout.preferredWidth: 100 * scaleRatio @@ -365,8 +377,27 @@ Rectangle { visible: persistentSettings.useRemoteNode ColumnLayout { Label { + id: remoteNodeLabel + fontSize: 22 * scaleRatio text: qsTr("Remote node") + translationManager.emptyString } + + Rectangle { + anchors.top: remoteNodeLabel.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + Layout.fillWidth: true + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + } + } + } + + RowLayout { + visible: persistentSettings.useRemoteNode + ColumnLayout{ RemoteNodeEdit { id: remoteNodeEdit Layout.minimumWidth: 100 * scaleRatio @@ -400,17 +431,23 @@ Rectangle { RowLayout { visible: !isMobile Label { + id: layoutSettingsLabel + fontSize: 22 * scaleRatio text: qsTr("Layout settings") + translationManager.emptyString anchors.topMargin: 30 * scaleRatio Layout.topMargin: 30 * scaleRatio } - } - Rectangle { - visible: !isMobile - Layout.fillWidth: true - height: 1 - color: Style.dividerColor - opacity: Style.dividerOpacity + + Rectangle { + anchors.top: layoutSettingsLabel.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + Layout.fillWidth: true + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + } } RowLayout { @@ -427,17 +464,25 @@ Rectangle { RowLayout { Label { + id: logLevelLabel + fontSize: 22 * scaleRatio text: qsTr("Log level") + translationManager.emptyString anchors.topMargin: 30 * scaleRatio Layout.topMargin: 30 * scaleRatio } + + Rectangle { + anchors.top: logLevelLabel.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + Layout.fillWidth: true + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: Style.dividerColor - opacity: Style.dividerOpacity - } + ColumnLayout { ComboBox { id: logLevel @@ -475,18 +520,25 @@ Rectangle { // Version RowLayout { Label { + id: debugLabel text: qsTr("Debug info") + translationManager.emptyString - fontSize: 16 + fontSize: 22 anchors.topMargin: 30 * scaleRatio Layout.topMargin: 30 * scaleRatio } + + Rectangle { + anchors.top: debugLabel.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + Layout.fillWidth: true + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + } } - Rectangle { - Layout.fillWidth: true - height: 1 - color: Style.dividerColor - opacity: Style.dividerOpacity - } + TextBlock { Layout.topMargin: 8 Layout.fillWidth: true From 0b9e89691ddb799ef9a8d1bd6b8637809ecc3e1f Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 9 Dec 2017 01:37:09 +0100 Subject: [PATCH 069/126] Remove debugging leftovers from transfer page --- pages/Transfer.qml | 121 --------------------------------------------- 1 file changed, 121 deletions(-) diff --git a/pages/Transfer.qml b/pages/Transfer.qml index ee0d7aa4..0af99427 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -201,10 +201,6 @@ Rectangle { LineEditMulti{ id: addressLine spacing: 0 -// @TODO: -// - fix wrong copy @ receive.qml -// - resolve button click @ multiline @ transfer.qml - inputLabelText: qsTr("\ Address ( Address book )") + translationManager.emptyString @@ -244,123 +240,6 @@ Rectangle { } } -// ColumnLayout { -// spacing: 0 -// Rectangle{ -// id: inputLabelRect -// color: "transparent" -// Layout.fillWidth: true -// height: inputLabel.height + 10 - -// Text { -// id: inputLabel -// anchors.top: parent.top -// anchors.left: parent.left -// font.family: Style.fontRegular.name -// font.pixelSize: 16 * scaleRatio -// font.bold: labelFontBold -// textFormat: Text.RichText -// color: Style.defaultFontColor -// onLinkActivated: { appWindow.showPageRequest("AddressBook") } -// text: qsTr("\ -// Address ( Address book )") -// + translationManager.emptyString -// } - -// Rectangle{ -// id: resolveButton -// color: "#808080" -// radius: 3 -// height: 20 -// width: resolveButtonText.width + 8 -// anchors.right: copyButton.left -// anchors.rightMargin: 6 -// visible: isValidOpenAliasAddress(addressLine.text) - -// Text { -// id: resolveButtonText -// anchors.verticalCenter: parent.verticalCenter -// anchors.horizontalCenter: parent.horizontalCenter -// font.family: Style.fontRegular.name -// font.pixelSize: 12 -// font.bold: true -// text: qsTr("Resolve") + translationManager.emptyString -// color: "black" -// } - -// MouseArea { -// cursorShape: Qt.PointingHandCursor -// anchors.fill: parent -// hoverEnabled: true -// onClicked: { -// var result = walletManager.resolveOpenAlias(addressLine.text) -// if (result) { -// var parts = result.split("|") -// if (parts.length == 2) { -// var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.testnet) -// if (parts[0] === "true") { -// if (address_ok) { -// addressLine.text = parts[1] -// addressLine.cursorPosition = 0 -// } -// else -// oa_message(qsTr("No valid address found at this OpenAlias address")) -// } else if (parts[0] === "false") { -// if (address_ok) { -// addressLine.text = parts[1] -// addressLine.cursorPosition = 0 -// oa_message(qsTr("Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed")) -// } else { -// oa_message(qsTr("No valid address found at this OpenAlias address, but the DNSSEC signatures could not be verified, so this may be spoofed")) -// } -// } else { -// oa_message(qsTr("Internal error")) -// } -// } else { -// oa_message(qsTr("Internal error")) -// } -// } else { -// oa_message(qsTr("No address found")) -// } -// } -// onEntered: { -// resolveButton.color = "#707070"; -// resolveButtonText.opacity = 0.8; -// } -// onExited: { -// resolveButtonText.opacity = 1.0; -// resolveButton.color = "#808080"; -// } -// } -// } -// } - -// InputMulti { -// id: addressLine -// readOnly: false -// addressValidation: true -// anchors.top: inputLabelRect.bottom -// placeholderText: "4..." -// Layout.fillWidth: true - -// Rectangle { -// color: "transparent" -// border.width: 1 -// border.color: { -// if(addressLine.error && addressLine.text !== ""){ -// return Qt.rgba(255, 0, 0, 0.45); -// } else if(addressLine.activeFocus){ -// return Qt.rgba(255, 255, 255, 0.35); -// } else { -// return Qt.rgba(255, 255, 255, 0.25); -// } -// } -// radius: 4 -// anchors.fill: parent -// } -// } -// } - StandardButton { id: qrfinderButton text: qsTr("QR Code") + translationManager.emptyString From 0477af1b0d882acd241de67187bf28dfe4873809 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 9 Dec 2017 02:14:33 +0100 Subject: [PATCH 070/126] Settings - dropdown for log level --- pages/Settings.qml | 79 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/pages/Settings.qml b/pages/Settings.qml index c4213870..808edc5b 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -43,12 +43,19 @@ Rectangle { color: "transparent" - Clipboard { id: clipboard } + // fires on every page load + function onPageCompleted() { + console.log("Settings page loaded"); - function initSettings() { - //runs on every page load + if(typeof daemonManager != "undefined"){ + appWindow.daemonRunning = daemonManager.running(persistentSettings.testnet); + } + + logLevelDropdown.update() } + Clipboard { id: clipboard } + ColumnLayout { id: mainLayout anchors.margins: (isMobile)? 17 : 40 @@ -483,28 +490,66 @@ Rectangle { } } - ColumnLayout { - ComboBox { - id: logLevel - model: [0,1,2,3,4,"custom"] - currentIndex : appWindow.persistentSettings.logLevel; - onCurrentIndexChanged: { - if (currentIndex == 5) { - console.log("log categories changed: ", logCategories.text); - walletManager.setLogCategories(logCategories.text); + GridLayout { + columns: (isMobile)? 1 : 3 + Layout.fillWidth: true + columnSpacing: 32 + + ColumnLayout { + spacing: 0 + Layout.fillWidth: true + + ListModel { + id: logLevel + ListElement { name: "wow"; column1: "0"; } + ListElement { column1: "1"; } + ListElement { column1: "2"; } + ListElement { column1: "3"; } + ListElement { column1: "4"; } + ListElement { column1: "custom"; } + } + + StandardDropdown { + id: logLevelDropdown + dataModel: logLevel + currentIndex: appWindow.persistentSettings.logLevel; + onChanged: { + if (currentIndex == 5) { + console.log("log categories changed: ", logCategories.text); + walletManager.setLogCategories(logCategories.text); + } + else { + console.log("log level changed: ",currentIndex); + walletManager.setLogLevel(currentIndex); + } + appWindow.persistentSettings.logLevel = currentIndex; } - else { - console.log("log level changed: ",currentIndex); - walletManager.setLogLevel(currentIndex); - } - appWindow.persistentSettings.logLevel = currentIndex; + Layout.fillWidth: true + shadowReleasedColor: "#FF4304" + shadowPressedColor: "#B32D00" + releasedColor: "#363636" + pressedColor: "#202020" } + // Make sure dropdown is on top + z: parent.z + 30 } + ColumnLayout { + Layout.fillWidth: true + } + + ColumnLayout { + Layout.fillWidth: true + } + } + + ColumnLayout { LineEdit { id: logCategories + Layout.topMargin: 16 * scaleRatio Layout.fillWidth: true text: appWindow.persistentSettings.logCategories + labelText: "Log Categories" placeholderText: qsTr("(e.g. *:WARNING,net.p2p:DEBUG)") + translationManager.emptyString enabled: logLevel.currentIndex == 5 onEditingFinished: { From be9cb8931c9bfe9fccf9d4ec7060dc467a1a6c8e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 9 Dec 2017 17:46:03 +0100 Subject: [PATCH 071/126] StandardButton - removed unused properties and some layout changes to settings page --- components/DaemonConsole.qml | 8 ------- components/DaemonManagerDialog.qml | 8 ------- components/DatePicker.qml | 4 ---- components/HistoryTable.qml | 4 ---- components/PasswordDialog.qml | 8 ------- components/RemoteNodeEdit.qml | 4 +++- components/StandardButton.qml | 32 ++++++--------------------- components/StandardDialog.qml | 8 ------- pages/AddressBook.qml | 8 ------- pages/History.qml | 4 ---- pages/Mining.qml | 8 ------- pages/Settings.qml | 35 +++++++++++++++++++----------- pages/Sign.qml | 24 -------------------- pages/Transfer.qml | 4 ---- pages/TxKey.qml | 6 +---- wizard/WizardMain.qml | 12 ---------- wizard/WizardManageWalletUI.qml | 12 ---------- 17 files changed, 33 insertions(+), 156 deletions(-) diff --git a/components/DaemonConsole.qml b/components/DaemonConsole.qml index 8bcd8a23..2643a339 100644 --- a/components/DaemonConsole.qml +++ b/components/DaemonConsole.qml @@ -110,10 +110,6 @@ Window { id: okButton width: 120 fontSize: 14 - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Close") + translationManager.emptyString onClicked: { root.close() @@ -138,10 +134,6 @@ Window { // id: sendCommandButton // enabled: sendCommandText.text.length > 0 // fontSize: 14 -// shadowReleasedColor: "#FF4304" -// shadowPressedColor: "#B32D00" -// releasedColor: "#FF6C3C" -// pressedColor: "#FF4304" // text: qsTr("Send command") // onClicked: { // daemonManager.sendCommand(sendCommandText.text,currentWallet.testnet); diff --git a/components/DaemonManagerDialog.qml b/components/DaemonManagerDialog.qml index d760c317..07dec4a0 100644 --- a/components/DaemonManagerDialog.qml +++ b/components/DaemonManagerDialog.qml @@ -108,10 +108,6 @@ Window { id: okButton visible:false fontSize: 14 - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Start daemon (%1)").arg(countDown) KeyNavigation.tab: cancelButton onClicked: { @@ -125,10 +121,6 @@ Window { MoneroComponents.StandardButton { id: cancelButton fontSize: 14 - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Use custom settings") onClicked: { diff --git a/components/DatePicker.qml b/components/DatePicker.qml index dafba285..8988f2bd 100644 --- a/components/DatePicker.qml +++ b/components/DatePicker.qml @@ -92,10 +92,6 @@ Item { StandardButton { id: button anchors.fill: parent - shadowReleasedColor: "#DBDBDB" - shadowPressedColor: "#888888" - releasedColor: "#F0EEEE" - pressedColor: "#DBDBDB" icon: "../images/datePicker.png" visible: !datePicker.expanded onClicked: datePicker.expanded = true diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index cac884ae..18d05f6d 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -96,10 +96,6 @@ ListView { anchors.topMargin: parent.height/2 - this.height/2 width: 80 fontSize: 14 - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Details") onClicked: { var tx_key = currentWallet.getTxKey(hash) diff --git a/components/PasswordDialog.qml b/components/PasswordDialog.qml index d2315011..e8563a73 100644 --- a/components/PasswordDialog.qml +++ b/components/PasswordDialog.qml @@ -149,10 +149,6 @@ Item { MoneroComponents.StandardButton { id: cancelButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Cancel") + translationManager.emptyString KeyNavigation.tab: passwordInput onClicked: { @@ -162,10 +158,6 @@ Item { } MoneroComponents.StandardButton { id: okButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Continue") KeyNavigation.tab: cancelButton onClicked: { diff --git a/components/RemoteNodeEdit.qml b/components/RemoteNodeEdit.qml index 295e4b16..49413436 100644 --- a/components/RemoteNodeEdit.qml +++ b/components/RemoteNodeEdit.qml @@ -33,9 +33,12 @@ import QtQuick.Layouts 1.1 GridLayout { columns: (isMobile) ? 1 : 2 + columnSpacing: 32 id: root property alias daemonAddrText: daemonAddr.text property alias daemonPortText: daemonPort.text + property alias daemonAddrLabelText: daemonAddr.labelText + property alias daemonPortLabelText: daemonPort.labelText signal editingFinished() @@ -50,7 +53,6 @@ GridLayout { onEditingFinished: root.editingFinished() } - LineEdit { id: daemonPort Layout.fillWidth: true diff --git a/components/StandardButton.qml b/components/StandardButton.qml index 440505ee..f41c104a 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -33,10 +33,6 @@ import "." 1.0 Item { id: button height: 37 * scaleRatio - property string shadowPressedColor: Style.buttonBackgroundColor - property string shadowReleasedColor: Style.buttonBackgroundColor - property string pressedColor: Style.buttonBackgroundColor - property string releasedColor: Style.buttonBackgroundColor property string icon: "" property string textColor: button.enabled? Style.buttonTextColor: Style.buttonTextColorDisabled property int fontSize: 16 * scaleRatio @@ -57,8 +53,8 @@ Item { anchors.right: parent.right height: parent.height - 1 radius: 3 +// color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled - border.color: Qt.darker(parent.releasedColor) border.width: parent.focus ? 1 : 0 MouseArea{ @@ -68,32 +64,18 @@ Item { propagateComposedEvents: true + // possibly do some hover effects here onEntered: { - if(button.enabled) parent.color = Style.buttonBackgroundColorHover; - else parent.color = Style.buttonBackgroundColorDisabledHover; +// if(button.enabled) parent.color = Style.buttonBackgroundColorHover; +// else parent.color = Style.buttonBackgroundColorDisabledHover; } onExited: { - if(button.enabled) parent.color = Style.buttonBackgroundColor; - else parent.color = Style.buttonBackgroundColorDisabled; +// if(button.enabled) parent.color = Style.buttonBackgroundColor; +// else parent.color = Style.buttonBackgroundColorDisabled; } } } -// Rectangle { -// anchors.left: parent.left -// anchors.right: parent.right -// height: parent.height - 1 -// y: buttonArea.pressed ? 1 : 0 -// color: { -// parent.enabled ? (buttonArea.pressed ? parent.pressedColor : parent.releasedColor) -// : Qt.lighter(parent.releasedColor) - -// } -// //radius: 4 - - -// } - Text { id: label anchors.verticalCenter: parent.verticalCenter @@ -105,7 +87,6 @@ Item { font.pixelSize: buttonArea.pressed ? button.fontSize - 1 : button.fontSize color: parent.textColor visible: parent.icon === "" -// font.capitalization : Font.Capitalize } Image { @@ -118,6 +99,7 @@ Item { id: buttonArea anchors.fill: parent onClicked: doClick() + cursorShape: Qt.PointingHandCursor } Keys.onSpacePressed: doClick() diff --git a/components/StandardDialog.qml b/components/StandardDialog.qml index 9d9766d9..7c9315d5 100644 --- a/components/StandardDialog.qml +++ b/components/StandardDialog.qml @@ -140,10 +140,6 @@ Rectangle { MoneroComponents.StandardButton { id: cancelButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Cancel") + translationManager.emptyString onClicked: { root.close() @@ -153,10 +149,6 @@ Rectangle { MoneroComponents.StandardButton { id: okButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("OK") KeyNavigation.tab: cancelButton onClicked: { diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml index 4613e260..27395a03 100644 --- a/pages/AddressBook.qml +++ b/pages/AddressBook.qml @@ -48,10 +48,6 @@ Rectangle { StandardButton { id: qrfinderButton text: qsTr("Qr Code") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible : appWindow.qrScannerEnabled enabled : visible width: visible ? 60 * scaleRatio : 0 @@ -91,10 +87,6 @@ Rectangle { id: addButton Layout.bottomMargin: 17 * scaleRatio StandardButton { - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Add") + translationManager.emptyString enabled: checkInformation(addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype) diff --git a/pages/History.qml b/pages/History.qml index 1642f3bc..26b74808 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -250,10 +250,6 @@ Rectangle { anchors.leftMargin: 17 width: 60 text: qsTr("Filter") + translationManager.emptyString - shadowReleasedColor: "#4D0051" - shadowPressedColor: "#2D002F" - releasedColor: "#6B0072" - pressedColor: "#4D0051" onClicked: { // Apply filter here; diff --git a/pages/Mining.qml b/pages/Mining.qml index be2b1805..5726acba 100644 --- a/pages/Mining.qml +++ b/pages/Mining.qml @@ -133,10 +133,6 @@ Rectangle { id: startSoloMinerButton width: 110 text: qsTr("Start mining") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { var success = walletManager.startMining(appWindow.currentWallet.address(0, 0), soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery) if (success) { @@ -158,10 +154,6 @@ Rectangle { id: stopSoloMinerButton width: 110 text: qsTr("Stop mining") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { walletManager.stopMining() update() diff --git a/pages/Settings.qml b/pages/Settings.qml index 808edc5b..8446d46b 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -404,33 +404,42 @@ Rectangle { RowLayout { visible: persistentSettings.useRemoteNode - ColumnLayout{ + ColumnLayout { + Layout.fillWidth: true + RemoteNodeEdit { id: remoteNodeEdit Layout.minimumWidth: 100 * scaleRatio property var rna: persistentSettings.remoteNodeAddress daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : "" daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : rna.split(":")[1] : "" + daemonAddrLabelText: qsTr("Address") + daemonPortLabelText: qsTr("Port") onEditingFinished: { persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); console.log("setting remote node to " + persistentSettings.remoteNodeAddress) } } + } + } - StandardButton { - id: remoteNodeSave - text: qsTr("Connect") + translationManager.emptyString - onClicked: { - // Update daemon login - persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); - persistentSettings.daemonUsername = daemonUsername.text; - persistentSettings.daemonPassword = daemonPassword.text; - persistentSettings.useRemoteNode = true + RowLayout{ + visible: persistentSettings.useRemoteNode + Layout.fillWidth: true - currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword); + StandardButton { + id: remoteNodeSave + text: qsTr("Connect") + translationManager.emptyString + onClicked: { + // Update daemon login + persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); + persistentSettings.daemonUsername = daemonUsername.text; + persistentSettings.daemonPassword = daemonPassword.text; + persistentSettings.useRemoteNode = true - appWindow.connectRemoteNode() - } + currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword); + + appWindow.connectRemoteNode() } } } diff --git a/pages/Sign.qml b/pages/Sign.qml index 6ff8dd6a..678541b0 100644 --- a/pages/Sign.qml +++ b/pages/Sign.qml @@ -143,10 +143,6 @@ Rectangle { id: signMessageButton anchors.right: parent.right text: qsTr("Sign") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true onClicked: { var signature = appWindow.currentWallet.signMessage(signMessageLine.text, false) @@ -181,10 +177,6 @@ Rectangle { id: loadFileToSignButton anchors.rightMargin: 17 * scaleRatio text: qsTr("Select") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true onClicked: { signFileDialog.open() @@ -213,10 +205,6 @@ Rectangle { id: signFileButton anchors.right: parent.right text: qsTr("Sign") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true onClicked: { var signature = appWindow.currentWallet.signMessage(signFileLine.text, true) @@ -300,10 +288,6 @@ Rectangle { id: verifyMessageButton anchors.right: parent.right text: qsTr("Verify") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true onClicked: { var verified = appWindow.currentWallet.verifySignedMessage(verifyMessageLine.text, verifyAddressLine.text, verifySignatureLine.text, false) @@ -338,10 +322,6 @@ Rectangle { id: loadFileToVerifyButton anchors.rightMargin: 17 * scaleRatio text: qsTr("Select") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true onClicked: { verifyFileDialog.open() @@ -369,10 +349,6 @@ Rectangle { id: verifyFileButton anchors.right: parent.right text: qsTr("Verify") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true onClicked: { var verified = appWindow.currentWallet.verifySignedMessage(verifyFileLine.text, verifyAddressLine.text, verifySignatureLine.text, true) diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 0af99427..88be98c8 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -436,10 +436,6 @@ Rectangle { StandardButton { id: submitTxButton text: qsTr("Submit tx file") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: appWindow.viewOnly enabled: pageRoot.enabled onClicked: { diff --git a/pages/TxKey.qml b/pages/TxKey.qml index e0455168..2e8f3a37 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -324,11 +324,7 @@ Rectangle { anchors.topMargin: 17 width: 60 text: qsTr("Check") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype))) + enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) onClicked: { 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) diff --git a/wizard/WizardMain.qml b/wizard/WizardMain.qml index 05a4099e..ec685fe4 100644 --- a/wizard/WizardMain.qml +++ b/wizard/WizardMain.qml @@ -365,10 +365,6 @@ ColumnLayout { anchors.bottom: parent.bottom anchors.margins: (isMobile) ? 20 * scaleRatio : 50 * scaleRatio text: qsTr("USE MONERO") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: parent.paths[currentPath][currentPage] === finishPage onClicked: { wizard.applySettings(); @@ -382,10 +378,6 @@ ColumnLayout { anchors.bottom: parent.bottom anchors.margins: (isMobile) ? 20 * scaleRatio : 50 text: qsTr("Create wallet") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: currentPath === "create_view_only_wallet" && parent.paths[currentPath][currentPage] === passwordPage enabled: passwordPage.passwordsMatch onClicked: { @@ -414,10 +406,6 @@ ColumnLayout { anchors.bottom: parent.bottom anchors.margins: (isMobile) ? 20 * scaleRatio : 50 text: qsTr("Abort") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible: currentPath === "create_view_only_wallet" && parent.paths[currentPath][currentPage] === passwordPage onClicked: { wizard.restart(); diff --git a/wizard/WizardManageWalletUI.qml b/wizard/WizardManageWalletUI.qml index b83648a7..020a9e05 100644 --- a/wizard/WizardManageWalletUI.qml +++ b/wizard/WizardManageWalletUI.qml @@ -176,10 +176,6 @@ ColumnLayout { StandardButton { id: recoverFromSeedButton text: qsTr("Restore from seed") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: recoverFromKeys.visible onClicked: { recoverFromSeedMode = true; @@ -190,10 +186,6 @@ ColumnLayout { StandardButton { id: recoverFromKeysButton text: qsTr("Restore from keys") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: recoverFromSeed.visible onClicked: { recoverFromSeedMode = false; @@ -204,10 +196,6 @@ ColumnLayout { StandardButton { id: qrfinderButton text: qsTr("From QR Code") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" visible : true //appWindow.qrScannerEnabled enabled : visible onClicked: { From f262ce520978fa406e6531ffc9a8464a14a3a722 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 10 Dec 2017 19:52:05 +0100 Subject: [PATCH 072/126] Finishing up on the settings page for now and modified some QML components --- MiddlePanel.qml | 2 +- components/Label.qml | 23 +-- components/LabelSubheader.qml | 45 ++++++ components/LineEdit.qml | 9 +- components/LineEditMulti.qml | 2 +- components/StandardButton.qml | 11 +- pages/Settings.qml | 259 ++++++++++++++++------------------ qml.qrc | 1 + 8 files changed, 197 insertions(+), 155 deletions(-) create mode 100644 components/LabelSubheader.qml diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 65982b79..bc1bc76c 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -139,7 +139,7 @@ Rectangle { }, State { name: "Settings" PropertyChanges { target: root; currentView: settingsView } - PropertyChanges { target: mainFlickable; contentHeight: 1200 * scaleRatio } + PropertyChanges { target: mainFlickable; contentHeight: 1400 * scaleRatio } }, State { name: "Mining" PropertyChanges { target: root; currentView: miningView } diff --git a/components/Label.qml b/components/Label.qml index 86618c9e..b2c4e52f 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -42,8 +42,10 @@ Item { property alias wrapMode: label.wrapMode property alias horizontalAlignment: label.horizontalAlignment signal linkActivated() - width: icon.x + icon.width * scaleRatio - height: icon.height * scaleRatio +// width: icon.x + icon.width * scaleRatio +// height: icon.height * scaleRatio + height: label.height * scaleRatio + width: label.width * scaleRatio Layout.topMargin: 10 * scaleRatio Text { @@ -58,14 +60,15 @@ Item { onLinkActivated: item.linkActivated() } - Image { - id: icon - anchors.verticalCenter: parent.verticalCenter - anchors.left: label.right - anchors.leftMargin: 5 * scaleRatio - source: "../images/whatIsIcon.png" - visible: appWindow.whatIsEnable - } +// @TODO: figure out significance of whatIsIcon.png, remove for now +// Image { +// id: icon +// anchors.verticalCenter: parent.verticalCenter +// anchors.left: label.right +// anchors.leftMargin: 5 * scaleRatio +// source: "../images/whatIsIcon.png" +// visible: appWindow.whatIsEnable +// } // MouseArea { // anchors.fill: icon diff --git a/components/LabelSubheader.qml b/components/LabelSubheader.qml new file mode 100644 index 00000000..daa067e0 --- /dev/null +++ b/components/LabelSubheader.qml @@ -0,0 +1,45 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.0 +import "." 1.0 + +Label { + id: item + fontSize: 17 * scaleRatio + + Rectangle { + anchors.top: item.bottom + anchors.topMargin: 4 + anchors.left: parent.left + anchors.right: parent.right + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + } +} diff --git a/components/LineEdit.qml b/components/LineEdit.qml index d52db763..42da1e9d 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -53,12 +53,13 @@ Item { property bool labelFontBold: false property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment + property bool showingHeader: inputLabel.text !== "" || copyButton signal labelLinkActivated(); // input label, rich text signal signal editingFinished(); signal accepted(); signal textUpdated(); - height: (inputLabel.height + inputItem.height + 2) * scaleRatio + height: showingHeader ? (inputLabel.height + inputItem.height + 2) * scaleRatio : 42 * scaleRatio onTextUpdated: { // check to remove placeholder text when there is content @@ -109,14 +110,14 @@ Item { appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) } } - visible: input.text && copyButton ? true : false + visible: copyButton && input.text !== "" } Item{ id: inputItem height: 40 * scaleRatio - anchors.top: inputLabel.bottom - anchors.topMargin: 6 * scaleRatio + anchors.top: showingHeader ? inputLabel.bottom : parent.top + anchors.topMargin: showingHeader ? 6 * scaleRatio : 2 width: parent.width Text { diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 91078e24..6c9dcf7a 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -71,7 +71,7 @@ ColumnLayout { LabelButton { id: copyButtonId - visible: copyButton + visible: copyButton && multiLine.text !== "" text: qsTr("Copy") anchors.right: labelButton.visible ? inputLabel.right : parent.right anchors.rightMargin: labelButton.visible? 4 : 0 diff --git a/components/StandardButton.qml b/components/StandardButton.qml index f41c104a..76c8c889 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -32,15 +32,20 @@ import "." 1.0 Item { id: button - height: 37 * scaleRatio property string icon: "" property string textColor: button.enabled? Style.buttonTextColor: Style.buttonTextColorDisabled - property int fontSize: 16 * scaleRatio + property bool small: false property alias text: label.text + property int fontSize: { + if(small) return 14 * scaleRatio; + else return 16 * scaleRatio; + } signal clicked() - // Dynamic label width + // Dynamic height/width Layout.minimumWidth: (label.contentWidth > 50)? label.contentWidth + 22 : 60 + height: small ? 30 * scaleRatio : 36 * scaleRatio + function doClick() { // Android workaround diff --git a/pages/Settings.qml b/pages/Settings.qml index 8446d46b..54985b53 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -91,6 +91,7 @@ Rectangle { columns: (isMobile)? 1 : 4 StandardButton { id: closeWalletButton + small: true text: qsTr("Close wallet") + translationManager.emptyString visible: true onClicked: { @@ -100,8 +101,9 @@ Rectangle { } StandardButton { - enabled: !viewOnly id: createViewOnlyWalletButton + enabled: !viewOnly + small: true text: qsTr("Create view only wallet") + translationManager.emptyString visible: true onClicked: { @@ -146,6 +148,7 @@ Rectangle { */ StandardButton { id: rescanSpentButton + small: true enabled: !persistentSettings.useRemoteNode text: qsTr("Rescan wallet balance") + translationManager.emptyString onClicked: { @@ -194,9 +197,17 @@ Rectangle { } RowLayout { + Layout.fillWidth: true + LabelSubheader { + text: qsTr("Wallet mode") + translationManager.emptyString + } + } + + RowLayout { StandardButton { id: remoteDisconnect + small: true enabled: persistentSettings.useRemoteNode Layout.fillWidth: false text: qsTr("Local Node") + translationManager.emptyString @@ -207,6 +218,7 @@ Rectangle { StandardButton { id: remoteConnect + small: true enabled: !persistentSettings.useRemoteNode Layout.fillWidth: false text: qsTr("Remote Node") + translationManager.emptyString @@ -216,10 +228,52 @@ Rectangle { } } + RowLayout { + visible: persistentSettings.useRemoteNode + ColumnLayout { + Layout.fillWidth: true + + RemoteNodeEdit { + id: remoteNodeEdit + Layout.minimumWidth: 100 * scaleRatio + daemonAddrLabelText: qsTr("Address") + daemonPortLabelText: qsTr("Port") + daemonAddrText: persistentSettings.remoteNodeAddress.split(":")[0].trim() + daemonPortText: (persistentSettings.remoteNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1] + onEditingFinished: { + persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); + console.log("setting remote node to " + persistentSettings.remoteNodeAddress) + } + } + } + } + + RowLayout{ + visible: persistentSettings.useRemoteNode + Layout.fillWidth: true + + StandardButton { + id: remoteNodeSave + small: true + text: qsTr("Connect") + translationManager.emptyString + onClicked: { + // Update daemon login + persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); + persistentSettings.daemonUsername = daemonUsername.text; + persistentSettings.daemonPassword = daemonPassword.text; + persistentSettings.useRemoteNode = true + + currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword); + + appWindow.connectRemoteNode() + } + } + } + //! Manage daemon RowLayout { visible: !isMobile - Layout.topMargin: 20 + Label { id: manageDaemonLabel fontSize: 22 * scaleRatio @@ -243,8 +297,9 @@ Rectangle { id: daemonStatusRow columns: (isMobile) ? 2 : 4 StandardButton { - visible: !appWindow.daemonRunning id: startDaemonButton + small: true + visible: !appWindow.daemonRunning text: qsTr("Start Local Node") + translationManager.emptyString onClicked: { // Update bootstrap daemon address @@ -257,8 +312,9 @@ Rectangle { } StandardButton { - visible: appWindow.daemonRunning id: stopDaemonButton + small: true + visible: appWindow.daemonRunning text: qsTr("Stop Local Node") + translationManager.emptyString onClicked: { appWindow.stopDaemon() @@ -266,8 +322,9 @@ Rectangle { } StandardButton { - visible: true id: daemonStatusButton + small: true + visible: true text: qsTr("Show status") + translationManager.emptyString onClicked: { daemonManager.sendCommand("status",currentWallet.nettype); @@ -279,29 +336,55 @@ Rectangle { ColumnLayout { id: blockchainFolderRow visible: !isMobile && !persistentSettings.useRemoteNode - Label { - id: blockchainFolderLabel - text: qsTr("Blockchain location") + translationManager.emptyString - } - LineEdit { - id: blockchainFolder - Layout.preferredWidth: 200 - Layout.fillWidth: true - labelText: qsTr("Blockchain location") + translationManager.emptyString - text: persistentSettings.blockchainDataDir - placeholderText: qsTr("(optional)") + translationManager.emptyString - MouseArea { - anchors.fill: parent + RowLayout { + Layout.fillWidth: true + Layout.bottomMargin: 14 * scaleRatio + + LabelSubheader { + text: qsTr("Blockchain location") + translationManager.emptyString + } + } + + RowLayout { + visible: persistentSettings.blockchainDataDir.length > 0 + + LineEdit { + id: blockchainFolder + Layout.preferredWidth: 200 + + Layout.fillWidth: true + text: persistentSettings.blockchainDataDir; + placeholderText: qsTr("(optional)") + translationManager.emptyString + } + } + + RowLayout { + Layout.fillWidth: true + Layout.topMargin: 8 + StandardButton { + id: blockchainFolderButton + small: true + visible: true + text: qsTr("Change location") + translationManager.emptyString onClicked: { - mouse.accepted = false + //mouse.accepted = false if(persistentSettings.blockchainDataDir != "") blockchainFileDialog.folder = "file://" + persistentSettings.blockchainDataDir blockchainFileDialog.open() blockchainFolder.focus = true } } + } + } + RowLayout { + visible: daemonAdvanced.checked && !isMobile + Layout.fillWidth: true + Layout.bottomMargin: 0 * scaleRatio + + LabelSubheader { + text: qsTr("Advanced daemon options") + translationManager.emptyString } } @@ -315,131 +398,38 @@ Rectangle { RowLayout { visible: daemonAdvanced.checked && !isMobile && !persistentSettings.useRemoteNode id: daemonFlagsRow - Label { - id: daemonFlagsLabel - fontSize: 16 * scaleRatio - text: qsTr("Local daemon startup flags") + translationManager.emptyString - } + LineEdit { id: daemonFlags Layout.preferredWidth: 200 Layout.fillWidth: true + labelText: qsTr("Local daemon startup flags") + translationManager.emptyString text: appWindow.persistentSettings.daemonFlags; placeholderText: qsTr("(optional)") + translationManager.emptyString } } - RowLayout { - Layout.fillWidth: true - visible: (daemonAdvanced.checked || isMobile) && persistentSettings.useRemoteNode - Label { - id: daemonLoginLabel - fontSize: 16 * scaleRatio - Layout.fillWidth: true - text: qsTr("Node login (optional)") + translationManager.emptyString - } - } - ColumnLayout { visible: (daemonAdvanced.checked || isMobile) && persistentSettings.useRemoteNode - LineEdit { - id: daemonUsername - Layout.preferredWidth: 100 * scaleRatio - Layout.fillWidth: true - text: persistentSettings.daemonUsername - placeholderText: qsTr("Username") + translationManager.emptyString - } + GridLayout { + columns: (isMobile) ? 1 : 2 + columnSpacing: 32 - LineEdit { - id: daemonPassword - Layout.preferredWidth: 100 * scaleRatio - Layout.fillWidth: true - text: persistentSettings.daemonPassword - placeholderText: qsTr("Password") + translationManager.emptyString - echoMode: TextInput.Password - } - } - - RowLayout { - visible: !isMobile && !persistentSettings.useRemoteNode - ColumnLayout { - Label { - color: "#4A4949" - text: qsTr("Bootstrap node (leave blank if not wanted)") + translationManager.emptyString - } - RemoteNodeEdit { - id: bootstrapNodeEdit - Layout.minimumWidth: 100 * scaleRatio - daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim() - daemonPortText: (persistentSettings.bootstrapNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.bootstrapNodeAddress.split(":")[1] - onEditingFinished: { - persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : ""; - console.log("setting bootstrap node to " + persistentSettings.bootstrapNodeAddress) - } - } - } - } - - RowLayout { - visible: persistentSettings.useRemoteNode - ColumnLayout { - Label { - id: remoteNodeLabel - fontSize: 22 * scaleRatio - text: qsTr("Remote node") + translationManager.emptyString - } - - Rectangle { - anchors.top: remoteNodeLabel.bottom - anchors.topMargin: 4 - anchors.left: parent.left - anchors.right: parent.right + LineEdit { + id: daemonUsername Layout.fillWidth: true - height: 2 - color: Style.dividerColor - opacity: Style.dividerOpacity + labelText: "Daemon username" + text: persistentSettings.daemonUsername + placeholderText: qsTr("Username") + translationManager.emptyString } - } - } - RowLayout { - visible: persistentSettings.useRemoteNode - ColumnLayout { - Layout.fillWidth: true - - RemoteNodeEdit { - id: remoteNodeEdit - Layout.minimumWidth: 100 * scaleRatio - property var rna: persistentSettings.remoteNodeAddress - daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : "" - daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : rna.split(":")[1] : "" - daemonAddrLabelText: qsTr("Address") - daemonPortLabelText: qsTr("Port") - onEditingFinished: { - persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); - console.log("setting remote node to " + persistentSettings.remoteNodeAddress) - } - } - } - } - - RowLayout{ - visible: persistentSettings.useRemoteNode - Layout.fillWidth: true - - StandardButton { - id: remoteNodeSave - text: qsTr("Connect") + translationManager.emptyString - onClicked: { - // Update daemon login - persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); - persistentSettings.daemonUsername = daemonUsername.text; - persistentSettings.daemonPassword = daemonPassword.text; - persistentSettings.useRemoteNode = true - - currentWallet.setDaemonLogin(persistentSettings.daemonUsername, persistentSettings.daemonPassword); - - appWindow.connectRemoteNode() + LineEdit { + id: daemonPassword + Layout.fillWidth: true + labelText: "Daemon password" + text: persistentSettings.daemonPassword + placeholderText: qsTr("Password") + translationManager.emptyString + echoMode: TextInput.Password } } } @@ -450,8 +440,6 @@ Rectangle { id: layoutSettingsLabel fontSize: 22 * scaleRatio text: qsTr("Layout settings") + translationManager.emptyString - anchors.topMargin: 30 * scaleRatio - Layout.topMargin: 30 * scaleRatio } Rectangle { @@ -483,8 +471,6 @@ Rectangle { id: logLevelLabel fontSize: 22 * scaleRatio text: qsTr("Log level") + translationManager.emptyString - anchors.topMargin: 30 * scaleRatio - Layout.topMargin: 30 * scaleRatio } Rectangle { @@ -555,12 +541,11 @@ Rectangle { ColumnLayout { LineEdit { id: logCategories - Layout.topMargin: 16 * scaleRatio Layout.fillWidth: true text: appWindow.persistentSettings.logCategories labelText: "Log Categories" placeholderText: qsTr("(e.g. *:WARNING,net.p2p:DEBUG)") + translationManager.emptyString - enabled: logLevel.currentIndex == 5 + enabled: logLevelDropdown.currentIndex === 5 onEditingFinished: { if(enabled) { console.log("log categories changed: ", text); @@ -632,6 +617,7 @@ Rectangle { StandardButton { id: restoreHeightSave + small: true Layout.fillWidth: false Layout.leftMargin: 30 text: qsTr("Save") + translationManager.emptyString @@ -703,7 +689,8 @@ Rectangle { folder: "file://" + persistentSettings.blockchainDataDir onAccepted: { - var dataDir = walletManager.urlToLocalPath(blockchainFileDialog.fileUrl) + var dataDir = walletManager.urlToLocalPath(blockchainFileDialog.fileUrl); + console.log(dataDir); var validator = daemonManager.validateDataDir(dataDir); if(!validator.valid) { diff --git a/qml.qrc b/qml.qrc index bb32bfbf..ac2a6978 100644 --- a/qml.qrc +++ b/qml.qrc @@ -194,5 +194,6 @@ images/checkedIcon-black.png components/LineEditMulti.qml components/LabelButton.qml + components/LabelSubheader.qml From 5a36aa7fce21a72328f2d615e6cb339e4c51a755 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 10 Dec 2017 23:38:21 +0100 Subject: [PATCH 073/126] Change default font color / family for checkboxes --- components/CheckBox.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/CheckBox.qml b/components/CheckBox.qml index f0b8ed9c..fce53ad7 100644 --- a/components/CheckBox.qml +++ b/components/CheckBox.qml @@ -28,6 +28,7 @@ import QtQuick 2.0 import QtQuick.Layouts 1.1 +import "." 1.0 RowLayout { id: checkBox @@ -83,9 +84,9 @@ RowLayout { Text { id: label - font.family: "Arial" + font.family: Style.fontRegular.name font.pixelSize: checkBox.fontSize - color: "#525252" + color: Style.defaultFontColor wrapMode: Text.Wrap Layout.fillWidth: true anchors.left: backgroundRect.right From e3390340821e0a367559f7a45408cec7771ef6d1 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 11 Dec 2017 00:31:52 +0100 Subject: [PATCH 074/126] Added better gradient for MenuButton, implemented 'arrow.png' for checked menu buttons and replaced leftPanel background gradient --- components/MenuButton.qml | 23 +++++++++++------------ images/arrow-right-medium-white.png | Bin 0 -> 191 bytes images/leftPanelBg.jpg | Bin 4637 -> 18457 bytes images/menuButtonGradient.png | Bin 244 -> 14654 bytes qml.qrc | 1 + 5 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 images/arrow-right-medium-white.png diff --git a/components/MenuButton.qml b/components/MenuButton.qml index f3ba56f6..ef6da091 100644 --- a/components/MenuButton.qml +++ b/components/MenuButton.qml @@ -84,19 +84,17 @@ Rectangle { Rectangle { id: dot anchors.centerIn: parent - width: 8 * scaleRatio - height: 8 * scaleRatio - radius: 4 * scaleRatio + width: button.checked ? 20 * scaleRatio : 8 * scaleRatio + height: button.checked ? 20 * scaleRatio : 8 * scaleRatio + radius: button.checked ? 20 * scaleRatio : 4 * scaleRatio color: button.dotColor - visible: !button.checked - } - - // arrow if checked - Image { - anchors.centerIn: parent - anchors.left: parent.left - source: "../images/menuArrow.png" - visible: button.checked + // arrow if checked + Image { + anchors.centerIn: parent + anchors.left: parent.left + source: "../images/arrow-right-medium-white.png" + visible: button.checked + } } // button text @@ -135,6 +133,7 @@ Rectangle { id: buttonArea anchors.fill: parent hoverEnabled: true + cursorShape: Qt.PointingHandCursor onClicked: { if(parent.checked) return diff --git a/images/arrow-right-medium-white.png b/images/arrow-right-medium-white.png new file mode 100644 index 0000000000000000000000000000000000000000..f33e9f41b22033f58573fa52a2bd73f76d57f382 GIT binary patch literal 191 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 diff --git a/images/menuButtonGradient.png b/images/menuButtonGradient.png index 3ac95cb88c089aa7f63b8b25a5eb78138a0b73c6..caeaf946aa3f275a385500f6f3b38e64e67dbadc 100644 GIT binary patch literal 14654 zcmeI3TWs4@7{^aVH%g{yLTG{^giN-<7$m-=X&NiZR+^4fTDq#uw3Zj<+9$2o#P)1w zNedDahzFiJE)Ou^39$zTlNfs%5L^(fd&%@O;msclgdRPK{>Y5FU`?{%##U@-_Lo!OBfK2yME_ z`*fj`FWiDq{|>z{;ZEfD%c@z9Dw;WkqqVX{)Ci^a)GS4v#V$96r*$J8{`Jkb!` zHXR=D3UU+qQEt$*F&B^aMO0A~xkNH5#`|MZ{9aBH#5gY`c~OW6qAUusByjaBoC%RA zWot!wEW58>j{KJn&$zB7^L({hjaFk()1KzVWHQMM5-&*+qKG(ihO5*fhO<3LvXUo@ z9o5z?S2qpL%d1S86*nCYdxaWT{l3apqmbd$*%69-O|f_}D)605n%eMK6}#jQO;dSX z!ewl@4)KW{eb$WWn$C>5M#)C^nuW=nehfQi z#a8jqF>)*0JKepj7n_sQlF92?bL_aLuVM3g0-L`Sf*DGYdzA-mthlCKFwIgXSY@Lt z2)V&Qe^qh24(WzwR-L<3e7mJN-_2||tGGBr)?*?fN)b^k2!bs3%0mA=WMK*dND?U9 za^y`-FV1z&(JR3mK-r#y>>o{Wl`F~uwIGkC%0<&ID{e+FE7O>_jOi5LYy`^2s*(rI zl4+A+;Y=*WcWMSMf2GO8hT|%Riifiq(h${kO-_i3K1orONWT{AiwHt*A~Ge#`y+8t z&=ONcwJ0bg`zrgY)LB!lc)O*ZTD!{Bz`iQ=0b3_0ol*iCZ}eANqC=WhrE_wdpj;2UfFVuL#%N|c^-e~%8KfpW*ODn5Lip`Ev?OA zHJo*u{(mPh$Pesm*Qm~5W4#R(r1Dj3CvnW8TUBg4FiqCPmF)E(Ypbn2eTw%^|B~K1 z5kYI~{H(0l)$^J14mFvq1u`zhp93+)uWD;n4)hb=oR%uSJ|PL@B0qiPs#{@qyLEDX zE9`E!Hk}6z-OWh#YHiKH<(<62u`o^^5^$z39*@OSe0y`dV^pu<(nMA#``7VSr6`db z^G)qN9i5ZF34Nfw?hB?0{G9tU8MKmz1@fH2Hy%`4C%Lf^u5r-3p=+ENrej4Q4QkAA zQ4v7_!v$$jV}^^02nrZ3NP`+PTvS9*z;Hnt)R^I-B7y>j3(}y*3>Os<6fj(n1~q25 zsED9|;es@%F~dbg1O*Hiq(O}tE-E4@V7MR+YRqs^5kUdN1!+)YhKq^_3K%X(gBmkj zR76m~a6uZ>nBk%#f&zvM(xAo+7Zni{FkFxZHDIYL5&$M zDk3OgxF8K`%y3Z=K>@=BX;5Q^i;4&e7%oVI8Z%r}L{PwRK^oL}U0k8&tAE%a@B3BB zi+!Swm&i+joSGZUBQ(Dgq2rGs^w%=^{t=;yfY48e5t5%p=w|b&2jAUCw9gD@2MVe)_v!a%?_7R$e#`MsZhv@p`H{U(qsy6vZgB(p{O z%DukpoU!ZNw|DjZQag3>tq0!O^xdVN*Pi?I#Pjdv{M@})mNKD+qFrTOt47biC^ef07V3+E5SzWMz33)`-r`iBf?dHFhY YY9P7$x6>OI$iHZKXe4{)zQd3H2UI-g&j0`b delta 196 zcmV;#06YJ_a`XX^IDY^KbV*G`2jL494J#6i%Iir0005IoL_t&-(~Xcp76LI0LO<-fcBVM yXQu-uOY_v7WwMS}?LK|F$!IU1_;Xzk{&-(KQ#}HzR1{YL0000components/LineEditMulti.qml components/LabelButton.qml components/LabelSubheader.qml + images/arrow-right-medium-white.png From 676d976e5326b62ee227d1067615394b2a2c3292 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 11 Dec 2017 00:32:30 +0100 Subject: [PATCH 075/126] Pointinghand cursor for checkboxes --- components/CheckBox.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/CheckBox.qml b/components/CheckBox.qml index fce53ad7..517917a3 100644 --- a/components/CheckBox.qml +++ b/components/CheckBox.qml @@ -76,6 +76,7 @@ RowLayout { MouseArea { anchors.fill: parent + cursorShape: Qt.PointingHandCursor onClicked: { toggle() } @@ -93,6 +94,7 @@ RowLayout { anchors.leftMargin: !isMobile ? 10 : 8 MouseArea { anchors.fill: parent + cursorShape: Qt.PointingHandCursor onClicked: { toggle() } From 129562594d83e2d3a945ebf6a9c6892baebea6e8 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 11 Dec 2017 00:33:04 +0100 Subject: [PATCH 076/126] Removing unnecessary label --- pages/Settings.qml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pages/Settings.qml b/pages/Settings.qml index 54985b53..76d03535 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -378,16 +378,6 @@ Rectangle { } } - RowLayout { - visible: daemonAdvanced.checked && !isMobile - Layout.fillWidth: true - Layout.bottomMargin: 0 * scaleRatio - - LabelSubheader { - text: qsTr("Advanced daemon options") + translationManager.emptyString - } - } - RowLayout{ CheckBox { id: daemonAdvanced From 4f3bf839f7515d5a19488f44d91e11247001de66 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 24 Dec 2017 21:52:29 +0100 Subject: [PATCH 077/126] Hover effects for titlebar buttons --- components/StandardButton.qml | 2 +- components/TitleBar.qml | 32 ++++++++++++++++++++++++-------- images/rightArrow.png | Bin 0 -> 437 bytes pages/Transfer.qml | 1 + qml.qrc | 1 + 5 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 images/rightArrow.png diff --git a/components/StandardButton.qml b/components/StandardButton.qml index 76c8c889..0429c77e 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -32,6 +32,7 @@ import "." 1.0 Item { id: button + property string rightIcon: "" property string icon: "" property string textColor: button.enabled? Style.buttonTextColor: Style.buttonTextColorDisabled property bool small: false @@ -58,7 +59,6 @@ Item { anchors.right: parent.right height: parent.height - 1 radius: 3 -// color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled border.width: parent.focus ? 1 : 0 diff --git a/components/TitleBar.qml b/components/TitleBar.qml index 5fe5ffa5..a6dfaadf 100644 --- a/components/TitleBar.qml +++ b/components/TitleBar.qml @@ -84,7 +84,7 @@ Rectangle { property bool checked: false anchors.top: parent.top anchors.left: parent.left - color: "black" + color: "transparent" height: 50 * scaleRatio width: height visible: isMobile @@ -101,6 +101,9 @@ Rectangle { id: basicMouseArea hoverEnabled: true anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onEntered: goToBasicVersionButton.color = "#262626"; + onExited: goToBasicVersionButton.color = "transparent"; onClicked: { releaseFocus() parent.checked = !parent.checked @@ -118,7 +121,7 @@ Rectangle { z: 2 Rectangle { - property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse + id: whatIsAreaButton anchors.top: parent.top anchors.bottom: parent.bottom width: 42 @@ -134,6 +137,9 @@ Rectangle { MouseArea { id: whatIsArea anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onEntered: whatIsAreaButton.color = "#262626"; + onExited: whatIsAreaButton.color = "transparent"; onClicked: { } @@ -141,11 +147,11 @@ Rectangle { } Rectangle { - property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse + id: minimizeButton anchors.top: parent.top anchors.bottom: parent.bottom width: 42 - color: containsMouse ? "#3665B3" : "#00000000" + color: "transparent" Image { anchors.centerIn: parent @@ -155,6 +161,10 @@ Rectangle { MouseArea { id: minimizeArea anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onEntered: minimizeButton.color = "#262626"; + onExited: minimizeButton.color = "transparent"; onClicked: { appWindow.visibility = Window.Minimized } @@ -163,11 +173,10 @@ Rectangle { Rectangle { id: maximizeButton - property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse anchors.top: parent.top anchors.bottom: parent.bottom width: 42 - color: containsMouse ? "#FF6C3C" : "#00000000" + color: "transparent"; Image { anchors.centerIn: parent @@ -175,12 +184,15 @@ Rectangle { width: 16 source: appWindow.visibility === Window.FullScreen ? "../images/backToWindowIcon.png" : "../images/fullscreen.png" - } MouseArea { id: maximizeArea anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onEntered: maximizeButton.color = "#262626"; + onExited: maximizeButton.color = "transparent"; onClicked: { appWindow.visibility = appWindow.visibility !== Window.FullScreen ? Window.FullScreen : Window.Windowed @@ -189,7 +201,7 @@ Rectangle { } Rectangle { - property bool containsMouse: titleBar.mouseX >= x + row.x && titleBar.mouseX <= x + row.x + width && titleBar.containsMouse + id: closeButton anchors.top: parent.top anchors.bottom: parent.bottom width: 42 @@ -205,6 +217,10 @@ Rectangle { MouseArea { anchors.fill: parent onClicked: appWindow.close(); + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onEntered: closeButton.color = "#262626"; + onExited: closeButton.color = "transparent"; } } } diff --git a/images/rightArrow.png b/images/rightArrow.png new file mode 100644 index 0000000000000000000000000000000000000000..2dd60c5d96cb86340573e121fced5f98347b78eb GIT binary patch literal 437 zcmV;m0ZRUfP)Px$Z%IT!R5%f1WWWOc|NqYl6b^u56Cf=GRrU->p8?_xAk4_f_!}yYn*tgZ0K|8I zm=L%PQ~D0dXfGQ?ST`^e|zVN~U2j^E*)t1d4*ZNhyGMA7~0I5QD;lAozD- z)&Ku*@8MDhGJ}-?NQB~2fiC{LR_N{T8li9hU*AHPg7HH^fr&e&Py&X5fhBW4Bg4;6 zKmJU#_{Q+|E}ATu8vt_QO_=dS(NE96`(4WX?su*5m;Z0?qHDRy2o(7YG@A!x{{M%^ z8UC%${|I!&7qERei2t8oa{d4QL6DJ0^czdTDJ}*<1(?b&nCS;5MIQa1LN8;)_)U-t zL3xun@ch#IKNCzD7})vQS@KVEGYBc7>pKH7a09w1F8-fs4*wb0`8ZhePjE2^D`Qi( z0pw*+!X~CL_)k>A23Z3%ka}4U=5C;&}I6z%V-Qo+$rNkDnpm4{?wu~@? fkZGVova0|9$IY5L$Pcb800000NkvXXu0mjf^L)FN literal 0 HcmV?d00001 diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 88be98c8..73c85b2c 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -275,6 +275,7 @@ Rectangle { RowLayout { StandardButton { id: sendButton + rightIcon: "../images/rightIcon.png" Layout.bottomMargin: 17 * scaleRatio Layout.topMargin: 17 * scaleRatio text: qsTr("Send") + translationManager.emptyString diff --git a/qml.qrc b/qml.qrc index ac1000d6..c1826e1f 100644 --- a/qml.qrc +++ b/qml.qrc @@ -196,5 +196,6 @@ components/LabelButton.qml components/LabelSubheader.qml images/arrow-right-medium-white.png + images/rightArrow.png From c28d2daf20126a3293627fb250ca6356f092b130 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 24 Dec 2017 22:48:59 +0100 Subject: [PATCH 078/126] White text for tick delegate --- components/TickDelegate.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/TickDelegate.qml b/components/TickDelegate.qml index f7c14eaf..94ead579 100644 --- a/components/TickDelegate.qml +++ b/components/TickDelegate.qml @@ -27,6 +27,8 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 +import "." 1.0 + Item { id: delegateItem @@ -50,7 +52,7 @@ Item { font.family: "Arial" font.bold: true font.pixelSize: 12 * scaleRatio - color: "#4A4949" + color: Style.defaultFontColor text: { if(currentIndex === 0) return qsTr("Default") + translationManager.emptyString if(currentIndex === 13) return qsTr("High") + translationManager.emptyString From cf2791a246c68bff6664843733ff661335db3d79 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 27 Dec 2017 00:53:21 +0100 Subject: [PATCH 079/126] New history page, including the mobile version. --- MiddlePanel.qml | 3 +- components/DatePicker.qml | 114 ++-- components/HistoryTable.qml | 706 ++++++++++++------------- components/HistoryTableInnerColumn.qml | 91 ++++ components/HistoryTableMobile.qml | 46 +- components/LineEdit.qml | 28 +- components/LineEditMulti.qml | 11 +- components/StandardButton.qml | 2 +- components/StandardDialog.qml | 16 +- components/StandardDropdown.qml | 33 +- components/Style.qml | 5 +- components/TableHeader.qml | 34 +- images/downArrow.png | Bin 0 -> 284 bytes images/historyBorderRadius.png | Bin 0 -> 203 bytes images/upArrow-green.png | Bin 0 -> 350 bytes pages/History.qml | 632 ++++++++-------------- pages/Transfer.qml | 1 - qml.qrc | 4 + 18 files changed, 851 insertions(+), 875 deletions(-) create mode 100644 components/HistoryTableInnerColumn.qml create mode 100644 images/downArrow.png create mode 100755 images/historyBorderRadius.png create mode 100644 images/upArrow-green.png diff --git a/MiddlePanel.qml b/MiddlePanel.qml index bc1bc76c..62d1946c 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -49,6 +49,7 @@ Rectangle { property string unlockedBalanceLabelText: qsTr("Unlocked Balance") + translationManager.emptyString property string unlockedBalanceText property int minHeight: (appWindow.height > 800) ? appWindow.height : 800 * scaleRatio + property alias contentHeight: mainFlickable.contentHeight // property int headerHeight: header.height property Transfer transferView: Transfer { } @@ -111,7 +112,7 @@ Rectangle { name: "History" PropertyChanges { target: root; currentView: historyView } PropertyChanges { target: historyView; model: appWindow.currentWallet ? appWindow.currentWallet.historyModel : null } - PropertyChanges { target: mainFlickable; contentHeight: minHeight } + PropertyChanges { target: mainFlickable; contentHeight: historyView.tableHeight + 220 * scaleRatio } }, State { name: "Transfer" PropertyChanges { target: root; currentView: transferView } diff --git a/components/DatePicker.qml b/components/DatePicker.qml index 8988f2bd..6fb3605d 100644 --- a/components/DatePicker.qml +++ b/components/DatePicker.qml @@ -29,18 +29,23 @@ import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 +import "../components" +import "." 1.0 + Item { id: datePicker property bool expanded: false property date currentDate property bool showCurrentDate: true - property color backgroundColor : "#FFFFFF" - property color errorColor : "#FFDDDD" + property color backgroundColor : "#404040" + property color errorColor : "red" property bool error: false + property alias inputLabel: inputLabel - height: 37 - width: 156 + signal dateChanged(); + + height: 50 onExpandedChanged: if(expanded) appWindow.currentItem = datePicker @@ -57,28 +62,48 @@ Item { return true } + Rectangle { + id: inputLabelRect + color: "transparent" + height: 22 + width: parent.width + + Text { + id: inputLabel + anchors.top: parent.top + anchors.left: parent.left + font.family: Style.fontRegular.name + font.pixelSize: 16 + font.bold: false + textFormat: Text.RichText + color: Style.defaultFontColor + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + } + Item { id: head - anchors.fill: parent - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - height: parent.height - //radius: 4 - y: 0 - color: "#DBDBDB" - - } + anchors.top: inputLabelRect.bottom + anchors.topMargin: 6 * scaleRatio + anchors.left: parent.left + anchors.right: parent.right + height: 28 Rectangle { + anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right height: parent.height - 1 anchors.leftMargin: datePicker.expanded ? 1 : 0 anchors.rightMargin: datePicker.expanded ? 1 : 0 - //radius: 4 + radius: 4 y: 1 - color: datePicker.error ? datePicker.errorColor : datePicker.backgroundColor + color: datePicker.backgroundColor } Item { @@ -89,24 +114,18 @@ Item { anchors.margins: 4 width: height - StandardButton { - id: button - anchors.fill: parent - icon: "../images/datePicker.png" - visible: !datePicker.expanded - onClicked: datePicker.expanded = true - } - Image { + id: button anchors.centerIn: parent - source: "../images/datePicker.png" - visible: datePicker.expanded + source: "../images/whiteDropIndicator.png" + rotation: datePicker.expanded ? 180 : 0 } MouseArea { anchors.fill: parent - enabled: datePicker.expanded - onClicked: datePicker.expanded = false + onClicked: datePicker.expanded = !datePicker.expanded + hoverEnabled: true + cursorShape: Qt.PointingHandCursor } } @@ -117,7 +136,7 @@ Item { anchors.rightMargin: 4 height: 16 width: 1 - color: "#DBDBDB" + color: "#808080" visible: datePicker.expanded } @@ -146,9 +165,9 @@ Item { id: dayInput readOnly: true width: 22 - font.family: "Arial" - font.pixelSize: 18 - // color: "#525252" + font.family: Style.fontRegular.name + font.pixelSize: 14 + color: datePicker.error ? errorColor : Style.defaultFontColor maximumLength: 2 horizontalAlignment: TextInput.AlignHCenter validator: IntValidator{bottom: 01; top: 31;} @@ -169,19 +188,19 @@ Item { } Text { - font.family: "Arial" - font.pixelSize: 18 - // color: "#525252" - text: "." + font.family: Style.fontRegular.name + font.pixelSize: 14 + color: datePicker.error ? errorColor : Style.defaultFontColor + text: "-" } TextInput { id: monthInput readOnly: true width: 22 - font.family: "Arial" - font.pixelSize: 18 - // color: "#525252" + font.family: Style.fontRegular.name + font.pixelSize: 14 + color: datePicker.error ? errorColor : Style.defaultFontColor maximumLength: 2 horizontalAlignment: TextInput.AlignHCenter validator: IntValidator{bottom: 01; top: 12;} @@ -201,18 +220,18 @@ Item { } Text { - font.family: "Arial" - font.pixelSize: 18 - // color: "#525252" - text: "." + font.family: Style.fontRegular.name + font.pixelSize: 14 + color: datePicker.error ? errorColor : Style.defaultFontColor + text: "-" } TextInput { id: yearInput width: 44 - font.family: "Arial" - font.pixelSize: 18 - /// color: "#525252" + font.family: Style.fontRegular.name + font.pixelSize: 14 + color: datePicker.error ? errorColor : Style.defaultFontColor maximumLength: 4 horizontalAlignment: TextInput.AlignHCenter validator: IntValidator{bottom: 1000; top: 9999;} @@ -268,6 +287,7 @@ Item { gridVisible: false background: Rectangle { color: "transparent" } dayDelegate: Item { + z: 8 implicitHeight: implicitWidth implicitWidth: calendar.width / 7 @@ -304,6 +324,8 @@ Item { calendar.showNextMonth() else calendar.showPreviousMonth() } + + dateChanged(); } } } diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index 18d05f6d..9954e4da 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -30,6 +30,7 @@ import QtQuick 2.0 import moneroComponents.Clipboard 1.0 import moneroComponents.AddressBookModel 1.0 import "../components" as MoneroComponents +import "." 1.0 ListView { id: listView @@ -65,11 +66,10 @@ ListView { return addressBookModel.data(idx, AddressBookModel.AddressBookDescriptionRole) } - footer: Rectangle { - height: 127 + height: 127 * scaleRatio width: listView.width - color: "#FFFFFF" + color: "transparent" Text { anchors.centerIn: parent @@ -80,396 +80,370 @@ ListView { } } + function get_color(i){ + if (i === 0){ + return "green"; + } else { + return "red"; + } + } + delegate: Rectangle { id: delegate - height: 144 + property bool collapsed: index ? false : true + height: collapsed ? 180 * scaleRatio : 70 * scaleRatio width: listView.width - color: index % 2 ? "#F8F8F8" : "#FFFFFF" - z: listView.count - index - function collapseDropdown() { dropdown.expanded = false } + color: "#CC000000" - StandardButton { - id: detailsButton - anchors.right:parent.right - anchors.rightMargin: 15 - anchors.top: parent.top - anchors.topMargin: parent.height/2 - this.height/2 - width: 80 - fontSize: 14 - text: qsTr("Details") - onClicked: { - var tx_key = currentWallet.getTxKey(hash) - var tx_note = currentWallet.getUserNote(hash) - var rings = currentWallet.getRings(hash) - if (rings) - rings = rings.replace(/\|/g, '\n') - informationPopup.title = "Transaction details"; - informationPopup.content = buildTxDetailsString(hash,paymentId,tx_key,tx_note,destinations, rings); - informationPopup.onCloseCallback = null - informationPopup.open(); - } + function collapse(){ + delegate.height = 180 * scaleRatio; } - - - Row { - id: row1 - anchors.left: parent.left + // borders + Rectangle{ anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: 14 - // -- direction indicator - Rectangle { - id: dot - width: 14 - height: width - radius: width / 2 - color: isOut ? "#FF4F41" : "#36B05B" - } - - Item { //separator - width: 12 - height: 14 - } - - // -- description aka recepient name from address book (TODO) - /* - Text { - id: descriptionText - width: text.length ? (descriptionArea.containsMouse ? parent.width - x - 12 : 120) : 0 - anchors.verticalCenter: dot.verticalCenter - font.family: "Arial" - font.bold: true - font.pixelSize: 19 - color: "#444444" - elide: Text.ElideRight - text: description - - MouseArea { - id: descriptionArea - anchors.fill: parent - hoverEnabled: true - } - } - */ - /* - Item { //separator - width: descriptionText.width ? 12 : 0 - height: 14 - visible: !descriptionArea.containsMouse - } - */ - // -- address (in case outgoing transaction) - N/A in case of incoming - MoneroComponents.TextBlock { - id: addressText - anchors.verticalCenter: dot.verticalCenter - width: parent.width - x - 12 - //elide: Text.ElideRight - font.family: "Arial" - font.pixelSize: 14 - color: "#545454" - text: hash - // visible: !descriptionArea.containsMouse - } + anchors.bottom: parent.bottom + width: 1 + color: "#404040" } - Row { - // - Payment ID - id: row2 + Rectangle{ anchors.left: parent.left - anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: 40 - anchors.leftMargin: 26 - - // -- "PaymentID" title - Text { - id: paymentLabel - width: 86 - anchors.bottom: parent.bottom - font.family: "Arial" - font.pixelSize: 12 - color: "#535353" - text: paymentId !== "" ? qsTr("Payment ID:") + translationManager.emptyString : "" - } - // -- "PaymentID" value - MoneroComponents.TextBlock { - id: paymentIdValue - width: 136 - anchors.bottom: parent.bottom - //elide: Text.ElideRight - font.family: "Arial" - font.pixelSize:13 - color: "#545454" - text: paymentId - - } - // Address book lookup - MoneroComponents.TextBlock { - id: addressBookLookupValue - width: 136 - anchors.bottom: parent.bottom - //elide: Text.ElideRight - font.family: "Arial" - font.pixelSize:13 - color: "#545454" - text: "(" + lookupPaymentID(paymentId) + ")" - visible: text !== "()" - } + anchors.bottom: parent.bottom + width: collapsed ? 2 : 1 + color: collapsed ? "#BBBBBB" : "#404040" } - Row { - // block height row - id: row3 - anchors.left: parent.left + + Rectangle{ anchors.right: parent.right - anchors.top: row2.bottom - anchors.topMargin: rowSpacing - anchors.leftMargin: 26 - - // -- "BlockHeight" title - Text { - id: blockHeghtTitle - anchors.bottom: parent.bottom - width: 86 - font.family: "Arial" - font.pixelSize: 12 - color: "#535353" - text: qsTr("BlockHeight:") + translationManager.emptyString - } - // -- "BlockHeight" value - MoneroComponents.TextBlock { - width: 200 - anchors.bottom: parent.bottom - //elide: Text.ElideRight - font.family: "Arial" - font.pixelSize: 13 - color: (confirmations < confirmationsRequired)? "#FF6C3C" : "#545454" - text: { - if (!isPending) - if(confirmations < confirmationsRequired) - return blockHeight + " " + qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired) - else - return blockHeight - if (!isOut) - return qsTr("UNCONFIRMED") + translationManager.emptyString - if (isFailed) - return qsTr("FAILED") + 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 - Row { - id: row4 - anchors.top: row3.bottom + anchors.bottom: parent.top anchors.left: parent.left - spacing: 12 - anchors.topMargin: rowSpacing - - Item { //separator - width: 14 - height: 14 - } - - // -- "Date" column - Column { - anchors.top: parent.top - width: 215 - - Text { - anchors.left: parent.left - font.family: "Arial" - font.pixelSize: 12 - color: "#545454" - text: qsTr("Date") + translationManager.emptyString - } - - Row { - anchors.left: parent.left - anchors.right: parent.right - spacing: 33 - - Text { - font.family: "Arial" - font.pixelSize: 18 - color: "#000000" - text: date - } - - Text { - font.family: "Arial" - font.pixelSize: 18 - color: "#000000" - text: time - } - } - } - // -- "Balance" column - // XXX: we don't have a balance - /* - Column { - anchors.top: parent.top - width: 148 - visible: false - - Text { - anchors.left: parent.left - font.family: "Arial" - font.pixelSize: 12 - color: "#545454" - text: qsTr("Balance") + translationManager.emptyString - } - - Text { - font.family: "Arial" - font.pixelSize: 18 - color: "#000000" - text: balance - } - } - */ - - // -- "Amount column - Column { - anchors.top: parent.top - - Text { - anchors.left: parent.left - font.family: "Arial" - font.pixelSize: 12 - color: "#545454" - text: qsTr("Amount") + translationManager.emptyString - } - - Row { - spacing: 2 - Text { - anchors.bottom: parent.bottom - anchors.bottomMargin: 3 - font.family: "Arial" - font.pixelSize: 16 - color: isOut ? "#FF4F41" : "#36B05B" - text: isOut ? "↓" : "↑" - } - - Text { - id: amountText - anchors.bottom: parent.bottom - font.family: "Arial" - font.pixelSize: 18 - color: isOut ? "#FF4F41" : "#36B05B" - text: displayAmount - } - } - } - - // -- "Fee column - Column { - anchors.top: parent.top - width: 148 - visible: isOut && fee != "" - Text { - anchors.left: parent.left - font.family: "Arial" - font.pixelSize: 12 - color: "#545454" - text: qsTr("Fee") + translationManager.emptyString - } - - Row { - spacing: 2 - Text { - anchors.bottom: parent.bottom - font.family: "Arial" - font.pixelSize: 18 - color: "#FF4F41" - text: fee - } - } - } + height: 1 + color: "#404040" } - - /* - // Transaction dropdown menu. - // Disable for now until AddressBook implemented - TableDropdown { - id: dropdown + Rectangle{ anchors.right: parent.right anchors.bottom: parent.bottom - anchors.bottomMargin: 11 - anchors.rightMargin: 5 - dataModel: dropModel - z: 1 - onExpandedChanged: { - if(expanded) { - listView.previousItem = delegate - listView.currentIndex = index - } + anchors.left: parent.left + height: 1 + color: "#404040" + } + + Rectangle { + id: row1 + anchors.left: parent.left + anchors.leftMargin: 20 * scaleRatio + anchors.right: parent.right + anchors.rightMargin: 20 * scaleRatio + anchors.top: parent.top + anchors.topMargin: 15 * scaleRatio + height: 40 * scaleRatio + color: "transparent" + + Image { + id: arrowImage + source: isOut ? "../images/downArrow.png" : "../images/upArrow-green.png" + height: 18 * scaleRatio + width: 12 * scaleRatio + anchors.top: parent.top + anchors.topMargin: 12 * scaleRatio } - onOptionClicked: { - if(option === 0) - clipboard.setText(address) + + Text { + id: txrxLabel + anchors.left: arrowImage.right + anchors.leftMargin: 18 * scaleRatio + font.family: Style.fontRegular.name + font.pixelSize: 14 * scaleRatio + text: isOut ? "Sent" : "Received" + color: "#808080" + } + +// // -- "BlockHeight" value +// TextEdit { +// readOnly: true +// selectByMouse: true +// width: 85 +// anchors.bottom: parent.bottom +// //elide: Text.ElideRight +// font.family: "Arial" +// font.pixelSize: 13 +// color: (confirmations < confirmationsRequired)? "#FF6C3C" : "#545454" +// text: { +// if (!isPending) +// if(confirmations < confirmationsRequired) +// return blockHeight + " " + qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired) +// else +// return blockHeight +// if (!isOut) +// return qsTr("UNCONFIRMED") + translationManager.emptyString +// if (isFailed) +// return qsTr("FAILED") + translationManager.emptyString +// return qsTr("PENDING") + translationManager.emptyString +// } +// } + + Text { + id: amountLabel + anchors.left: arrowImage.right + anchors.leftMargin: 18 * scaleRatio + anchors.top: txrxLabel.bottom + anchors.topMargin: 0 * scaleRatio + font.family: Style.fontBold.name + font.pixelSize: 18 * scaleRatio + font.bold: true + text: { return (displayAmount * 1) + " XMR" } // hack, removes trailing zeros + color: isOut ? "white" : "#2eb358" + } + + Rectangle { + anchors.right: parent.right + width: 300 * scaleRatio + height: parent.height + color: "transparent" + + Text { + id: dateLabel + anchors.left: parent.left + font.family: Style.fontRegular.name + font.pixelSize: 14 * scaleRatio + text: date + color: "#808080" + } + + Text { + id: timeLabel + anchors.left: dateLabel.right + anchors.leftMargin: 7 * scaleRatio + anchors.top: parent.top + anchors.topMargin: 3 * scaleRatio + font.pixelSize: 12 * scaleRatio + text: time + color: "#808080" + } + + Text { + id: toLabel + property string address: "" + color: "#BBBBBB" + anchors.left: parent.left + anchors.top: dateLabel.bottom + anchors.topMargin: 0 + font.family: Style.fontRegular.name + font.pixelSize: 16 * scaleRatio + text: { + if(isOut){ + var _address = destinations.split(" ")[1]; + if(_address === undefined) return "" + + if(_address){ + address = _address; + var address_truncated = address.substring(0, 6) + "..." + address.substring(address.length-6); + return "To " + address_truncated; + } else { + return "Unknown recipient"; + } + } + return "" + } + + MouseArea{ + visible: parent.address !== undefined + hoverEnabled: true + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onEntered: { + toLabel.color = "white"; + } + onExited: { + toLabel.color = "#BBBBBB"; + } + onClicked: { + if(parent.address){ + console.log(parent.address + " copied to clipboard"); + clipboard.setText(parent.address); + appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3) + } + } + } + } + + Rectangle { + height: 24 * scaleRatio + width: 24 * scaleRatio + color: "transparent" + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + Image { + id: dropdownImage + height: 8 * scaleRatio + width: 12 * scaleRatio + source: "../images/whiteDropIndicator.png" + rotation: delegate.collapsed ? 180 : 0 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + } + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + delegate.collapsed = !delegate.collapsed; + } + } + } } } Rectangle { + id: row2 anchors.left: parent.left + anchors.leftMargin: 20 * scaleRatio anchors.right: parent.right - anchors.bottom: parent.bottom - height: 1 - color: "#DBDBDB" - } - */ - } + anchors.rightMargin: 20 * scaleRatio + anchors.top: row1.bottom + anchors.topMargin: 15 * scaleRatio + height: 40 * scaleRatio + color: "transparent" + visible: delegate.collapsed - ListModel { - id: dropModel - ListElement { name: "Copy address to clipboard"; icon: "../images/dropdownCopy.png" } - ListElement { name: "Add to address book"; icon: "../images/dropdownAdd.png" } - ListElement { name: "Send to this address"; icon: "../images/dropdownSend.png" } - ListElement { name: "Find similar transactions"; icon: "../images/dropdownSearch.png" } + // left column + HistoryTableInnerColumn{ + anchors.left: parent.left + anchors.leftMargin: 30 * scaleRatio + + labelHeader: "Transaction ID" + labelValue: hash.substring(0, 18) + "..." + copyValue: hash + } + + // right column + HistoryTableInnerColumn{ + anchors.right: parent.right + anchors.rightMargin: 100 * scaleRatio + width: 200 * scaleRatio + height: parent.height + color: "transparent" + + labelHeader: qsTr("Fee") + labelValue: { + if(!isOut && !fee){ + return "-"; + } else if(isOut && fee){ + return fee + " XMR"; + } else { + return "Unknown" + } + } + copyValue: { + if(isOut && fee){ return fee } + else { return "" } + } + } + + } + + Rectangle { + id: row3 + anchors.left: parent.left + anchors.leftMargin: 20 * scaleRatio + anchors.right: parent.right + anchors.rightMargin: 20 * scaleRatio + anchors.top: row2.bottom + anchors.topMargin: 15 * scaleRatio + height: 40 * scaleRatio + color: "transparent" + visible: delegate.collapsed + + // left column + HistoryTableInnerColumn{ + anchors.left: parent.left + anchors.leftMargin: 30 * scaleRatio + labelHeader: qsTr("Payment ID") + labelValue: paymentId !== "" && !paymentId.startsWith("00000000") ? paymentId.substring(0, 32) + "..." : "-" + copyValue: { + if(paymentId !== "") { return paymentId } + else { return undefined } + } + } + + // right column + HistoryTableInnerColumn { + visible: currentWallet.getUserNote(hash) + anchors.right: parent.right + anchors.rightMargin: 80 * scaleRatio + width: 220 * scaleRatio + height: parent.height + color: "transparent" + + labelHeader: qsTr("Description") + labelValue: { + var note = currentWallet.getUserNote(hash); + if(note){ + if(note.length > 28) { + return note.substring(0, 28) + "..."; + } else { + return note; + } + } else { + return ""; + } + } + copyValue: { + return currentWallet.getUserNote(hash); + } + } + + Rectangle { + id: detailsButton + color: "#404040" + height: 24 * scaleRatio + width: 24 * scaleRatio + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.bottomMargin: 6 + radius: 20 * scaleRatio + + MouseArea { + id: detailsButtonMouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + var tx_key = currentWallet.getTxKey(hash) + var tx_note = currentWallet.getUserNote(hash) + var rings = currentWallet.getRings(hash) + if (rings) + rings = rings.replace(/\|/g, '\n') + informationPopup.title = "Transaction details"; + informationPopup.content = buildTxDetailsString(hash,paymentId,tx_key,tx_note,destinations, rings); + informationPopup.onCloseCallback = null + informationPopup.open(); + } + + onEntered: { + detailsButton.color = "#656565"; + } + + onExited: { + detailsButton.color = "#404040"; + } + } + + Text { + color: Style.defaultFontColor + text: "?" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: 14 * scaleRatio + } + } + } } Clipboard { id: clipboard } diff --git a/components/HistoryTableInnerColumn.qml b/components/HistoryTableInnerColumn.qml new file mode 100644 index 00000000..61c39deb --- /dev/null +++ b/components/HistoryTableInnerColumn.qml @@ -0,0 +1,91 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.2 +import moneroComponents.Clipboard 1.0 +import moneroComponents.PendingTransaction 1.0 +import moneroComponents.Wallet 1.0 +import "../components" +import "." 1.0 + + +Rectangle{ + Clipboard { id: clipboard } + + width: label1.width > label2.width ? label1.width : label2.width + height: label1.height + label2.height + color: "transparent" + + property string copyValue: "" + property alias labelHeader: label1.text + property alias labelValue: label2.text + + Text { + id: label1 + anchors.left: parent.left + font.family: Style.fontRegular.name + font.pixelSize: 14 * scaleRatio + text: labelHeader + color: Style.greyFontColor + } + + Text { + id: label2 + anchors.left: parent.left + anchors.top: label1.bottom + font.family: Style.fontRegular.name + font.pixelSize: 14 * scaleRatio + text: labelValue + color: Style.dimmedFontColor + } + + // hover effect / copy value + MouseArea { + visible: copyValue !== "" + hoverEnabled: true + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onEntered: { + label1.color = Style.defaultFontColor; + label2.color = Style.defaultFontColor; + } + onExited: { + label1.color = Style.greyFontColor; + label2.color = Style.dimmedFontColor; + } + onClicked: { + if(copyValue){ + console.log(copyValue + " copied to clipboard"); + clipboard.setText(copyValue); + appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) + } + } + } +} diff --git a/components/HistoryTableMobile.qml b/components/HistoryTableMobile.qml index 3b1dc31c..8ea5afcc 100644 --- a/components/HistoryTableMobile.qml +++ b/components/HistoryTableMobile.qml @@ -68,7 +68,7 @@ ListView { footer: Rectangle { height: 127 * scaleRatio width: listView.width - color: "#FFFFFF" + color: "transparent" Text { anchors.centerIn: parent @@ -83,10 +83,35 @@ ListView { id: delegate height: tableContent.height + 20 * scaleRatio width: listView.width - color: index % 2 ? "#F8F8F8" : "#FFFFFF" + color: "transparent" Layout.leftMargin: 10 * scaleRatio z: listView.count - index function collapseDropdown() { dropdown.expanded = false } + + Rectangle{ + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: "#404040" + } + + Rectangle{ + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.top: parent.top + width: 1 + color: "#404040" + } + + Rectangle{ + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.left: parent.left + height: 1 + color: "#404040" + } + MouseArea { anchors.fill: parent onClicked: { @@ -109,7 +134,7 @@ ListView { anchors.topMargin: parent.height/2 - this.height/2 width: 30 * scaleRatio; height: 30 * scaleRatio radius: 25 - color: "#FF4304" + color: "#404040" Image { width: 20 * scaleRatio @@ -127,16 +152,16 @@ ListView { Layout.topMargin: 20 * scaleRatio Layout.leftMargin: 10 * scaleRatio Text { - font.family: "Arial" + font.family: Style.fontMedium.name font.pixelSize: 14 * scaleRatio - color: "#555555" + color: Style.defaultFontColor text: date } Text { - font.family: "Arial" + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio - color: "#555555" + color: Style.dimmedFontColor text: time } @@ -144,7 +169,7 @@ ListView { Text { visible: confirmations < confirmationsRequired || isPending Layout.leftMargin: 5 * scaleRatio - font.family: "Arial" + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: (confirmations < confirmationsRequired)? "#FF6C3C" : "#545454" text: { @@ -161,7 +186,6 @@ ListView { } } - // Amount & confirmations RowLayout { Layout.leftMargin: 10 * scaleRatio @@ -169,7 +193,7 @@ ListView { Text { font.family: "Arial" font.pixelSize: 14 * scaleRatio - color: isOut ? "#FF4F41" : "#36B05B" + color: isOut ? Style.defaultFontColor : "#2eb358" text: isOut ? "↓" : "↑" } @@ -177,7 +201,7 @@ ListView { id: amountText font.family: "Arial" font.pixelSize: 18 * scaleRatio - color: isOut ? "#FF4F41" : "#36B05B" + color: isOut ? Style.defaultFontColor : "#2eb358" text: displayAmount } } diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 42da1e9d..243cc767 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -33,6 +33,8 @@ Item { id: item property alias text: input.text property alias placeholderText: placeholderLabel.text + property bool placeholderCenter: false + property int placeholderFontSize: 18 property alias validator: input.validator property alias readOnly : input.readOnly property alias cursorPosition: input.cursorPosition @@ -41,6 +43,7 @@ Item { property alias inlineButtonText: inlineButtonId.text property alias inlineIcon: inlineIcon.visible property bool copyButton: false + property bool borderDisabled: false property int fontSize: 18 * scaleRatio property bool showBorder: true property bool fontBold: true @@ -48,12 +51,14 @@ Item { property alias labelText: inputLabel.text property alias labelColor: inputLabel.color property alias labelTextFormat: inputLabel.textFormat + property string backgroundColor: "transparent" property string tipText: "" property int labelFontSize: 16 * scaleRatio property bool labelFontBold: false property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment property bool showingHeader: inputLabel.text !== "" || copyButton + property int inputHeight: 42 signal labelLinkActivated(); // input label, rich text signal signal editingFinished(); signal accepted(); @@ -115,7 +120,7 @@ Item { Item{ id: inputItem - height: 40 * scaleRatio + height: inputHeight * scaleRatio anchors.top: showingHeader ? inputLabel.bottom : parent.top anchors.topMargin: showingHeader ? 6 * scaleRatio : 2 width: parent.width @@ -124,12 +129,20 @@ Item { id: placeholderLabel visible: input.text ? false : true anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: inlineIcon.visible ? 50 * scaleRatio : 10 * scaleRatio + anchors.horizontalCenter: placeholderCenter ? parent.horizontalCenter : undefined + anchors.left: placeholderCenter ? undefined : parent.left + anchors.leftMargin: { + if(placeholderCenter){ + return undefined; + } + else if(inlineIcon.visible){ return 50 * scaleRatio; } + else { return 10 * scaleRatio; } + } + opacity: 0.25 color: Style.defaultFontColor font.family: Style.fontRegular.name - font.pixelSize: 18 * scaleRatio + font.pixelSize: placeholderFontSize * scaleRatio text: "" z: 3 } @@ -141,8 +154,10 @@ Item { } Rectangle { - color: "transparent" - border.width: 1 + id: inputFill + color: backgroundColor + anchors.fill: parent + border.width: borderDisabled ? 0 : 1 border.color: { if(input.activeFocus){ return Qt.rgba(255, 255, 255, 0.35); @@ -151,7 +166,6 @@ Item { } } radius: 4 - anchors.fill: parent } Image { diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 6c9dcf7a..abed2696 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -39,13 +39,14 @@ ColumnLayout { property alias readOnly: multiLine.readOnly property alias addressValidation: multiLine.addressValidation property alias labelButtonText: labelButton.text + property bool labelFontBold: false property bool labelButtonVisible: false property bool copyButton: false signal labelButtonClicked(); signal inputLabelLinkActivated(); spacing: 0 - Rectangle{ + Rectangle { id: inputLabelRect color: "transparent" Layout.fillWidth: true @@ -77,9 +78,9 @@ ColumnLayout { anchors.rightMargin: labelButton.visible? 4 : 0 onClicked: { if (multiLine.text.length > 0) { - console.log(multiLine.text + " copied to clipboard") - clipboard.setText(multiLine.text) - appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) + console.log(multiLine.text + " copied to clipboard"); + clipboard.setText(multiLine.text); + appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3); } } } @@ -91,6 +92,8 @@ ColumnLayout { addressValidation: true anchors.top: inputLabelRect.bottom Layout.fillWidth: true + topPadding: 10 + bottomPadding: 10 Text { id: placeholderLabel diff --git a/components/StandardButton.qml b/components/StandardButton.qml index 0429c77e..02e08be8 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -62,7 +62,7 @@ Item { color: parent.enabled ? Style.buttonBackgroundColor : Style.buttonBackgroundColorDisabled border.width: parent.focus ? 1 : 0 - MouseArea{ + MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor hoverEnabled: true diff --git a/components/StandardDialog.qml b/components/StandardDialog.qml index 7c9315d5..4804f294 100644 --- a/components/StandardDialog.qml +++ b/components/StandardDialog.qml @@ -37,7 +37,7 @@ import "../components" as MoneroComponents Rectangle { id: root - color: "white" + color: "transparent" visible: false property alias title: dialogTitle.text property alias text: dialogContent.text @@ -55,6 +55,14 @@ Rectangle { signal rejected() signal closeCallback(); + Image { + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "../images/middlePanelBg.jpg" + } + // Make window draggable MouseArea { anchors.fill: parent @@ -99,7 +107,7 @@ Rectangle { horizontalAlignment: Text.AlignHCenter font.pixelSize: 18 * scaleRatio font.family: "Arial" - color: "#555555" + color: Style.defaultFontColor } } @@ -115,6 +123,10 @@ Rectangle { font.pixelSize: 12 * scaleRatio selectByMouse: false wrapMode: TextEdit.Wrap + textColor: Style.defaultFontColor + style: TextAreaStyle { + backgroundColor: "black" + } MouseArea { anchors.fill: parent diff --git a/components/StandardDropdown.qml b/components/StandardDropdown.qml index f22cbab0..371b426e 100644 --- a/components/StandardDropdown.qml +++ b/components/StandardDropdown.qml @@ -39,11 +39,17 @@ Item { property string textColor: "#FFFFFF" property alias currentIndex: column.currentIndex property bool expanded: false + property int dropdownHeight: 40 + property int fontHeaderSize: 16 * scaleRatio + property int fontItemSize: 14 * scaleRatio + property string colorHeaderBackground: "transparent" + property bool headerBorder: true + property bool headerFontBold: true + + height: dropdownHeight signal changed(); - height: 40 * scaleRatio - onExpandedChanged: if(expanded) appWindow.currentItem = dropdown function hide() { dropdown.expanded = false } function containsPoint(px, py) { @@ -68,15 +74,14 @@ Item { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - height: 40 * scaleRatio + height: dropdown.dropdownHeight Rectangle { - color: "transparent" - border.width: 1 + color: dropdown.colorHeaderBackground + border.width: dropdown.headerBorder ? 1 : 0 border.color: Qt.rgba(1, 1, 1, 0.25) radius: 4 anchors.fill: parent - z: 4 } Text { @@ -86,8 +91,8 @@ Item { anchors.leftMargin: 12 * scaleRatio elide: Text.ElideRight font.family: Style.fontRegular.name - font.bold: true - font.pixelSize: 16 * scaleRatio + font.bold: dropdown.headerFontBold + font.pixelSize: dropdown.fontHeaderSize color: "#FFFFFF" } @@ -109,6 +114,8 @@ Item { id: dropArea anchors.fill: parent onClicked: dropdown.expanded = !dropdown.expanded + hoverEnabled: true + cursorShape: Qt.PointingHandCursor } } @@ -162,23 +169,23 @@ Item { property string stringSent: qsTr("Sent") + translationManager.emptyString property string stringReceived: qsTr("Received") + translationManager.emptyString - delegate: Rectangle { anchors.left: parent.left anchors.right: parent.right - height: 30 * scaleRatio + height: (dropdown.dropdownHeight * 0.75) * scaleRatio //radius: index === repeater.count - 1 ? 4 : 0 color: itemArea.containsMouse || index === column.currentIndex || itemArea.containsMouse ? dropdown.releasedColor : dropdown.pressedColor Text { + id: col1Text anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.right: col2Text.left anchors.leftMargin: 12 * scaleRatio - anchors.rightMargin: column2.length > 0 ? 12 * scaleRatio: 0 + anchors.rightMargin: 0 font.family: Style.fontRegular.name font.bold: true - font.pixelSize: 14 * scaleRatio + font.pixelSize: fontItemSize color: itemArea.containsMouse || index === column.currentIndex || itemArea.containsMouse ? "#FA6800" : "#FFFFFF" text: qsTr(column1) + translationManager.emptyString } @@ -191,7 +198,7 @@ Item { font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: "#FFFFFF" - text: column2 + text: "" } Rectangle { diff --git a/components/Style.qml b/components/Style.qml index 5e1dd26f..ffe9c194 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -8,7 +8,11 @@ QtObject { property QtObject fontLight: FontLoader { id: _fontLight; source: "qrc:/fonts/SFUIDisplay-Light.otf"; } property QtObject fontRegular: FontLoader { id: _fontRegular; source: "qrc:/fonts/SFUIDisplay-Regular.otf"; } + property string grey: "#404040" + property string defaultFontColor: "white" + property string greyFontColor: "#808080" + property string dimmedFontColor: "#BBBBBB" property string inputBoxBackground: "black" property string inputBoxBackgroundError: "#FFDDDD" property string inputBoxColor: "white" @@ -17,7 +21,6 @@ QtObject { property string buttonBackgroundColorHover: "#E65E00" property string buttonBackgroundColorDisabled: "#707070" property string buttonBackgroundColorDisabledHover: "#808080" - property string buttonTextColor: "white" property string buttonTextColorDisabled: "black" property string dividerColor: "white" diff --git a/components/TableHeader.qml b/components/TableHeader.qml index d1f1778b..2936599e 100644 --- a/components/TableHeader.qml +++ b/components/TableHeader.qml @@ -36,26 +36,40 @@ Rectangle { property int offset: 0 height: 31 - color: "#FFFFFF" + color: "transparent" + + Rectangle{ + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: "#808080" + } + + Rectangle{ + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: "#808080" + } Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom height: 1 - color: "#DBDBDB" + color: "#808080" } Row { id: row - anchors.horizontalCenter: header.offset !== 0 ? undefined: parent.horizontalCenter - anchors.left: header.offset !== 0 ? parent.left : undefined - anchors.leftMargin: header.offset + anchors.horizontalCenter: parent.horizontalCenter Rectangle { height: 31 width: 1 - color: "#DBDBDB" + color: "#808080" } Repeater { @@ -70,6 +84,7 @@ Rectangle { delegate: Rectangle { id: delegate property bool desc: false + color: "transparent" height: 31 width: columnWidth @@ -86,7 +101,7 @@ Rectangle { color: { if(delegateArea.pressed) return "#FF4304" - return index === header.activeSortColumn || delegateArea.containsMouse ? "#FF6C3C" : "#4A4949" + return index === header.activeSortColumn || delegateArea.containsMouse ? "white" : "#808080" } text: qsTr(columnName) + translationManager.emptyString } @@ -95,6 +110,7 @@ Rectangle { id: delegateArea hoverEnabled: true anchors.fill: parent + cursorShape: Qt.PointingHandCursor onClicked: { delegate.desc = !delegate.desc header.activeSortColumn = index @@ -170,7 +186,7 @@ Rectangle { anchors.right: parent.right anchors.bottom: parent.bottom height: 1 - color: index === header.activeSortColumn ? "#FFFFFF" : "#DBDBDB" + color: "transparent" } Rectangle { @@ -178,7 +194,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.right: parent.right width: 1 - color: "#DBDBDB" + color: "#808080" } } } diff --git a/images/downArrow.png b/images/downArrow.png new file mode 100644 index 0000000000000000000000000000000000000000..3e03d314bf9305befe7494509c359a2fd56f066c GIT binary patch literal 284 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eO!2~29oL&(Pq&N#aB8wRqxP?KOkzv*x37{Z* ziKnkC`$HZ{9%Hp@fqhm$q1~P?jv*T7-%i-bdssoh)nCJ7n)mvH3_b_gMC2M~#_T-) ziGk;UT#rL*N^Ii~O%10t8mAa4ukNppx4NrdrG88zdC7YQh5}>OzX$AH`ajz&&y2eM zb=SJvdGnq>wwN(9$cw>=Bk0t|Ld{eTMhCCXDM6O$4EL%PUHCZ__k3q4I_IUSq_nnF zll8#1T-z(Iny%S@t@3*k(|8Ov8$SEjv~}CHTf$qzvfn-rpIf|k>$O?M@76XI-uPY{ eIZe;)KWBV*YpL;Fw$ngwFnGH9xvXf4P4aYc45^sYd(M#Skb?m01$oY$ zt=E!XGsZlUJ#$gVwz)!d_EyPlQ3VN8JPi{zZZzD`qLVi3zRkb+r!3oNW;2%Tzr&F6 zit`4O#p+k{X1cmm8Sh>`rA7or>2U z-oL7kt&NS1oj~jz8?o?I+r+6a-+r?eaLwO-KQSdWXvL<7LE>o%2?>uTJP%*9J^fL_ z&w>{hFTYGz=$hwe|NG$uWi>vrqgB;>m33mRQqgH~+s>!Yw|{4U@Pqub1ONZaf1jW5 zEbXc3w2&1WQ-9Sx|GPZcUw)hX&;QTmH~Ihn|MUBXzbBRlpWk=CvR_Pzr)swH7c=(- soJNKMjBcU}m#G8&wLUyPS&NB5e}ey)o%=t{1qK9zr>mdKI;Vst07M*;+W-In literal 0 HcmV?d00001 diff --git a/pages/History.qml b/pages/History.qml index 26b74808..2e44b940 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -27,7 +27,8 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 - +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.2 import moneroComponents.Wallet 1.0 import moneroComponents.WalletManager 1.0 import moneroComponents.TransactionHistory 1.0 @@ -39,13 +40,14 @@ import "../components" Rectangle { id: root property var model + property int tableHeight: !isMobile ? table.contentHeight : tableMobile.contentHeight QtObject { id: d property bool initialized: false } - color: "#F0EEEE" + color: "transparent" function getSelectedAmount() { if (typeof model === 'undefined' || model == null) @@ -81,178 +83,25 @@ Rectangle { onModelChanged: { if (typeof model !== 'undefined' && model != null) { - - selectedAmount.text = getSelectedAmount() - if (!d.initialized) { // setup date filter scope according to real transactions fromDatePicker.currentDate = model.transactionHistory.firstDateTime toDatePicker.currentDate = model.transactionHistory.lastDateTime - /* Default sorting by timestamp desc */ - /* Sort indicator on table header */ - /* index of 'sort by blockheight' column */ - header.activeSortColumn = 2 - /* Sorting model */ - model.sortRole = TransactionHistoryModel.TransactionBlockHeightRole model.sort(0, Qt.DescendingOrder); d.initialized = true - // TODO: public interface for 'Header' item that will cause 'sortRequest' signal } - } } function onFilterChanged() { + // set datepicker error states var datesValid = fromDatePicker.currentDate <= toDatePicker.currentDate - var amountsValid = amountFromLine.text === "" ? true : - amountToLine.text === "" ? true: - parseFloat(amountFromLine.text) <= parseFloat(amountToLine.text) - - // reset error state if amount filter valid - if (amountsValid) { - amountFromLine.error = amountToLine.error = false - } - - filterButton.enabled = datesValid && amountsValid - } - - - Text { - visible: !isMobile - id: filterHeaderText - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.leftMargin: 17 - anchors.topMargin: 17 - - elide: Text.ElideRight - font.family: "Arial" - font.pixelSize: 18 - color: "#4A4949" - text: qsTr("Filter transaction history") + translationManager.emptyString - } - - Label { - visible: !isMobile - id: selectedAmount - anchors.right: parent.right - anchors.top: parent.top - anchors.rightMargin: 17 - anchors.topMargin: 17 - text: getSelectedAmount() - fontSize: 14 - } - - // Filter by string - LineEdit { - visible: !isMobile - id: searchLine - anchors.left: parent.left - anchors.right: parent.right - anchors.top: filterHeaderText.bottom - anchors.leftMargin: 17 - anchors.rightMargin: 17 - anchors.topMargin: 5 - placeholderText: qsTr("Type for incremental search...") + translationManager.emptyString - onTextChanged: { - model.searchFilter = searchLine.text - selectedAmount.text = getSelectedAmount() - } - } - - // Filter by description input (not implemented yet) - /* - Label { - id: descriptionLabel - anchors.left: parent.left - anchors.top: searchLine.bottom - anchors.leftMargin: 17 - anchors.topMargin: 17 - text: qsTr("Description (Local database)") + translationManager.emptyString - fontSize: 14 - } - - LineEdit { - id: descriptionLine - anchors.left: parent.left - anchors.right: parent.right - anchors.top: descriptionLabel.bottom - anchors.leftMargin: 17 - anchors.rightMargin: 17 - anchors.topMargin: 5 - } - */ - - - // DateFrom picker - Label { - visible: !isMobile - id: dateFromText - anchors.left: parent.left - anchors.top: searchLine.bottom // descriptionLine.bottom - anchors.leftMargin: 17 - anchors.topMargin: 17 - width: 156 - text: qsTr("Date from") + translationManager.emptyString - fontSize: 14 - } - - DatePicker { - visible: !isMobile - id: fromDatePicker - anchors.left: parent.left - anchors.top: dateFromText.bottom - anchors.leftMargin: 17 - anchors.topMargin: 5 - z: 2 - onCurrentDateChanged: { - error = currentDate > toDatePicker.currentDate - onFilterChanged() - } - } - - // DateTo picker - Label { - visible: !isMobile - id: dateToText - anchors.left: dateFromText.right - anchors.top: searchLine.bottom //descriptionLine.bottom - anchors.leftMargin: 17 - anchors.topMargin: 17 - text: qsTr("To") + translationManager.emptyString - fontSize: 14 - } - - DatePicker { - visible: !isMobile - id: toDatePicker - anchors.left: fromDatePicker.right - anchors.top: dateToText.bottom - anchors.leftMargin: 17 - anchors.topMargin: 5 - z: 2 - onCurrentDateChanged: { - error = currentDate < fromDatePicker.currentDate - onFilterChanged() - } - } - - - - StandardButton { - visible: !isMobile - id: filterButton - anchors.bottom: toDatePicker.bottom - anchors.left: toDatePicker.right - anchors.leftMargin: 17 - width: 60 - text: qsTr("Filter") + translationManager.emptyString - onClicked: { - // Apply filter here; + fromDatePicker.error = !datesValid; + toDatePicker.error = !datesValid; + if(datesValid){ resetFilter(model) if (fromDatePicker.currentDate > toDatePicker.currentDate) { @@ -262,279 +111,233 @@ Rectangle { model.dateToFilter = toDatePicker.currentDate } - if (advancedFilteringCheckBox.checked) { - if (amountFromLine.text.length) { - model.amountFromFilter = parseFloat(amountFromLine.text) - } - - if (amountToLine.text.length) { - model.amountToFilter = parseFloat(amountToLine.text) - } - - var directionFilter = transactionsModel.get(transactionTypeDropdown.currentIndex).value - console.log("Direction filter: " + directionFilter) - model.directionFilter = directionFilter - } - - selectedAmount.text = getSelectedAmount() + model.searchFilter = searchLine.text; + tableHeader.visible = model.rowCount() > 0; } } - CheckBox { - visible: !isMobile - id: advancedFilteringCheckBox - text: qsTr("Advanced filtering") + translationManager.emptyString - anchors.left: filterButton.right - anchors.bottom: filterButton.bottom - anchors.leftMargin: 17 - onClicked: { - if(checked) tableRect.height = Qt.binding(function(){ return tableRect.collapsedHeight }) - else tableRect.height = Qt.binding(function(){ return tableRect.middleHeight }) - } + Rectangle{ + id: rootLayout + visible: false } - Label { - visible: !isMobile - id: transactionTypeText + ColumnLayout { + id: pageRoot + anchors.margins: isMobile ? 17 : 20 * scaleRatio + anchors.topMargin: isMobile ? 0 : 40 * scaleRatio + anchors.left: parent.left - anchors.top: fromDatePicker.bottom - anchors.leftMargin: 17 - anchors.topMargin: 17 - width: 156 - text: qsTr("Type of transaction") + translationManager.emptyString - fontSize: 14 - } - - ListModel { - id: transactionsModel - ListElement { column1: "All"; column2: ""; value: TransactionInfo.Direction_Both } - ListElement { column1: "Sent"; column2: ""; value: TransactionInfo.Direction_Out } - ListElement { column1: "Received"; column2: ""; value: TransactionInfo.Direction_In } - - } - - StandardDropdown { - visible: !isMobile - id: transactionTypeDropdown - anchors.left: parent.left - anchors.top: transactionTypeText.bottom - anchors.leftMargin: 17 - anchors.topMargin: 5 - width: 156 - shadowReleasedColor: "#4D0051" - shadowPressedColor: "#2D002F" - releasedColor: "#6B0072" - pressedColor: "#4D0051" - dataModel: transactionsModel - z: 1 - } - - Label { - visible: !isMobile - id: amountFromText - anchors.left: transactionTypeText.right - anchors.top: fromDatePicker.bottom - anchors.leftMargin: 17 - anchors.topMargin: 17 - width: 156 - text: qsTr("Amount from") + translationManager.emptyString - fontSize: 14 - } - - LineEdit { - visible: !isMobile - id: amountFromLine - anchors.left: transactionTypeDropdown.right - anchors.top: amountFromText.bottom - anchors.leftMargin: 17 - anchors.topMargin: 5 - width: 156 - validator: DoubleValidator { - locale: "C" - notation: DoubleValidator.StandardNotation - bottom: 0 - } - onTextChanged: { - // indicating error - amountFromLine.error = amountFromLine.text === "" ? false : parseFloat(amountFromLine.text) > parseFloat(amountToLine.text) - onFilterChanged() - } - - } - - Label { - visible: !isMobile - id: amountToText - anchors.left: amountFromText.right - anchors.top: fromDatePicker.bottom - anchors.leftMargin: 17 - anchors.topMargin: 17 - width: 156 - text: qsTr("To") + translationManager.emptyString - fontSize: 14 - } - - LineEdit { - visible: !isMobile - id: amountToLine - anchors.left: amountFromLine.right - anchors.top: amountToText.bottom - anchors.leftMargin: 17 - anchors.topMargin: 5 - width: 156 - validator: DoubleValidator { - locale: "C" - notation: DoubleValidator.StandardNotation - bottom: 0.0 - } - - onTextChanged: { - // indicating error - amountToLine.error = amountToLine.text === "" ? false : parseFloat(amountFromLine.text) > parseFloat(amountToLine.text) - onFilterChanged() - } - - } - - Item { - visible: !isMobile - id: expandItem - property bool expanded: false - + anchors.top: parent.top anchors.right: parent.right - anchors.bottom: tableRect.top - width: 34 - height: 34 - Image { - anchors.centerIn: parent - source: "../images/expandTable.png" - rotation: parent.expanded ? 180 : 0 - } + spacing: 0 - MouseArea { - anchors.fill: parent - onClicked: { - parent.expanded = !parent.expanded - if (advancedFilteringCheckBox.checked) { - tableRect.height = Qt.binding(function() { return parent.expanded ? tableRect.expandedHeight : tableRect.collapsedHeight }) - } else { - tableRect.height = Qt.binding(function() { return parent.expanded ? tableRect.expandedHeight : tableRect.middleHeight }) + GridLayout { + columns: (isMobile)? 1 : 2 + Layout.fillWidth: true + columnSpacing: 26 * scaleRatio + + RowLayout { + visible: !isMobile + } + + RowLayout { + LineEdit { + id: searchLine + fontSize: 14 * scaleRatio + inputHeight: 28 * scaleRatio + borderDisabled: true + Layout.fillWidth: true + backgroundColor: "#404040" + placeholderText: qsTr("Search") + translationManager.emptyString + placeholderCenter: true + onTextChanged: { + onFilterChanged(); + } } } } - } - Rectangle { - id: tableRect - property int expandedHeight: parent.height - filterHeaderText.y - filterHeaderText.height - 5 - property int middleHeight: parent.height - fromDatePicker.y - fromDatePicker.height - 17 - property int collapsedHeight: parent.height - transactionTypeDropdown.y - transactionTypeDropdown.height - 17 - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom -// anchors.top: parent.top - color: "#FFFFFF" - z: 1 - - height: (isMobile)? parent.height : middleHeight - onHeightChanged: { - if(height === middleHeight) z = 1 - else if(height === collapsedHeight) z = 0 - else z = 3 - } - - Behavior on height { - NumberAnimation { duration: 200; easing.type: Easing.InQuad } - } - - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - height: 1 - color: "#DBDBDB" - } - - ListModel { - id: columnsModel - property int pidWidth: 127 * scaleRatio - ListElement { columnName: "Payment ID"; columnWidth: 127 } - ListElement { columnName: "Date"; columnWidth: 100 } - ListElement { columnName: "Block height"; columnWidth: 150 } - ListElement { columnName: "Amount"; columnWidth: 148 } - // ListElement { columnName: "Description"; columnWidth: 148 } - } - - TableHeader { - id: header + GridLayout { + z: 6 + columns: (isMobile)? 1 : 3 + Layout.fillWidth: true + columnSpacing: 22 * scaleRatio visible: !isMobile - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.topMargin: 17 * scaleRatio - anchors.leftMargin: 14 * scaleRatio - anchors.rightMargin: 14 * scaleRatio - dataModel: columnsModel - offset: 20 - onSortRequest: { - console.log("column: " + column + " desc: " + desc) - switch (column) { - case 0: - // Payment ID - model.sortRole = TransactionHistoryModel.TransactionPaymentIdRole - break; - case 1: - // Date (actually sort by timestamp as we want to have transactions sorted within one day as well); - model.sortRole = TransactionHistoryModel.TransactionTimeStampRole - break; - case 2: - // BlockHeight; - model.sortRole = TransactionHistoryModel.TransactionBlockHeightRole - break; - case 3: - // Amount; - model.sortRole = TransactionHistoryModel.TransactionAmountRole - break; + + ColumnLayout { + Layout.fillWidth: true + + RowLayout { + Layout.fillWidth: true + id: fromDateRow + Layout.minimumWidth: 150 * scaleRatio + + DatePicker { + visible: !isMobile + + id: fromDatePicker + Layout.fillWidth: true + width: 100 * scaleRatio + inputLabel.text: "Date from" + + onCurrentDateChanged: { + onFilterChanged() + } + } + } + } + + ColumnLayout { + Layout.fillWidth: true + + RowLayout { + Layout.fillWidth: true + id: toDateRow + Layout.minimumWidth: 150 * scaleRatio + + DatePicker { + visible: !isMobile + + id: toDatePicker + Layout.fillWidth: true + width: 100 * scaleRatio + inputLabel.text: "Date to" + + onCurrentDateChanged: { + onFilterChanged() + } + } + } + } + + ColumnLayout { + Layout.fillWidth: true + + Label { + id: transactionPriority + Layout.minimumWidth: 120 * scaleRatio + text: qsTr("Sort") + translationManager.emptyString + } + + ListModel { + id: priorityModelV5 + + ListElement { column1: qsTr("Block height") ; column2: "";} + ListElement { column1: qsTr("Date") ; column2: ""; } + } + + StandardDropdown { + id: priorityDropdown + anchors.topMargin: 2 * scaleRatio + fontHeaderSize: 14 * scaleRatio + dropdownHeight: 28 * scaleRatio + + Layout.fillWidth: true + shadowReleasedColor: "#FF4304" + shadowPressedColor: "#B32D00" + releasedColor: "#404040" + pressedColor: "#202020" + colorHeaderBackground: "#404040" + + onChanged: { + switch(priorityDropdown.currentIndex){ + case 0: + // block sort + model.sortRole = TransactionHistoryModel.TransactionBlockHeightRole; + break; + case 1: + // amount sort + model.sortRole = TransactionHistoryModel.TransactionDateRole; + break; + } + model.sort(0, Qt.DescendingOrder); + } + } - model.sort(0, desc ? Qt.DescendingOrder : Qt.AscendingOrder) } } - Scroll { - id: flickableScroll - visible: !isMobile - anchors.right: table.right - anchors.rightMargin: !isMobile ? -14 * scaleRatio : 0 - anchors.top: table.top - anchors.bottom: table.bottom - flickable: table - } + GridLayout { + id: tableHeader + columns: 1 + columnSpacing: 0 + rowSpacing: 0 + Layout.topMargin: 20 + Layout.fillWidth: true - HistoryTable { - id: table - visible: !isMobile - anchors.left: parent.left - anchors.right: parent.right - anchors.top: header.bottom - anchors.bottom: parent.bottom - anchors.leftMargin: 14 * scaleRatio - anchors.rightMargin: 14 * scaleRatio - onContentYChanged: flickableScroll.flickableContentYChanged() - model: !isMobile ? root.model : null - addressBookModel: null - } + RowLayout{ + Layout.preferredHeight: 10 + Layout.fillWidth: true - HistoryTableMobile { - id: tableMobile - visible: isMobile - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - onContentYChanged: flickableScroll.flickableContentYChanged() - model: isMobile ? root.model : null - addressBookModel: null + Rectangle { + id: header + Layout.fillWidth: true + + height: 10 + color: "#CC000000" + + Rectangle { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.leftMargin: 10 + + height: 1 + color: "#404040" + } + + Image { + anchors.top: parent.top + anchors.left: parent.left + + width: 10 + height: 10 + + source: "../images/historyBorderRadius.png" + } + + Image { + anchors.top: parent.top + anchors.right: parent.right + + width: 10 + height: 10 + + source: "../images/historyBorderRadius.png" + rotation: 90 + } + } + } + + RowLayout { + Layout.preferredHeight: isMobile ? tableMobile.contentHeight : table.contentHeight + Layout.fillWidth: true + Layout.fillHeight: true + + HistoryTable { + id: table + visible: !isMobile + onContentYChanged: flickableScroll.flickableContentYChanged() + model: !isMobile ? root.model : null + addressBookModel: null + + Layout.fillWidth: true + Layout.fillHeight: true + } + + HistoryTableMobile { + id: tableMobile + visible: isMobile + onContentYChanged: flickableScroll.flickableContentYChanged() + model: isMobile ? root.model : null + addressBookModel: null + + Layout.fillWidth: true + Layout.fillHeight: true + } + } } } @@ -542,8 +345,11 @@ Rectangle { if(currentWallet != null && typeof currentWallet.history !== "undefined" ) { currentWallet.history.refresh(currentWallet.currentSubaddressAccount) table.addressBookModel = currentWallet ? currentWallet.addressBookModel : null - transactionTypeDropdown.update() + //transactionTypeDropdown.update() } + priorityDropdown.dataModel = priorityModelV5; + priorityDropdown.currentIndex = 0; + priorityDropdown.update(); } } diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 73c85b2c..6e45b62a 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -388,7 +388,6 @@ Rectangle { onFillLevelChanged: updateMixin() } - GridLayout { visible: persistentSettings.transferShowAdvanced Layout.topMargin: 50 * scaleRatio diff --git a/qml.qrc b/qml.qrc index c1826e1f..e6d5c51c 100644 --- a/qml.qrc +++ b/qml.qrc @@ -197,5 +197,9 @@ components/LabelSubheader.qml images/arrow-right-medium-white.png images/rightArrow.png + images/upArrow-green.png + images/downArrow.png + images/historyBorderRadius.png + components/HistoryTableInnerColumn.qml From a9b6a70d1594f18b77187b5423e88086129429f9 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 12 Jan 2018 01:17:20 +0100 Subject: [PATCH 080/126] Cleanup after rebase --- LeftPanel.qml | 29 ++++++++++++++--------------- components/NewPasswordDialog.qml | 8 -------- components/StandardDialog.qml | 2 +- pages/Settings.qml | 9 +++++---- pages/TxKey.qml | 6 +----- 5 files changed, 21 insertions(+), 33 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index a999f9ad..d2eb3df0 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -110,7 +110,7 @@ Rectangle { anchors.leftMargin: 20 anchors.verticalCenter: parent.verticalCenter height: 490 * scaleRatio - width: 50 * scaleRatio + width: 259 * scaleRatio Image { width: 259; height: 170 @@ -128,22 +128,21 @@ Rectangle { anchors.leftMargin: 192 font.bold: true font.pixelSize: 12 - color: "red" - opacity: 1 + color: "#f33434" } - // @TODO: implement - // Text { - // id: viewOnlyLabel - // visible: viewOnly - // text: qsTr("View Only") + translationManager.emptyString - // anchors.top: logo.bottom - // anchors.topMargin: 5 - // anchors.left: parent.left - // anchors.leftMargin: 50 - // font.bold: true - // color: "blue" - // } + Text { + id: viewOnlyLabel + visible: viewOnly + text: qsTr("View Only") + translationManager.emptyString + anchors.top: parent.top + anchors.topMargin: 8 + anchors.right: testnetLabel.visible ? testnetLabel.left : parent.right + anchors.rightMargin: 8 + font.pixelSize: 12 + font.bold: true + color: "#ff9323" + } } Item { diff --git a/components/NewPasswordDialog.qml b/components/NewPasswordDialog.qml index 414a225d..af9c0973 100644 --- a/components/NewPasswordDialog.qml +++ b/components/NewPasswordDialog.qml @@ -224,10 +224,6 @@ Item { MoneroComponents.StandardButton { id: cancelButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Cancel") + translationManager.emptyString KeyNavigation.tab: passwordInput1 onClicked: { @@ -237,10 +233,6 @@ Item { } MoneroComponents.StandardButton { id: okButton - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Continue") KeyNavigation.tab: cancelButton enabled: passwordInput1.text === passwordInput2.text diff --git a/components/StandardDialog.qml b/components/StandardDialog.qml index 4804f294..56ce06e2 100644 --- a/components/StandardDialog.qml +++ b/components/StandardDialog.qml @@ -120,7 +120,7 @@ Rectangle { font.family: "Arial" textFormat: TextEdit.AutoText readOnly: true - font.pixelSize: 12 * scaleRatio + font.pixelSize: 14 * scaleRatio selectByMouse: false wrapMode: TextEdit.Wrap textColor: Style.defaultFontColor diff --git a/pages/Settings.qml b/pages/Settings.qml index 76d03535..4fd49cb4 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -168,14 +168,15 @@ Rectangle { } } } + } + + RowLayout{ + Layout.fillWidth: true StandardButton { id: changePasswordButton + small: true text: qsTr("Change password") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" onClicked: { passwordDialog.onAcceptedCallback = function() { if(appWindow.walletPassword === passwordDialog.password){ diff --git a/pages/TxKey.qml b/pages/TxKey.qml index 2e8f3a37..8ed3b8fe 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -184,11 +184,7 @@ Rectangle { anchors.topMargin: 17 width: 60 text: qsTr("Generate") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" - enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype)) + enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) onClicked: { console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) From 6677a185f8ec869a5b8bd8adce349b80a3c9ddd4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 12 Jan 2018 01:45:27 +0100 Subject: [PATCH 081/126] Some font adjustments --- components/DatePicker.qml | 5 +++-- components/LineEdit.qml | 8 ++++---- components/LineEditMulti.qml | 12 ++++++------ pages/History.qml | 2 ++ pages/Transfer.qml | 2 ++ 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/components/DatePicker.qml b/components/DatePicker.qml index 6fb3605d..c08f97ad 100644 --- a/components/DatePicker.qml +++ b/components/DatePicker.qml @@ -71,10 +71,11 @@ Item { Text { id: inputLabel anchors.top: parent.top + anchors.topMargin: 2 anchors.left: parent.left font.family: Style.fontRegular.name - font.pixelSize: 16 - font.bold: false + font.pixelSize: 14 + font.bold: true textFormat: Text.RichText color: Style.defaultFontColor diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 243cc767..7f46506f 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -34,7 +34,7 @@ Item { property alias text: input.text property alias placeholderText: placeholderLabel.text property bool placeholderCenter: false - property int placeholderFontSize: 18 + property int placeholderFontSize: 18 * scaleRatio property alias validator: input.validator property alias readOnly : input.readOnly property alias cursorPosition: input.cursorPosition @@ -53,12 +53,12 @@ Item { property alias labelTextFormat: inputLabel.textFormat property string backgroundColor: "transparent" property string tipText: "" - property int labelFontSize: 16 * scaleRatio - property bool labelFontBold: false + property int labelFontSize: 14 * scaleRatio + property bool labelFontBold: true property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment property bool showingHeader: inputLabel.text !== "" || copyButton - property int inputHeight: 42 + property int inputHeight: 42 * scaleRatio signal labelLinkActivated(); // input label, rich text signal signal editingFinished(); signal accepted(); diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index abed2696..5cc76e2d 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -39,7 +39,7 @@ ColumnLayout { property alias readOnly: multiLine.readOnly property alias addressValidation: multiLine.addressValidation property alias labelButtonText: labelButton.text - property bool labelFontBold: false + property bool labelFontBold: true property bool labelButtonVisible: false property bool copyButton: false signal labelButtonClicked(); @@ -50,14 +50,14 @@ ColumnLayout { id: inputLabelRect color: "transparent" Layout.fillWidth: true - height: inputLabel.height + 10 + height: (inputLabel.height + 10) * scaleRatio Text { id: inputLabel anchors.top: parent.top anchors.left: parent.left font.family: Style.fontRegular.name - font.pixelSize: 16 * scaleRatio + font.pixelSize: 14 * scaleRatio font.bold: labelFontBold textFormat: Text.RichText color: Style.defaultFontColor @@ -92,15 +92,15 @@ ColumnLayout { addressValidation: true anchors.top: inputLabelRect.bottom Layout.fillWidth: true - topPadding: 10 - bottomPadding: 10 + topPadding: 10 * scaleRatio + bottomPadding: 10 * scaleRatio Text { id: placeholderLabel visible: multiLine.text ? false : true anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left - anchors.leftMargin: 10 + anchors.leftMargin: 10 * scaleRatio opacity: 0.25 color: Style.defaultFontColor font.family: Style.fontRegular.name diff --git a/pages/History.qml b/pages/History.qml index 2e44b940..6a0206f8 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -218,6 +218,8 @@ Rectangle { id: transactionPriority Layout.minimumWidth: 120 * scaleRatio text: qsTr("Sort") + translationManager.emptyString + fontSize: 14 + fontBold: true } ListModel { diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 6e45b62a..96bd0dc1 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -161,6 +161,8 @@ Rectangle { Label { id: transactionPriority text: qsTr("Transaction priority") + translationManager.emptyString + fontBold: true + fontSize: 14 } // Note: workaround for translations in listElements // ListElement: cannot use script for property value, so From a128581ae503649c8abac60def2a62f05e0e6e6c Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 13 Jan 2018 02:39:06 +0100 Subject: [PATCH 082/126] Restyled addressbook panel --- components/AddressBookTable.qml | 9 +++++---- pages/AddressBook.qml | 15 ++++----------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/components/AddressBookTable.qml b/components/AddressBookTable.qml index de724bb8..cae68d2f 100644 --- a/components/AddressBookTable.qml +++ b/components/AddressBookTable.qml @@ -53,7 +53,7 @@ ListView { id: delegate height: 64 width: listView.width - color: index % 2 ? "#ee6000" : "#3e3e3e" + color: "transparent" z: listView.count - index function collapseDropdown() { dropdown.expanded = false } @@ -62,7 +62,7 @@ ListView { anchors.left: parent.left anchors.top: parent.top anchors.topMargin: 12 - width: text.length ? (descriptionArea.containsMouse ? dropdown.x - x - 12 : 139) : 0 + width: text.length ? (descriptionArea.containsMouse ? 139 : 139) : 0 font.family: "Arial" font.bold: true font.pixelSize: 19 @@ -89,6 +89,7 @@ ListView { font.pixelSize: 16 color: "#ffffff" text: address + readOnly: true } Text { @@ -111,7 +112,7 @@ ListView { anchors.leftMargin: 12 anchors.rightMargin: 12 anchors.right: dropdown.left - + readOnly: true font.family: "Arial" font.pixelSize: 13 @@ -164,7 +165,7 @@ ListView { anchors.right: parent.right anchors.bottom: parent.bottom height: 1 - color: "#808080" + color: "#404040" } } } diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml index 27395a03..68598dc4 100644 --- a/pages/AddressBook.qml +++ b/pages/AddressBook.qml @@ -38,6 +38,7 @@ Rectangle { property var model ColumnLayout { + id: columnLayout anchors.margins: (isMobile)? 17 : 40 anchors.left: parent.left anchors.top: parent.top @@ -115,6 +116,9 @@ Rectangle { Rectangle { id: tableRect + anchors.top: columnLayout.bottom + anchors.leftMargin: (isMobile)? 17 : 40 + anchors.rightMargin: (isMobile)? 17 : 40 anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom @@ -125,14 +129,6 @@ Rectangle { NumberAnimation { duration: 200; easing.type: Easing.InQuad } } - Rectangle { - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - height: 1 - color: "#808080" - } - Scroll { id: flickableScroll anchors.right: table.right @@ -148,9 +144,6 @@ Rectangle { anchors.right: parent.right anchors.top: parent.top anchors.bottom: parent.bottom - anchors.topMargin: 14 - anchors.leftMargin: 14 - anchors.rightMargin: 14 onContentYChanged: flickableScroll.flickableContentYChanged() model: root.model } From 53b5b7a5c7a7894c04bdedad345f733be1dd34b7 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 21 Jan 2018 19:14:34 +0100 Subject: [PATCH 083/126] Fixing the start-up wizards --- components/Label.qml | 6 ++++-- components/LineEdit.qml | 20 ++++++++++++-------- components/RemoteNodeEdit.qml | 14 ++++++++++++++ wizard/WizardDaemonSettings.qml | 11 ++++++++++- wizard/WizardManageWalletUI.qml | 28 ++++++++++++++++++++++++++++ wizard/WizardOptions.qml | 1 + 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/components/Label.qml b/components/Label.qml index b2c4e52f..5ad72e08 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -39,6 +39,8 @@ Item { property string tipText: "" property int fontSize: 16 * scaleRatio property bool fontBold: false + property string fontColor: Style.defaultFontColor + property string fontFamily: Style.fontRegular.name property alias wrapMode: label.wrapMode property alias horizontalAlignment: label.horizontalAlignment signal linkActivated() @@ -53,10 +55,10 @@ Item { anchors.bottom: parent.bottom anchors.bottomMargin: 2 * scaleRatio anchors.left: parent.left - font.family: Style.fontRegular.name + font.family: fontFamily font.pixelSize: fontSize font.bold: fontBold - color: Style.defaultFontColor + color: fontColor onLinkActivated: item.linkActivated() } diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 7f46506f..330e3bba 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -43,14 +43,23 @@ Item { property alias inlineButtonText: inlineButtonId.text property alias inlineIcon: inlineIcon.visible property bool copyButton: false + property string borderColor: { + if(input.activeFocus){ + return Qt.rgba(255, 255, 255, 0.35); + } else { + return Qt.rgba(255, 255, 255, 0.25); + } + } property bool borderDisabled: false property int fontSize: 18 * scaleRatio property bool showBorder: true property bool fontBold: true + property alias fontColor: input.color property bool error: false property alias labelText: inputLabel.text property alias labelColor: inputLabel.color property alias labelTextFormat: inputLabel.textFormat + property string labelFontFamily: Style.fontRegular.name property string backgroundColor: "transparent" property string tipText: "" property int labelFontSize: 14 * scaleRatio @@ -59,6 +68,7 @@ Item { property alias labelHorizontalAlignment: inputLabel.horizontalAlignment property bool showingHeader: inputLabel.text !== "" || copyButton property int inputHeight: 42 * scaleRatio + signal labelLinkActivated(); // input label, rich text signal signal editingFinished(); signal accepted(); @@ -90,7 +100,7 @@ Item { anchors.top: parent.top anchors.left: parent.left anchors.topMargin: 2 * scaleRatio - font.family: Style.fontRegular.name + font.family: labelFontFamily font.pixelSize: labelFontSize font.bold: labelFontBold textFormat: Text.RichText @@ -158,13 +168,7 @@ Item { color: backgroundColor anchors.fill: parent border.width: borderDisabled ? 0 : 1 - border.color: { - if(input.activeFocus){ - return Qt.rgba(255, 255, 255, 0.35); - } else { - return Qt.rgba(255, 255, 255, 0.25); - } - } + border.color: borderColor radius: 4 } diff --git a/components/RemoteNodeEdit.qml b/components/RemoteNodeEdit.qml index 49413436..4d44c156 100644 --- a/components/RemoteNodeEdit.qml +++ b/components/RemoteNodeEdit.qml @@ -40,6 +40,11 @@ GridLayout { property alias daemonAddrLabelText: daemonAddr.labelText property alias daemonPortLabelText: daemonPort.labelText + property string lineEditBorderColor: Qt.rgba(0, 0, 0, 0.15) + property string lineEditBackgroundColor: "white" + property string lineEditFontColor: "black" + property bool lineEditFontBold: true + signal editingFinished() function getAddress() { @@ -51,6 +56,10 @@ GridLayout { Layout.fillWidth: true placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString onEditingFinished: root.editingFinished() + borderColor: lineEditBorderColor + backgroundColor: lineEditBackgroundColor + fontColor: lineEditFontColor + fontBold: lineEditFontBold } LineEdit { @@ -58,5 +67,10 @@ GridLayout { Layout.fillWidth: true placeholderText: qsTr("Port") + translationManager.emptyString onEditingFinished: root.editingFinished() + + borderColor: lineEditBorderColor + backgroundColor: lineEditBackgroundColor + fontColor: lineEditFontColor + fontBold: lineEditFontBold } } diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index 419e3cd5..c94beaa8 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -124,6 +124,7 @@ ColumnLayout { CheckBox { id: localNode text: qsTr("Start a node automatically in background (recommended)") + translationManager.emptyString + checkedIcon: "../images/checkedVioletIcon.png" background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio @@ -152,6 +153,11 @@ ColumnLayout { text: persistentSettings.blockchainDataDir placeholderText: qsTr("(optional)") + translationManager.emptyString + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false + MouseArea { anchors.fill: parent onClicked: { @@ -193,7 +199,6 @@ ColumnLayout { localNode.checked = false } } - } RowLayout { @@ -204,6 +209,10 @@ ColumnLayout { property var rna: persistentSettings.remoteNodeAddress daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : "" daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1] : "" + lineEditBorderColor: Qt.rgba(0, 0, 0, 0.15) + lineEditBackgroundColor: "white" + lineEditFontColor: "black" + lineEditFontBold: false } } } diff --git a/wizard/WizardManageWalletUI.qml b/wizard/WizardManageWalletUI.qml index 020a9e05..6f039415 100644 --- a/wizard/WizardManageWalletUI.qml +++ b/wizard/WizardManageWalletUI.qml @@ -154,6 +154,8 @@ ColumnLayout { Label { Layout.topMargin: 20 * scaleRatio + fontFamily: "Ariel" + fontColor: "#555555" fontSize: 14 * scaleRatio text: qsTr("Wallet name") + translationManager.emptyString @@ -166,6 +168,10 @@ ColumnLayout { Layout.minimumWidth: 200 * scaleRatio text: defaultAccountName onTextUpdated: checkNextButton() + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false } } @@ -232,6 +238,10 @@ ColumnLayout { Layout.minimumWidth: 200 * scaleRatio placeholderText: qsTr("Account address (public)") + translationManager.emptyString onTextUpdated: checkNextButton() + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false } LineEdit { Layout.fillWidth: true @@ -240,6 +250,10 @@ ColumnLayout { Layout.minimumWidth: 200 * scaleRatio placeholderText: qsTr("View key (private)") + translationManager.emptyString onTextUpdated: checkNextButton() + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false } LineEdit { @@ -249,6 +263,10 @@ ColumnLayout { id: spendKeyLine placeholderText: qsTr("Spend key (private)") + translationManager.emptyString onTextUpdated: checkNextButton() + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false } } @@ -263,6 +281,10 @@ ColumnLayout { validator: IntValidator { bottom:0 } + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false } } @@ -272,6 +294,8 @@ ColumnLayout { Layout.fillWidth: true Layout.topMargin: 20 * scaleRatio fontSize: 14 + fontFamily: "Ariel" + fontColor: "#555555" text: qsTr("Your wallet is stored in") + ": " + fileUrlInput.text; } @@ -292,6 +316,10 @@ ColumnLayout { fileUrlInput.focus = true } } + borderColor: Qt.rgba(0, 0, 0, 0.15) + backgroundColor: "white" + fontColor: "black" + fontBold: false } FileDialog { diff --git a/wizard/WizardOptions.qml b/wizard/WizardOptions.qml index d0e6b930..fb6d83f3 100644 --- a/wizard/WizardOptions.qml +++ b/wizard/WizardOptions.qml @@ -245,6 +245,7 @@ ColumnLayout { CheckBox { id: testNet text: qsTr("Testnet") + translationManager.emptyString + checkedIcon: "../images/checkedVioletIcon.png" background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio From 49770494251a318da37849f1c628f25edaf94483 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 28 Jan 2018 00:14:42 +0100 Subject: [PATCH 084/126] Fixes some fonts, introduces a new checkbox and fixes 0 amount history entries --- components/CheckBox2.qml | 99 +++++++++++++++++++++++++++++++++ components/DatePicker.qml | 4 +- components/HistoryTable.qml | 19 ++++++- components/InputMulti.qml | 11 +++- components/Label.qml | 12 ++-- components/LineEdit.qml | 11 ++-- components/LineEditMulti.qml | 6 +- components/StandardDropdown.qml | 6 +- pages/History.qml | 1 - pages/Keys.qml | 73 +++++++++++++----------- pages/Mining.qml | 10 +++- pages/Settings.qml | 3 + pages/Transfer.qml | 25 +++++---- qml.qrc | 1 + wizard/WizardDaemonSettings.qml | 1 + 15 files changed, 213 insertions(+), 69 deletions(-) create mode 100644 components/CheckBox2.qml diff --git a/components/CheckBox2.qml b/components/CheckBox2.qml new file mode 100644 index 00000000..dd48624e --- /dev/null +++ b/components/CheckBox2.qml @@ -0,0 +1,99 @@ +// Copyright (c) 2014-2015, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import "." 1.0 + +RowLayout { + id: checkBox + property alias text: label.text + property string checkedIcon: "../images/checkedIcon-black.png" + property string uncheckedIcon + property bool checked: false + property string background: "backgroundRect.color" + property int fontSize: 14 * scaleRatio + property alias fontColor: label.color + property int textMargin: 8 * scaleRatio + signal clicked() + height: 25 * scaleRatio + + function toggle(){ + checkBox.checked = !checkBox.checked + checkBox.clicked() + } + + RowLayout { + Layout.fillWidth: true + + Rectangle{ + height: label.height + width: (label.width + indicatorRect.width + checkBox.textMargin) + color: "transparent" + anchors.left: parent.left + + Text { + id: label + font.family: Style.fontLight + font.pixelSize: checkBox.fontSize + color: Style.defaultFontColor + wrapMode: Text.Wrap + Layout.fillWidth: true + anchors.left: parent.left + } + + Rectangle { + id: indicatorRect + width: indicatorImage.width + height: label.height + anchors.left: label.right + anchors.leftMargin: textMargin + color: "transparent" + + Image { + id: indicatorImage + anchors.centerIn: parent + source: "../images/whiteDropIndicator.png" + rotation: checkBox.checked ? 180 * scaleRatio : 0 + verticalAlignment: parent.verticalCenter + } + } + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + toggle(); + } + } + } + + + } +} diff --git a/components/DatePicker.qml b/components/DatePicker.qml index c08f97ad..ace95d2d 100644 --- a/components/DatePicker.qml +++ b/components/DatePicker.qml @@ -73,9 +73,9 @@ Item { anchors.top: parent.top anchors.topMargin: 2 anchors.left: parent.left - font.family: Style.fontRegular.name + font.family: Style.fontLight font.pixelSize: 14 - font.bold: true + font.bold: false textFormat: Text.RichText color: Style.defaultFontColor diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index 9954e4da..c083ef3c 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -156,7 +156,7 @@ ListView { id: txrxLabel anchors.left: arrowImage.right anchors.leftMargin: 18 * scaleRatio - font.family: Style.fontRegular.name + font.family: Style.fontLight.name font.pixelSize: 14 * scaleRatio text: isOut ? "Sent" : "Received" color: "#808080" @@ -195,7 +195,22 @@ ListView { font.family: Style.fontBold.name font.pixelSize: 18 * scaleRatio font.bold: true - text: { return (displayAmount * 1) + " XMR" } // hack, removes trailing zeros + text: { + // hack, removes trailing zeros + var amount = (displayAmount * 1); + + // sometimes, displayAmount is 0 - no idea why. + // in that case, we try to get the amount from + // the `destinations` string. + if(amount === 0){ + amount = destinations.split(" ")[0].split(":")[0]; + amount = (amount *1); + } + + // sometimes this destinations string also shows 0, + // at which point we run out of options. + return amount + " XMR"; + } color: isOut ? "white" : "#2eb358" } diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 0f030f2d..2df797e2 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -35,14 +35,21 @@ import "." 1.0 TextArea { property bool error: false property bool addressValidation: false + property bool wrapAnywhere: true id: textArea font.family: Style.fontRegular.name font.pixelSize: 18 * scaleRatio - font.bold: true + font.bold: false horizontalAlignment: TextInput.AlignLeft selectByMouse: true color: Style.defaultFontColor - wrapMode: Text.WrapAnywhere + wrapMode: { + if(wrapAnywhere){ + return Text.WrapAnywhere; + } else { + return Text.WordWrap; + } + } onTextChanged: { if(addressValidation){ // js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }` diff --git a/components/Label.qml b/components/Label.qml index 5ad72e08..ac0ff487 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -40,12 +40,10 @@ Item { property int fontSize: 16 * scaleRatio property bool fontBold: false property string fontColor: Style.defaultFontColor - property string fontFamily: Style.fontRegular.name + property string fontFamily: "" property alias wrapMode: label.wrapMode property alias horizontalAlignment: label.horizontalAlignment signal linkActivated() -// width: icon.x + icon.width * scaleRatio -// height: icon.height * scaleRatio height: label.height * scaleRatio width: label.width * scaleRatio Layout.topMargin: 10 * scaleRatio @@ -55,7 +53,13 @@ Item { anchors.bottom: parent.bottom anchors.bottomMargin: 2 * scaleRatio anchors.left: parent.left - font.family: fontFamily + font.family: { + if(fontFamily){ + return fontFamily; + } else { + return Style.fontLight; + } + } font.pixelSize: fontSize font.bold: fontBold color: fontColor diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 330e3bba..f488790d 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -53,17 +53,16 @@ Item { property bool borderDisabled: false property int fontSize: 18 * scaleRatio property bool showBorder: true - property bool fontBold: true + property bool fontBold: false property alias fontColor: input.color property bool error: false property alias labelText: inputLabel.text property alias labelColor: inputLabel.color property alias labelTextFormat: inputLabel.textFormat - property string labelFontFamily: Style.fontRegular.name property string backgroundColor: "transparent" property string tipText: "" property int labelFontSize: 14 * scaleRatio - property bool labelFontBold: true + property bool labelFontBold: false property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment property bool showingHeader: inputLabel.text !== "" || copyButton @@ -100,7 +99,7 @@ Item { anchors.top: parent.top anchors.left: parent.left anchors.topMargin: 2 * scaleRatio - font.family: labelFontFamily + font.family: Style.fontLight font.pixelSize: labelFontSize font.bold: labelFontBold textFormat: Text.RichText @@ -132,7 +131,7 @@ Item { id: inputItem height: inputHeight * scaleRatio anchors.top: showingHeader ? inputLabel.bottom : parent.top - anchors.topMargin: showingHeader ? 6 * scaleRatio : 2 + anchors.topMargin: showingHeader ? 12 * scaleRatio : 2 width: parent.width Text { @@ -189,7 +188,7 @@ Item { anchors.fill: parent anchors.leftMargin: inlineIcon.visible ? 38 : 0 font.pixelSize: item.fontSize - font.bold: fontBold + font.bold: item.fontBold onEditingFinished: item.editingFinished() onAccepted: item.accepted(); onTextChanged: item.textUpdated() diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 5cc76e2d..43d67602 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -39,9 +39,10 @@ ColumnLayout { property alias readOnly: multiLine.readOnly property alias addressValidation: multiLine.addressValidation property alias labelButtonText: labelButton.text - property bool labelFontBold: true + property bool labelFontBold: false property bool labelButtonVisible: false property bool copyButton: false + property bool wrapAnywhere: true signal labelButtonClicked(); signal inputLabelLinkActivated(); @@ -56,7 +57,7 @@ ColumnLayout { id: inputLabel anchors.top: parent.top anchors.left: parent.left - font.family: Style.fontRegular.name + font.family: Style.fontLight font.pixelSize: 14 * scaleRatio font.bold: labelFontBold textFormat: Text.RichText @@ -94,6 +95,7 @@ ColumnLayout { Layout.fillWidth: true topPadding: 10 * scaleRatio bottomPadding: 10 * scaleRatio + wrapAnywhere: parent.wrapAnywhere Text { id: placeholderLabel diff --git a/components/StandardDropdown.qml b/components/StandardDropdown.qml index 371b426e..0d6e771d 100644 --- a/components/StandardDropdown.qml +++ b/components/StandardDropdown.qml @@ -39,12 +39,12 @@ Item { property string textColor: "#FFFFFF" property alias currentIndex: column.currentIndex property bool expanded: false - property int dropdownHeight: 40 + property int dropdownHeight: 42 property int fontHeaderSize: 16 * scaleRatio property int fontItemSize: 14 * scaleRatio property string colorHeaderBackground: "transparent" property bool headerBorder: true - property bool headerFontBold: true + property bool headerFontBold: false height: dropdownHeight @@ -90,7 +90,7 @@ Item { anchors.left: parent.left anchors.leftMargin: 12 * scaleRatio elide: Text.ElideRight - font.family: Style.fontRegular.name + font.family: Style.fontRegular font.bold: dropdown.headerFontBold font.pixelSize: dropdown.fontHeaderSize color: "#FFFFFF" diff --git a/pages/History.qml b/pages/History.qml index 6a0206f8..3a2c79ad 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -219,7 +219,6 @@ Rectangle { Layout.minimumWidth: 120 * scaleRatio text: qsTr("Sort") + translationManager.emptyString fontSize: 14 - fontBold: true } ListModel { diff --git a/pages/Keys.qml b/pages/Keys.qml index 4bcff537..50928579 100644 --- a/pages/Keys.qml +++ b/pages/Keys.qml @@ -31,73 +31,76 @@ import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.1 import QtQuick.Dialogs 1.2 -import "../version.js" as Version - - -import "../components" import moneroComponents.Clipboard 1.0 +import "../version.js" as Version +import "../components" +import "." 1.0 + Rectangle { property bool viewOnly: false id: page - color: "#F0EEEE" + color: "transparent" Clipboard { id: clipboard } ColumnLayout { id: mainLayout - anchors.margins: 17 * scaleRatio + anchors.left: parent.left anchors.top: parent.top anchors.right: parent.right - spacing: 20 * scaleRatio + + anchors.margins: (isMobile)? 17 : 20 + anchors.topMargin: 40 * scaleRatio + + spacing: 30 * scaleRatio Layout.fillWidth: true //! Manage wallet ColumnLayout { Layout.fillWidth: true + Label { Layout.fillWidth: true + fontSize: 22 * scaleRatio + Layout.topMargin: 10 * scaleRatio text: qsTr("Mnemonic seed") + translationManager.emptyString } Rectangle { Layout.fillWidth: true - height: 1 - color: "#DEDEDE" + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + Layout.bottomMargin: 10 * scaleRatio } - TextEdit { + + LineEditMulti{ id: seedText - wrapMode: TextEdit.Wrap - Layout.fillWidth: true; - font.pixelSize: 14 * scaleRatio + spacing: 0 + copyButton: true + addressValidation: false readOnly: true - MouseArea { - anchors.fill: parent - onClicked: { - appWindow.showStatusMessage(qsTr("Double tap to copy"),3) - } - onDoubleClicked: { - parent.selectAll() - parent.copy() - parent.deselect() - console.log("copied to clipboard"); - appWindow.showStatusMessage(qsTr("Seed copied to clipboard"),3) - } - } + wrapAnywhere: false } } ColumnLayout { Layout.fillWidth: true + Label { Layout.fillWidth: true + fontSize: 22 * scaleRatio + Layout.topMargin: 10 * scaleRatio text: qsTr("Keys") + translationManager.emptyString } Rectangle { Layout.fillWidth: true - height: 1 - color: "#DEDEDE" + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + Layout.bottomMargin: 10 * scaleRatio } TextEdit { id: keysText @@ -106,6 +109,7 @@ Rectangle { font.pixelSize: 14 * scaleRatio textFormat: TextEdit.RichText readOnly: true + color: Style.defaultFontColor MouseArea { anchors.fill: parent onClicked: { @@ -124,21 +128,26 @@ Rectangle { ColumnLayout { Layout.fillWidth: true + Label { Layout.fillWidth: true + fontSize: 22 * scaleRatio + Layout.topMargin: 10 * scaleRatio text: qsTr("Export wallet") + translationManager.emptyString } Rectangle { Layout.fillWidth: true - height: 1 - color: "#DEDEDE" + height: 2 + color: Style.dividerColor + opacity: Style.dividerOpacity + Layout.bottomMargin: 10 * scaleRatio } - RowLayout { StandardButton { enabled: !fullWalletQRCode.visible id: showFullQr + small: true text: qsTr("Spendable Wallet") + translationManager.emptyString onClicked: { viewOnlyQRCode.visible = false @@ -147,6 +156,7 @@ Rectangle { StandardButton { enabled: fullWalletQRCode.visible id: showViewOnlyQr + small: true text: qsTr("View Only Wallet") + translationManager.emptyString onClicked: { viewOnlyQRCode.visible = true @@ -155,7 +165,6 @@ Rectangle { Layout.bottomMargin: 30 * scaleRatio } - Image { visible: !viewOnlyQRCode.visible id: fullWalletQRCode diff --git a/pages/Mining.qml b/pages/Mining.qml index 5726acba..11275347 100644 --- a/pages/Mining.qml +++ b/pages/Mining.qml @@ -34,7 +34,7 @@ import moneroComponents.Wallet 1.0 Rectangle { id: root - color: "#F0EEEE" + color: "transparent" property var currentHashRate: 0 /* main layout */ @@ -74,13 +74,16 @@ Rectangle { text: qsTr("Mining with your computer helps strengthen the Monero network. The more that people mine, the harder it is for the network to be attacked, and every little bit helps.

Mining also gives you a small chance to earn some Monero. Your computer will create hashes looking for block solutions. If you find a block, you will get the associated reward. Good luck!") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true + font.family: Style.fontRegular + font.pixelSize: 14 * scaleRatio + color: Style.defaultFontColor } RowLayout { id: soloMinerThreadsRow Label { id: soloMinerThreadsLabel - color: "#4A4949" + color: Style.defaultFontColor text: qsTr("CPU threads") + translationManager.emptyString fontSize: 16 Layout.preferredWidth: 120 @@ -122,7 +125,7 @@ Rectangle { RowLayout { Label { id: manageSoloMinerLabel - color: "#4A4949" + color: Style.defaultFontColor text: qsTr("Manage miner") + translationManager.emptyString fontSize: 16 } @@ -165,6 +168,7 @@ Rectangle { Text { id: statusText text: qsTr("Status: not mining") + color: Style.defaultFontColor textFormat: Text.RichText wrapMode: Text.Wrap } diff --git a/pages/Settings.qml b/pages/Settings.qml index 4fd49cb4..c0a152a8 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -239,6 +239,9 @@ Rectangle { Layout.minimumWidth: 100 * scaleRatio daemonAddrLabelText: qsTr("Address") daemonPortLabelText: qsTr("Port") + lineEditBackgroundColor: "transparent" + lineEditFontColor: "white" + lineEditBorderColor: Qt.rgba(255, 255, 255, 0.35) daemonAddrText: persistentSettings.remoteNodeAddress.split(":")[0].trim() daemonPortText: (persistentSettings.remoteNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1] onEditingFinished: { diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 96bd0dc1..b5fbfbea 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -120,7 +120,7 @@ Rectangle { anchors.top: parent.top anchors.right: parent.right - spacing: 26 * scaleRatio + spacing: 30 * scaleRatio GridLayout { columns: (isMobile)? 1 : 2 @@ -160,8 +160,9 @@ Rectangle { Layout.fillWidth: true Label { id: transactionPriority + Layout.topMargin: 14 text: qsTr("Transaction priority") + translationManager.emptyString - fontBold: true + fontBold: false fontSize: 14 } // Note: workaround for translations in listElements @@ -185,6 +186,7 @@ Rectangle { StandardDropdown { Layout.fillWidth: true id: priorityDropdown + Layout.topMargin: 6 shadowReleasedColor: "#FF4304" shadowPressedColor: "#B32D00" releasedColor: "#363636" @@ -278,8 +280,7 @@ Rectangle { StandardButton { id: sendButton rightIcon: "../images/rightIcon.png" - Layout.bottomMargin: 17 * scaleRatio - Layout.topMargin: 17 * scaleRatio + Layout.topMargin: 4 * scaleRatio text: qsTr("Send") + translationManager.emptyString enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.testnet) onClicked: { @@ -317,7 +318,7 @@ Rectangle { } // pageRoot Rectangle { - id:desaturate + id: desaturate color:"black" anchors.fill: parent opacity: 0.1 @@ -329,18 +330,18 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.margins: (isMobile)? 17 : 20 - anchors.topMargin: 40 * scaleRatio + anchors.topMargin: 32 * scaleRatio spacing: 26 * scaleRatio enabled: !viewOnly || pageRoot.enabled RowLayout { - CheckBox { + CheckBox2 { id: showAdvancedCheckbox checked: persistentSettings.transferShowAdvanced onClicked: { persistentSettings.transferShowAdvanced = !persistentSettings.transferShowAdvanced } - text: qsTr("Show advanced options") + translationManager.emptyString + text: qsTr("Advanced options") + translationManager.emptyString } } @@ -401,6 +402,7 @@ Rectangle { id: sweepUnmixableButton text: qsTr("Sweep Unmixable") + translationManager.emptyString enabled : pageRoot.enabled + small: true onClicked: { console.log("Transfer: sweepUnmixableClicked") root.sweepUnmixableClicked() @@ -412,6 +414,7 @@ Rectangle { text: qsTr("Create tx file") + translationManager.emptyString visible: appWindow.viewOnly enabled: pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype) + small: true onClicked: { console.log("Transfer: saveTx Clicked") var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority @@ -428,6 +431,7 @@ Rectangle { StandardButton { id: signTxButton text: qsTr("Sign tx file") + translationManager.emptyString + small: true visible: !appWindow.viewOnly onClicked: { console.log("Transfer: sign tx clicked") @@ -438,6 +442,7 @@ Rectangle { StandardButton { id: submitTxButton text: qsTr("Submit tx file") + translationManager.emptyString + small: true visible: appWindow.viewOnly enabled: pageRoot.enabled onClicked: { @@ -446,12 +451,8 @@ Rectangle { } } } - - } - - //SignTxDialog FileDialog { id: signTxDialog diff --git a/qml.qrc b/qml.qrc index e6d5c51c..11d2d448 100644 --- a/qml.qrc +++ b/qml.qrc @@ -201,5 +201,6 @@ images/downArrow.png images/historyBorderRadius.png components/HistoryTableInnerColumn.qml + components/CheckBox2.qml diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index c94beaa8..f7142468 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -144,6 +144,7 @@ ColumnLayout { Layout.fillWidth: true Layout.topMargin: 20 * scaleRatio fontSize: 14 * scaleRatio + fontColor: "black" text: qsTr("Blockchain location") + translationManager.emptyString } LineEdit { From 57a9508849f36c7cda513df98e478babbc3e6cb3 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 19 Mar 2018 02:42:46 +0100 Subject: [PATCH 085/126] Receive page; modified subaddress table --- components/InputDialog.qml | 8 -- components/InputMulti.qml | 6 +- components/LineEdit.qml | 2 +- components/LineEditMulti.qml | 12 +- components/SubaddressTable.qml | 91 ++++++++++--- pages/Receive.qml | 228 ++++++++++++--------------------- pages/Settings.qml | 6 + 7 files changed, 171 insertions(+), 182 deletions(-) diff --git a/components/InputDialog.qml b/components/InputDialog.qml index 8ab5b5d8..2990c5c9 100644 --- a/components/InputDialog.qml +++ b/components/InputDialog.qml @@ -150,10 +150,6 @@ Item { id: cancelButton width: 120 fontSize: 14 - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Cancel") + translationManager.emptyString KeyNavigation.tab: input onClicked: { @@ -165,10 +161,6 @@ Item { id: okButton width: 120 fontSize: 14 - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" text: qsTr("Ok") KeyNavigation.tab: cancelButton onClicked: { diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 2df797e2..f809ca10 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -36,13 +36,15 @@ TextArea { property bool error: false property bool addressValidation: false property bool wrapAnywhere: true + property int fontSize: 18 * scaleRatio id: textArea - font.family: Style.fontRegular.name - font.pixelSize: 18 * scaleRatio + font.family: Style.fontRegular + font.pixelSize: fontSize font.bold: false horizontalAlignment: TextInput.AlignLeft selectByMouse: true color: Style.defaultFontColor + wrapMode: { if(wrapAnywhere){ return Text.WrapAnywhere; diff --git a/components/LineEdit.qml b/components/LineEdit.qml index f488790d..f5e8a478 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -131,7 +131,7 @@ Item { id: inputItem height: inputHeight * scaleRatio anchors.top: showingHeader ? inputLabel.bottom : parent.top - anchors.topMargin: showingHeader ? 12 * scaleRatio : 2 + anchors.topMargin: showingHeader ? 12 * scaleRatio : 2 * scaleRatio width: parent.width Text { diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 43d67602..02f281f3 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -32,6 +32,7 @@ import "." 1.0 ColumnLayout { + id: lineditmulti property alias text: multiLine.text property alias placeholderText: placeholderLabel.text property alias inputLabelText: inputLabel.text @@ -43,6 +44,10 @@ ColumnLayout { property bool labelButtonVisible: false property bool copyButton: false property bool wrapAnywhere: true + property bool showingHeader: true + property bool showBorder: true + property int fontSize: 18 * scaleRatio + signal labelButtonClicked(); signal inputLabelLinkActivated(); @@ -52,6 +57,7 @@ ColumnLayout { color: "transparent" Layout.fillWidth: true height: (inputLabel.height + 10) * scaleRatio + visible: showingHeader ? true : false Text { id: inputLabel @@ -91,11 +97,12 @@ ColumnLayout { id: multiLine readOnly: false addressValidation: true - anchors.top: inputLabelRect.bottom + anchors.top: parent.showingHeader ? inputLabelRect.bottom : parent.top Layout.fillWidth: true - topPadding: 10 * scaleRatio + topPadding: parent.showingHeader ? 10 * scaleRatio : 0 bottomPadding: 10 * scaleRatio wrapAnywhere: parent.wrapAnywhere + fontSize: parent.fontSize Text { id: placeholderLabel @@ -125,6 +132,7 @@ ColumnLayout { } radius: 4 anchors.fill: parent + visible: lineditmulti.showBorder } } } diff --git a/components/SubaddressTable.qml b/components/SubaddressTable.qml index 8d6b8d1d..a52ed1fe 100644 --- a/components/SubaddressTable.qml +++ b/components/SubaddressTable.qml @@ -28,40 +28,57 @@ import QtQuick 2.0 import moneroComponents.Clipboard 1.0 +import "." 1.0 ListView { id: listView clip: true boundsBehavior: ListView.StopAtBounds highlightMoveDuration: 0 + highlightFollowsCurrentItem: true + anchors.topMargin: 0 + spacing: 0 delegate: Rectangle { id: delegate - height: 64 + height: 74 + color: 'transparent'; + anchors.topMargin: 0 width: listView.width - LineEdit { + LineEditMulti { id: addressLine + //borderDisabled: true fontSize: 12 readOnly: true width: parent.width anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - anchors.margins: 5 + anchors.leftMargin: 5 + anchors.topMargin: 12 + anchors.rightMargin: 40 + anchors.bottomMargin: 0 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); - } + showingHeader: false + 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); } + + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.verticalCenter: parent.verticalCenter } Text { @@ -85,7 +102,7 @@ ListView { font.family: "Arial" font.bold: true font.pixelSize: 12 - color: "#444444" + color: Style.greyFontColor text: label } @@ -96,14 +113,46 @@ ListView { anchors.bottom: parent.bottom anchors.right: parent.right anchors.rightMargin: clipboardButton.width - onClicked: listView.currentIndex = index + cursorShape: Qt.PointingHandCursor + onClicked: { + listView.currentIndex = index; + } + } + + Rectangle { + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: Style.grey + z: 6 + } + + Rectangle { + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 1 + color: Style.grey + z: 6 + } + + Rectangle { + anchors.right: parent.right + anchors.left: parent.left + anchors.bottom: parent.bottom + color: Style.grey + height: 1 + z: 6 + } + + Rectangle { + width: 3 + color: 'white' + visible: listView.currentIndex == index + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom } } - - highlight: Rectangle { - height: 64 - color: '#FF4304' - opacity: 0.2 - z: 2 - } } diff --git a/pages/Receive.qml b/pages/Receive.qml index 18c5ef72..75504387 100644 --- a/pages/Receive.qml +++ b/pages/Receive.qml @@ -26,7 +26,7 @@ // 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.7 +import QtQuick 2.0 import QtQuick.Controls 2.2 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.1 @@ -44,9 +44,6 @@ import moneroComponents.SubaddressModel 1.0 Rectangle { id: pageReceive color: "transparent" - property alias addressText : addressLine.text - property alias paymentIdText : paymentIdLine.text - property alias integratedAddressText : integratedAddressLine.text property var model property var current_address property alias addressText : pageReceive.current_address @@ -156,26 +153,69 @@ Rectangle { anchors.top: parent.top anchors.right: parent.right - spacing: 26 * scaleRatio + spacing: 20 * scaleRatio property int labelWidth: 120 * scaleRatio property int editWidth: 400 * scaleRatio property int lineEditFontSize: 12 * scaleRatio property int qrCodeSize: 240 * scaleRatio + ColumnLayout { -<<<<<<< HEAD id: addressRow + spacing: 0 Label { id: addressLabel text: qsTr("Addresses") + translationManager.emptyString width: mainLayout.labelWidth } + Rectangle { + id: header + Layout.fillWidth: true + Layout.topMargin: 10 + + height: 10 + color: "#CC000000" + + Rectangle { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.leftMargin: 10 + + height: 1 + color: "#404040" + } + + Image { + anchors.top: parent.top + anchors.left: parent.left + + width: 10 + height: 10 + + source: "../images/historyBorderRadius.png" + } + + Image { + anchors.top: parent.top + anchors.right: parent.right + + width: 10 + height: 10 + + source: "../images/historyBorderRadius.png" + rotation: 90 + } + } + Rectangle { id: tableRect Layout.fillWidth: true - Layout.preferredHeight: 200 - color: "#FFFFFF" + Layout.preferredHeight: 240 + color: "transparent" + Scroll { id: flickableScroll anchors.right: table.right @@ -183,6 +223,7 @@ Rectangle { anchors.bottom: table.bottom flickable: table } + SubaddressTable { id: table anchors.fill: parent @@ -195,11 +236,10 @@ Rectangle { RowLayout { spacing: 20 + Layout.topMargin: 20 + StandardButton { - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + small: true text: qsTr("Create new address") + translationManager.emptyString; onClicked: { inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString @@ -213,10 +253,7 @@ Rectangle { } } StandardButton { - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + small: true enabled: table.currentIndex > 0 text: qsTr("Rename") + translationManager.emptyString; onClicked: { @@ -224,123 +261,42 @@ Rectangle { inputDialog.inputText = appWindow.currentWallet.getSubaddressLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex) inputDialog.onAcceptedCallback = function() { appWindow.currentWallet.subaddress.setLabel(appWindow.currentWallet.currentSubaddressAccount, table.currentIndex, inputDialog.inputText) -======= - id: addressLineRow - - LineEditMulti { - id: addressLine - inputLabelText: qsTr("Address") + translationManager.emptyString - placeholderText: qsTr("ReadOnly wallet address displayed here") + translationManager.emptyString; - readOnly: true - Layout.fillWidth: true - copyButton: true - } - } - - GridLayout { - id: paymentIdRow - columns:2 - - // @TODO: copy button copies the wrong input box - LineEdit { - id: paymentIdLine - placeholderText: qsTr("16 hexadecimal characters") + translationManager.emptyString; - readOnly: false - onTextChanged: updatePaymentId(paymentIdLine.text) - inlineButtonText: "Generate" - inlineButton.onClicked: updatePaymentId() - width: mainLayout.editWidth - Layout.fillWidth: true - copyButton: true - labelText: qsTr("Payment ID") + qsTr("\ - (
help ) ") - + translationManager.emptyString - onLabelLinkActivated: { - trackingHowToUseDialog.title = qsTr("Tracking payments") + translationManager.emptyString; - trackingHowToUseDialog.text = qsTr( - "

This is a simple sales tracker:

" + - "

Click Generate to create a random payment id for a new customer

" + - "

Let your customer scan that QR code to make a payment (if that customer has software which " + - "supports QR code scanning).

" + - "

This page will automatically scan the blockchain and the tx pool " + - "for incoming transactions using this QR code. If you input an amount, it will also check " + - "that incoming transactions total up to that amount.

" + - "It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " + - "confirmed in short order, but there is still a possibility they might not, so for larger " + - "values you may want to wait for one or more confirmation(s).

" - ) - trackingHowToUseDialog.icon = StandardIcon.Information - trackingHowToUseDialog.open() - } - } - - // @TODO: CLEAR BUTTON should be present as labelButton -// StandardButton { -// id: clearPaymentId -// enabled: !!paymentIdLine.text -// shadowReleasedColor: "#FF4304" -// shadowPressedColor: "#B32D00" -// releasedColor: "#FF6C3C" -// pressedColor: "#FF4304" -// text: qsTr("Clear") + translationManager.emptyString; -// onClicked: updatePaymentId("") -// } - } - - ColumnLayout { - id: integratedAddressRow - - LineEditMulti { - id: integratedAddressLine - inputLabelText: qsTr("Integrated address") + translationManager.emptyString - placeholderText: qsTr("Generate payment ID for integrated address") + translationManager.emptyString - readOnly: true - Layout.fillWidth: true - copyButton: true - } - } - - GridLayout { - columns: (isMobile)? 1 : 2 - Layout.fillWidth: true - columnSpacing: 32 - - ColumnLayout { - Layout.fillWidth: true - - RowLayout { - Layout.fillWidth: true - Layout.minimumWidth: 200 - LineEdit { - id: amountLine - placeholderText: qsTr("Amount to receive") + translationManager.emptyString - readOnly: false - inlineIcon: true - labelText: qsTr("Amount") - Layout.fillWidth: true - validator: DoubleValidator { - bottom: 0.0 - top: 18446744.073709551615 - decimals: 12 - notation: DoubleValidator.StandardNotation - locale: "C" ->>>>>>> Receive page development } inputDialog.onRejectedCallback = null; inputDialog.open() } } } - ColumnLayout { + } + + ColumnLayout { + id: amountRow + Label { + id: amountLabel + text: qsTr("Amount") + translationManager.emptyString + width: mainLayout.labelWidth + } + + + LineEdit { + id: amountLine + placeholderText: qsTr("Amount to receive") + translationManager.emptyString + readOnly: false + width: mainLayout.editWidth Layout.fillWidth: true + validator: DoubleValidator { + bottom: 0.0 + top: 18446744.073709551615 + decimals: 12 + notation: DoubleValidator.StandardNotation + locale: "C" + } } } - RowLayout { + ColumnLayout { id: trackingRow - Layout.fillWidth: true visible: !isAndroid && !isIOS -<<<<<<< HEAD Label { id: trackingLabel textFormat: Text.RichText @@ -368,41 +324,17 @@ Rectangle { trackingHowToUseDialog.open() } } -======= ->>>>>>> Receive page development TextEdit { id: trackingLine - anchors.top: trackingRow.top - horizontalAlignment: TextInput.AlignLeft + readOnly: true + width: mainLayout.editWidth Layout.fillWidth: true textFormat: Text.RichText text: "" - readOnly: true selectByMouse: true - color: Style.defaultFontColor - font.family: Style.fontRegular.name - font.pixelSize: 16 * scaleRatio - leftPadding: 12 * scaleRatio - rightPadding: 12 * scaleRatio - topPadding: 8 * scaleRatio - bottomPadding: 8 * scaleRatio - - Rectangle { - color: "transparent" - border.width: 1 - border.color: { - if(trackingLine.activeFocus){ - return Qt.rgba(255, 255, 255, 0.35); - } else { - return Qt.rgba(255, 255, 255, 0.25); - } - } - radius: 4 - anchors.fill: parent - } + color: 'white' } - } MessageDialog { diff --git a/pages/Settings.qml b/pages/Settings.qml index c0a152a8..c56e6e0c 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -574,17 +574,20 @@ Rectangle { TextBlock { Layout.topMargin: 8 + font.pixelSize: 14 Layout.fillWidth: true text: qsTr("GUI version: ") + Version.GUI_VERSION + translationManager.emptyString } TextBlock { id: guiMoneroVersion Layout.fillWidth: true + font.pixelSize: 14 text: qsTr("Embedded Monero version: ") + Version.GUI_MONERO_VERSION + translationManager.emptyString } TextBlock { id: restoreHeightText Layout.fillWidth: true + font.pixelSize: 14 textFormat: Text.RichText property var txt: "" + qsTr("Wallet creation height: ") + (currentWallet ? currentWallet.walletCreationHeight : "") + translationManager.emptyString property var linkTxt: qsTr(" (Click to change)") + translationManager.emptyString @@ -652,14 +655,17 @@ Rectangle { TextBlock { Layout.fillWidth: true + font.pixelSize: 14 text: (!currentWallet) ? "" : qsTr("Wallet log path: ") + currentWallet.walletLogPath + translationManager.emptyString } TextBlock { Layout.fillWidth: true + font.pixelSize: 14 text: qsTr("Wallet Name: ") + walletName + translationManager.emptyString } TextBlock { Layout.fillWidth: true + font.pixelSize: 14 text: (!currentWallet) ? "" : qsTr("Daemon log path: ") + currentWallet.daemonLogPath + translationManager.emptyString } } From bb9e4ee0b9663bb11e2ea52f8f4c26ad47a0a3aa Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 19 Mar 2018 03:56:15 +0100 Subject: [PATCH 086/126] Changed scrollbar width --- components/Scroll.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Scroll.qml b/components/Scroll.qml index 8ef01087..43876a49 100644 --- a/components/Scroll.qml +++ b/components/Scroll.qml @@ -51,7 +51,7 @@ Item { Rectangle { id: scroll - width: 15 + width: 4 height: { var t = (flickable.height * flickable.height) / flickable.contentHeight return t < 20 ? 20 : t @@ -62,7 +62,7 @@ Item { visible: flickable.contentHeight > flickable.height Behavior on opacity { - NumberAnimation { duration: 100; easing.type: Easing.InQuad } + NumberAnimation { duration: 200; easing.type: Easing.InQuad } } MouseArea { From 30bf765b7554f6cabfa6fa7c09497e102e183d37 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 19 Mar 2018 20:26:59 +0100 Subject: [PATCH 087/126] Fixing up after rebase --- main.qml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/main.qml b/main.qml index d8b4b0c2..943d50f8 100644 --- a/main.qml +++ b/main.qml @@ -384,23 +384,6 @@ ApplicationWindow { function onWalletUpdate() { console.log(">>> wallet updated") updateBalance(); - var unlockedBalance = walletManager.displayAmount(currentWallet.unlockedBalance); - var unlockedBalanceFloat = parseFloat(unlockedBalance); - - if(unlockedBalanceFloat === 0){ - // no available funds; hide the 'unlocked balance' label - leftPanel.unlockedBalanceVisible = false - leftPanel.unlockedBalanceLabelVisible = false - } else { - leftPanel.unlockedBalanceVisible = true - leftPanel.unlockedBalanceLabelVisible = true - leftPanel.unlockedBalanceText.text = unlockedBalance - } - - // showing middlePanel unlockedBalance regardless - middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = unlockedBalance; - middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance); - // Update history if new block found since last update if(foundNewBlock) { foundNewBlock = false; From 499419a23cd5553cc6295127b67af5744e79c379 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Mon, 19 Mar 2018 23:30:34 +0100 Subject: [PATCH 088/126] Redesigned txkey/sign pages --- MiddlePanel.qml | 2 +- pages/Mining.qml | 2 + pages/Sign.qml | 16 +- pages/TxKey.qml | 394 +++++++++++++++++++---------------------------- 4 files changed, 175 insertions(+), 239 deletions(-) diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 62d1946c..c9bb874c 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -124,7 +124,7 @@ Rectangle { }, State { name: "TxKey" PropertyChanges { target: root; currentView: txkeyView } - PropertyChanges { target: mainFlickable; contentHeight: minHeight } + PropertyChanges { target: mainFlickable; contentHeight: 1000 * scaleRatio } }, State { name: "SharedRingDB" PropertyChanges { target: root; currentView: sharedringdbView } diff --git a/pages/Mining.qml b/pages/Mining.qml index 11275347..983fc880 100644 --- a/pages/Mining.qml +++ b/pages/Mining.qml @@ -135,6 +135,7 @@ Rectangle { //enabled: !walletManager.isMining() id: startSoloMinerButton width: 110 + small: true text: qsTr("Start mining") + translationManager.emptyString onClicked: { var success = walletManager.startMining(appWindow.currentWallet.address(0, 0), soloMinerThreadsLine.text, persistentSettings.allow_background_mining, persistentSettings.miningIgnoreBattery) @@ -156,6 +157,7 @@ Rectangle { //enabled: walletManager.isMining() id: stopSoloMinerButton width: 110 + small: true text: qsTr("Stop mining") + translationManager.emptyString onClicked: { walletManager.stopMining() diff --git a/pages/Sign.qml b/pages/Sign.qml index 678541b0..b43985a4 100644 --- a/pages/Sign.qml +++ b/pages/Sign.qml @@ -39,7 +39,7 @@ import moneroComponents.WalletManager 1.0 Rectangle { id: mainLayout - color: "#F0EEEE" + color: "transparent" Clipboard { id: clipboard } @@ -105,8 +105,10 @@ Rectangle { Text { text: qsTr("Sign a message or file contents with your address:") + translationManager.emptyString wrapMode: Text.Wrap - font.pixelSize: 14 * scaleRatio Layout.fillWidth: true + font.family: Style.fontRegular + font.pixelSize: 16 * scaleRatio + color: Style.defaultFontColor } } @@ -160,7 +162,7 @@ Rectangle { id: signFileRow anchors.topMargin: 17 anchors.left: parent.left - anchors.right: parent.right + anchors.right: parent.right FileDialog { id: signFileDialog @@ -249,8 +251,10 @@ Rectangle { Text { text: qsTr("Verify a message or file signature from an address:") + translationManager.emptyString wrapMode: Text.Wrap - font.pixelSize: 14 * scaleRatio Layout.fillWidth: true + font.family: Style.fontRegular + font.pixelSize: 16 * scaleRatio + color: Style.defaultFontColor } } @@ -359,14 +363,14 @@ Rectangle { Text { id: verifyAddressLabel - text: "" + + text: "" + qsTr("Signing address") + " ( " + qsTr("Paste in or select from Address book") + " )" + translationManager.emptyString wrapMode: Text.Wrap - font.pixelSize: 14 * scaleRatio + font.pixelSize: 16 * scaleRatio Layout.fillWidth: true textFormat: Text.RichText onLinkActivated: appWindow.showPageRequest("AddressBook") diff --git a/pages/TxKey.qml b/pages/TxKey.qml index 8ed3b8fe..c4372b60 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -36,7 +36,7 @@ import moneroComponents.Clipboard 1.0 Rectangle { - color: "#F0EEEE" + color: "transparent" Clipboard { id: clipboard } @@ -87,260 +87,190 @@ Rectangle { anchors.left: parent.left anchors.top: parent.top anchors.right: parent.right - + anchors.bottom: parent.bottom spacing: 20 - property int labelWidth: 120 - property int editWidth: 400 - property int lineEditFontSize: 12 - Text { - 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 - Layout.fillWidth: true; - } - - RowLayout { - Label { - fontSize: 14 - text: qsTr("Transaction ID") + translationManager.emptyString - width: mainLayout.labelWidth - } - - LineEdit { - id: getProofTxIdLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Paste tx ID") + translationManager.emptyString - readOnly: false - width: mainLayout.editWidth - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (getProofTxIdLine.text.length > 0) { - clipboard.setText(getProofTxIdLine.text) - } - } - } - - } - } - - RowLayout { - Label { - fontSize: 14 - text: qsTr("Address") + translationManager.emptyString - width: mainLayout.labelWidth - } - - LineEdit { - id: getProofAddressLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString; - readOnly: false - width: mainLayout.editWidth - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (getProofAddressLine.text.length > 0) { - clipboard.setText(getProofAddressLine.text) - } - } - } - } - } - - RowLayout { - Label { - fontSize: 14 - text: qsTr("Message") + translationManager.emptyString - width: mainLayout.labelWidth - } - - LineEdit { - id: getProofMessageLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Optional message against which the signature is signed") + translationManager.emptyString; - readOnly: false - width: mainLayout.editWidth - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (getProofMessageLine.text.length > 0) { - clipboard.setText(getProofMessageLine.text) - } - } - } - } - } - - StandardButton { + // solo + ColumnLayout { + id: soloBox anchors.left: parent.left - anchors.topMargin: 17 - width: 60 - text: qsTr("Generate") + translationManager.emptyString - enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) - onClicked: { - console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); - root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) - } - } + anchors.right: parent.right + anchors.top: parent.top + spacing: 20 - // underline - Rectangle { - height: 1 - color: "#DBDBDB" - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - anchors.bottomMargin: 3 - - } - - 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.\n" + - "For the case with Spend Proof, you don't need to specify the recipient address.") + translationManager.emptyString - wrapMode: Text.Wrap - Layout.fillWidth: true; - } - - RowLayout { Label { - fontSize: 14 - text: qsTr("Transaction ID") + translationManager.emptyString - width: mainLayout.labelWidth + id: soloTitleLabel + fontSize: 24 + text: qsTr("Prove Transaction") + translationManager.emptyString } - LineEdit { - id: checkProofTxIdLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Paste tx ID") + translationManager.emptyString - readOnly: false - width: mainLayout.editWidth + Text { + 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 Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (checkProofTxIdLine.text.length > 0) { - clipboard.setText(checkProofTxIdLine.text) - } - } - } - - } - } - - RowLayout { - Label { - fontSize: 14 - text: qsTr("Address") + translationManager.emptyString - width: mainLayout.labelWidth + font.family: Style.fontRegular + font.pixelSize: 14 * scaleRatio + color: Style.defaultFontColor } - LineEdit { - id: checkProofAddressLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString; - readOnly: false - width: mainLayout.editWidth - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (checkProofAddressLine.text.length > 0) { - clipboard.setText(checkProofAddressLine.text) - } - } + RowLayout { + LineEdit { + labelText: qsTr("Transaction ID") + translationManager.emptyString + id: getProofTxIdLine + fontSize: 16 * scaleRatio + placeholderText: qsTr("Paste tx ID") + translationManager.emptyString + readOnly: false + Layout.fillWidth: true + copyButton: true } } - } - RowLayout { - Label { - fontSize: 14 - text: qsTr("Message") + translationManager.emptyString - width: mainLayout.labelWidth - } - - LineEdit { - id: checkProofMessageLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Optional message against which the signature is signed") + translationManager.emptyString; - readOnly: false - width: mainLayout.editWidth - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (checkProofMessageLine.text.length > 0) { - clipboard.setText(checkProofMessageLine.text) - } - } + RowLayout { + LineEdit { + id: getProofAddressLine + labelText: qsTr("Address") + translationManager.emptyString + fontSize: 16 * scaleRatio + placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString; + readOnly: false + Layout.fillWidth: true + copyButton: true } } - } - RowLayout { - Label { - fontSize: 14 - text: qsTr("Signature") + translationManager.emptyString - width: mainLayout.labelWidth - } - - - LineEdit { - id: checkProofSignatureLine - fontSize: mainLayout.lineEditFontSize - placeholderText: qsTr("Paste tx proof") + translationManager.emptyString; - readOnly: false - - width: mainLayout.editWidth - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (checkProofSignatureLine.text.length > 0) { - clipboard.setText(checkProofSignatureLine.text) - } - } + RowLayout { + LineEdit { + id: getProofMessageLine + fontSize: 16 * scaleRatio + labelText: qsTr("Message") + translationManager.emptyString + placeholderText: qsTr("Optional message against which the signature is signed") + translationManager.emptyString; + readOnly: false + width: mainLayout.editWidth + Layout.fillWidth: true + copyButton: true } } - } - StandardButton { - anchors.left: parent.left - anchors.topMargin: 17 - width: 60 - text: qsTr("Check") + translationManager.emptyString - enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) - onClicked: { - 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) + StandardButton { + anchors.left: parent.left + anchors.topMargin: 17 + width: 60 + text: qsTr("Generate") + translationManager.emptyString + enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) + onClicked: { + console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); + root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) + } } - } - // underline - Rectangle { - height: 1 - color: "#DBDBDB" - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - anchors.bottomMargin: 3 + // underline + Rectangle { + height: 1 + color: "#404040" + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + anchors.bottomMargin: 3 - } + } - Text { - text: qsTr("If a payment had several transactions then each must be checked and the results combined.") + translationManager.emptyString - wrapMode: Text.Wrap - Layout.fillWidth: true; + Label { + id: soloTitleLabel2 + fontSize: 24 + text: qsTr("Check Transaction") + translationManager.emptyString + } + + 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.\n" + + "For the case with Spend Proof, you don't need to specify the recipient address.") + translationManager.emptyString + wrapMode: Text.Wrap + Layout.fillWidth: true + font.family: Style.fontRegular + font.pixelSize: 14 * scaleRatio + color: Style.defaultFontColor + } + + RowLayout { + LineEdit { + id: checkProofTxIdLine + labelText: qsTr("Transaction ID") + translationManager.emptyString + fontSize: 16 * scaleRatio + placeholderText: qsTr("Paste tx ID") + translationManager.emptyString + readOnly: false + width: mainLayout.editWidth + Layout.fillWidth: true + copyButton: true + } + } + + RowLayout { + LineEdit { + id: checkProofAddressLine + labelText: qsTr("Address") + translationManager.emptyString + fontSize: 16 * scaleRatio + placeholderText: qsTr("Recipient's wallet address") + translationManager.emptyString; + readOnly: false + width: mainLayout.editWidth + Layout.fillWidth: true + copyButton: true + } + } + + RowLayout { + LineEdit { + id: checkProofMessageLine + fontSize: 16 * scaleRatio + labelText: qsTr("Message") + translationManager.emptyString + placeholderText: qsTr("Optional message against which the signature is signed") + translationManager.emptyString; + readOnly: false + width: mainLayout.editWidth + Layout.fillWidth: true + copyButton: true + } + } + + RowLayout { + LineEdit { + id: checkProofSignatureLine + fontSize: 16 * scaleRatio + labelText: qsTr("Signature") + translationManager.emptyString + placeholderText: qsTr("Paste tx proof") + translationManager.emptyString; + readOnly: false + width: mainLayout.editWidth + Layout.fillWidth: true + copyButton: true + } + } + + StandardButton { + anchors.left: parent.left + anchors.topMargin: 17 + width: 60 + text: qsTr("Check") + translationManager.emptyString + enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) + onClicked: { + 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) + } + } + + // underline + Rectangle { + height: 1 + color: "#404040" + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + anchors.bottomMargin: 3 + + } + + Text { + text: qsTr("If a payment had several transactions then each must be checked and the results combined.") + translationManager.emptyString + wrapMode: Text.Wrap + Layout.fillWidth: true + font.family: Style.fontRegular + font.pixelSize: 14 * scaleRatio + color: Style.defaultFontColor + } } } From bbc16e36dd2759076dadc38c229f4485bf12ec98 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 20 Mar 2018 00:51:54 +0100 Subject: [PATCH 089/126] Fixes the progressbars alignment --- LeftPanel.qml | 2 -- 1 file changed, 2 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index d2eb3df0..27ac3e5a 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -596,8 +596,6 @@ Rectangle { anchors.bottom: parent.bottom syncType: qsTr("Daemon") visible: networkStatus.connected - anchors.leftMargin: 4 * scaleRatio - anchors.rightMargin: 4 * scaleRatio height: 62 * scaleRatio } } // menuRect From 69b4d56fddb2728553f71b401fd050caada1d5b9 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 20 Mar 2018 00:52:52 +0100 Subject: [PATCH 090/126] Small style changes --- MiddlePanel.qml | 2 +- components/SubaddressTable.qml | 2 +- wizard/WizardDaemonSettings.qml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/MiddlePanel.qml b/MiddlePanel.qml index c9bb874c..f5a4d285 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -124,7 +124,7 @@ Rectangle { }, State { name: "TxKey" PropertyChanges { target: root; currentView: txkeyView } - PropertyChanges { target: mainFlickable; contentHeight: 1000 * scaleRatio } + PropertyChanges { target: mainFlickable; contentHeight: 1200 * scaleRatio } }, State { name: "SharedRingDB" PropertyChanges { target: root; currentView: sharedringdbView } diff --git a/components/SubaddressTable.qml b/components/SubaddressTable.qml index a52ed1fe..027a57ad 100644 --- a/components/SubaddressTable.qml +++ b/components/SubaddressTable.qml @@ -42,7 +42,7 @@ ListView { delegate: Rectangle { id: delegate height: 74 - color: 'transparent'; + color: 'black'; anchors.topMargin: 0 width: listView.width diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index f7142468..bec134df 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -175,6 +175,7 @@ ColumnLayout { Layout.fillWidth: true Layout.topMargin: 20 * scaleRatio fontSize: 14 * scaleRatio + color: 'black' text: qsTr("Bootstrap node (leave blank if not wanted)") + translationManager.emptyString } RemoteNodeEdit { From 3ba4224b69b5153d6d196ad1859ff63a26c399c0 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 20 Mar 2018 00:58:49 +0100 Subject: [PATCH 091/126] Redesigned StandardDialog --- components/StandardDialog.qml | 50 ++++++++++++++++++++++++++++------- main.qml | 13 ++++----- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/components/StandardDialog.qml b/components/StandardDialog.qml index 56ce06e2..44c7c784 100644 --- a/components/StandardDialog.qml +++ b/components/StandardDialog.qml @@ -27,7 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 -import QtQuick.Controls 1.4 +import QtQuick.Controls 2.0 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.4 @@ -76,7 +76,7 @@ Rectangle { // Center if(!isMobile) { root.x = parent.width/2 - root.width/2 - root.y = screenHeight/2 - root.height/2 + root.y = 100 } show() root.z = 11 @@ -89,13 +89,13 @@ Rectangle { } // TODO: implement without hardcoding sizes - width: isMobile ? screenWidth : 480 - height: isMobile ? screenHeight : 280 + width: isMobile ? screenWidth : 520 + height: isMobile ? screenHeight : 380 ColumnLayout { id: mainLayout spacing: 10 - anchors { fill: parent; margins: 35 } + anchors { fill: parent; margins: 15 } RowLayout { id: column @@ -117,16 +117,14 @@ Rectangle { id : dialogContent Layout.fillWidth: true Layout.fillHeight: true - font.family: "Arial" + renderType: Text.QtRendering + font.family: Style.fontLight textFormat: TextEdit.AutoText readOnly: true font.pixelSize: 14 * scaleRatio selectByMouse: false wrapMode: TextEdit.Wrap - textColor: Style.defaultFontColor - style: TextAreaStyle { - backgroundColor: "black" - } + color: Style.defaultFontColor MouseArea { anchors.fill: parent @@ -172,6 +170,38 @@ Rectangle { } } + // window borders + Rectangle{ + width: 1 + color: Style.grey + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + } + + Rectangle{ + width: 1 + color: Style.grey + anchors.right: parent.right + anchors.top: parent.top + anchors.bottom: parent.bottom + } + + Rectangle{ + height: 1 + color: Style.grey + anchors.left: parent.left + anchors.top: parent.top + anchors.right: parent.right + } + + Rectangle{ + height: 1 + color: Style.grey + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.right: parent.right + } } diff --git a/main.qml b/main.qml index 943d50f8..b380a99a 100644 --- a/main.qml +++ b/main.qml @@ -588,11 +588,7 @@ ApplicationWindow { + ", fee: " + walletManager.displayAmount(transaction.fee)); // here we show confirmation popup; - - transactionConfirmationPopup.title = qsTr("Confirmation") + translationManager.emptyString - transactionConfirmationPopup.text = qsTr("Please confirm transaction:\n"); - for (var i = 0; i < transaction.subaddrIndices.length; ++i) - transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i] + transactionConfirmationPopup.title = qsTr("Please confirm transaction:\n") + translationManager.emptyString; transactionConfirmationPopup.text += (address === "" ? "" : (qsTr("\n\nAddress: ") + address)) + (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId)) @@ -601,7 +597,12 @@ ApplicationWindow { + qsTr("\n\nRingsize: ") + (mixinCount + 1) + qsTr("\n\Number of transactions: ") + transaction.txCount + (transactionDescription === "" ? "" : (qsTr("\n\nDescription: ") + transactionDescription)) - + translationManager.emptyString + + for (var i = 0; i < transaction.subaddrIndices.length; ++i){ + transactionConfirmationPopup.text += qsTr("\nSpending address index: ") + transaction.subaddrIndices[i]; + } + + transactionConfirmationPopup.text += translationManager.emptyString; transactionConfirmationPopup.icon = StandardIcon.Question transactionConfirmationPopup.open() } From 09935ba4b07e222fcc224110884976876e255baa Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 20 Mar 2018 18:55:53 +0100 Subject: [PATCH 092/126] Fixes duplicate id --- components/ProgressBar.qml | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml index 4b415051..f9bb315f 100644 --- a/components/ProgressBar.qml +++ b/components/ProgressBar.qml @@ -65,8 +65,8 @@ Rectangle { font.pixelSize: 13 * scaleRatio font.bold: true color: "white" - text: qsTr("Synchronizing blocks") - height:18 * scaleRatio + text: qsTr("Synchronizing %1").arg(syncType) + height: 18 * scaleRatio } Text { @@ -98,7 +98,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.left: parent.left height: bar.height - property int maxWidth: parent.width - 4 * scaleRatio + property int maxWidth: bar.width - 4 * scaleRatio width: (maxWidth * fillLevel) / 100 radius: 8 // could change color based on progressbar status; if(item.fillLevel < 99 ) @@ -110,16 +110,6 @@ Rectangle { anchors.bottom: parent.bottom anchors.left: parent.left anchors.leftMargin: 8 * scaleRatio - - Text { - id:progressText - anchors.bottom: parent.bottom - font.family: "Arial" - font.pixelSize: 12 * scaleRatio - color: "#000" - text: qsTr("Synchronizing %1").arg(syncType) - height:18 * scaleRatio - } } } From 70983136bccff61d7d72e0dd0e85cc27178f76d9 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 01:35:34 +0100 Subject: [PATCH 093/126] Generate proof from history view and made javascript file with tx related functions --- components/HistoryTable.qml | 72 ++++++++++++++++++++++++++++++------- js/TxUtils.js | 57 +++++++++++++++++++++++++++++ pages/History.qml | 6 ++-- pages/TxKey.qml | 47 +++--------------------- qml.qrc | 1 + 5 files changed, 124 insertions(+), 59 deletions(-) create mode 100644 js/TxUtils.js diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index c083ef3c..b7a32d41 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -30,6 +30,7 @@ import QtQuick 2.0 import moneroComponents.Clipboard 1.0 import moneroComponents.AddressBookModel 1.0 import "../components" as MoneroComponents +import "../js/TxUtils.js" as TxUtils import "." 1.0 ListView { @@ -196,19 +197,17 @@ ListView { font.pixelSize: 18 * scaleRatio font.bold: true text: { - // hack, removes trailing zeros - var amount = (displayAmount * 1); + var amount = (displayAmount * 1); // * 1 removes trailing zeros // sometimes, displayAmount is 0 - no idea why. // in that case, we try to get the amount from // the `destinations` string. if(amount === 0){ - amount = destinations.split(" ")[0].split(":")[0]; + amount = TxUtils.destinationsToAmount(destinations); amount = (amount *1); } - // sometimes this destinations string also shows 0, - // at which point we run out of options. + // sometimes this destinations string also shows 0 at which point we run out of options. return amount + " XMR"; } color: isOut ? "white" : "#2eb358" @@ -251,18 +250,15 @@ ListView { font.pixelSize: 16 * scaleRatio text: { if(isOut){ - var _address = destinations.split(" ")[1]; - if(_address === undefined) return "" - - if(_address){ - address = _address; - var address_truncated = address.substring(0, 6) + "..." + address.substring(address.length-6); - return "To " + address_truncated; + address = TxUtils.destinationsToAddress(destinations); + if(address){ + var truncated = TxUtils.addressTruncate(address); + return "To " + truncated; } else { return "Unknown recipient"; } } - return "" + return ""; } MouseArea{ @@ -414,6 +410,56 @@ ListView { } } + Rectangle { + id: proofButton + visible: isOut + color: "#404040" + height: 24 * scaleRatio + width: 24 * scaleRatio + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.bottomMargin: 36 + radius: 20 * scaleRatio + + MouseArea { + id: proofButtonMouseArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + var address = TxUtils.destinationsToAddress(destinations); + if(address === undefined){ + console.log('getProof: Error fetching address') + return; + } + + var checked = (TxUtils.checkTxID(hash) && TxUtils.checkAddress(address, appWindow.persistentSettings.testnet)); + if(!checked){ + console.log('getProof: Error checking TxId and/or address'); + } + + console.log("getProof: Generate clicked: txid " + hash + ", address " + address); + root.getProofClicked(hash, address, ''); + } + + onEntered: { + proofButton.color = "#656565"; + } + + onExited: { + proofButton.color = "#404040"; + } + } + + Text { + color: Style.defaultFontColor + text: "P" + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: 14 * scaleRatio + } + } + Rectangle { id: detailsButton color: "#404040" diff --git a/js/TxUtils.js b/js/TxUtils.js new file mode 100644 index 00000000..4a4b01c4 --- /dev/null +++ b/js/TxUtils.js @@ -0,0 +1,57 @@ +function destinationsToAmount(destinations){ + // Gets amount from destinations line + // input: "20.000000000000: 9tLGyK277MnYrDc7Vzi6TB1pJvstFoviziFwsqQNFbwA9rvg5RxYVYjEezFKDjvDHgAzTELJhJHVx6JAaWZKeVqSUZkXeKk" + // returns: 20.000000000000 + return destinations.split(" ")[0].split(":")[0]; +} + +function destinationsToAddress(destinations){ + var address = destinations.split(" ")[1]; + if(address === undefined) return "" + return address; +} + +function addressTruncate(address){ + return address.substring(0, 6) + "..." + address.substring(address.length-6); +} + +function check256(str, length) { + if (str.length != length) + return false; + for (var i = 0; i < length; ++i) { + if (str[i] >= '0' && str[i] <= '9') + continue; + if (str[i] >= 'a' && str[i] <= 'z') + continue; + if (str[i] >= 'A' && str[i] <= 'Z') + continue; + return false; + } + return true; +} + +function checkAddress(address, testnet) { + return walletManager.addressValid(address, testnet) +} + +function checkTxID(txid) { + return check256(txid, 64) +} + +function checkSignature(signature) { + if (signature.indexOf("OutProofV") === 0) { + if ((signature.length - 10) % 132 != 0) + return false; + return check256(signature, signature.length); + } else if (signature.indexOf("InProofV") === 0) { + if ((signature.length - 9) % 132 != 0) + return false; + return check256(signature, signature.length); + } else if (signature.indexOf("SpendProofV") === 0) { + if ((signature.length - 12) % 88 != 0) + return false; + return check256(signature, signature.length); + } + return false; +} + diff --git a/pages/History.qml b/pages/History.qml index 3a2c79ad..079373bc 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -38,7 +38,7 @@ import moneroComponents.TransactionHistoryModel 1.0 import "../components" Rectangle { - id: root + id: mainLayout property var model property int tableHeight: !isMobile ? table.contentHeight : tableMobile.contentHeight @@ -321,7 +321,7 @@ Rectangle { id: table visible: !isMobile onContentYChanged: flickableScroll.flickableContentYChanged() - model: !isMobile ? root.model : null + model: !isMobile ? mainLayout.model : null addressBookModel: null Layout.fillWidth: true @@ -332,7 +332,7 @@ Rectangle { id: tableMobile visible: isMobile onContentYChanged: flickableScroll.flickableContentYChanged() - model: isMobile ? root.model : null + model: isMobile ? mainLayout.model : null addressBookModel: null Layout.fillWidth: true diff --git a/pages/TxKey.qml b/pages/TxKey.qml index c4372b60..a9f571ba 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -34,52 +34,14 @@ import QtQuick.Layouts 1.1 import "../components" import moneroComponents.Clipboard 1.0 +import "../js/TxUtils.js" as TxUtils + Rectangle { color: "transparent" Clipboard { id: clipboard } - function checkAddress(address, nettype) { - return walletManager.addressValid(address, nettype) - } - - function check256(str, length) { - if (str.length != length) - return false; - for (var i = 0; i < length; ++i) { - if (str[i] >= '0' && str[i] <= '9') - continue; - if (str[i] >= 'a' && str[i] <= 'z') - continue; - if (str[i] >= 'A' && str[i] <= 'Z') - continue; - return false; - } - return true; - } - - function checkTxID(txid) { - return check256(txid, 64) - } - - function checkSignature(signature) { - if (signature.indexOf("OutProofV") === 0) { - if ((signature.length - 10) % 132 != 0) - return false; - return check256(signature, signature.length); - } else if (signature.indexOf("InProofV") === 0) { - if ((signature.length - 9) % 132 != 0) - return false; - return check256(signature, signature.length); - } else if (signature.indexOf("SpendProofV") === 0) { - if ((signature.length - 12) % 88 != 0) - return false; - return check256(signature, signature.length); - } - return false; - } - /* main layout */ ColumnLayout { id: mainLayout @@ -156,7 +118,7 @@ Rectangle { anchors.topMargin: 17 width: 60 text: qsTr("Generate") + translationManager.emptyString - enabled: checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) + enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) onClicked: { console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) @@ -246,7 +208,7 @@ Rectangle { anchors.topMargin: 17 width: 60 text: qsTr("Check") + translationManager.emptyString - enabled: checkTxID(checkProofTxIdLine.text) && checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) + enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) onClicked: { 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) @@ -278,5 +240,4 @@ Rectangle { console.log("TxKey page loaded"); } - } diff --git a/qml.qrc b/qml.qrc index 11d2d448..ad4f1f86 100644 --- a/qml.qrc +++ b/qml.qrc @@ -202,5 +202,6 @@ images/historyBorderRadius.png components/HistoryTableInnerColumn.qml components/CheckBox2.qml + js/TxUtils.js From 57c0477fc6efeb6ce618ed35d27dd29820c29ee5 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 02:12:02 +0100 Subject: [PATCH 094/126] Design polish work --- components/HistoryTable.qml | 2 +- components/LineEditMulti.qml | 2 +- images/historyBorderRadius.png | Bin 203 -> 14768 bytes pages/History.qml | 2 +- pages/Receive.qml | 4 +--- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index b7a32d41..e5abbc65 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -94,7 +94,7 @@ ListView { property bool collapsed: index ? false : true height: collapsed ? 180 * scaleRatio : 70 * scaleRatio width: listView.width - color: "#CC000000" + color: "transparent" function collapse(){ delegate.height = 180 * scaleRatio; diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 02f281f3..dd5199d4 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -46,7 +46,7 @@ ColumnLayout { property bool wrapAnywhere: true property bool showingHeader: true property bool showBorder: true - property int fontSize: 18 * scaleRatio + property int fontSize: 16 * scaleRatio signal labelButtonClicked(); signal inputLabelLinkActivated(); diff --git a/images/historyBorderRadius.png b/images/historyBorderRadius.png index c18a6b9f66e73b7f8bf287adcbe9d74d7d65f159..ee86e191128341871d7a56b843838f57f43e03d8 100755 GIT binary patch literal 14768 zcmeI3PmB{)9LFC*R#^c_2oVW}Nzo``JAb;}-HvS$wqQ50uvwO{dr)^e^SV3G&Wtlt z+FcV^{v9-W@dB9D=)nUfdcm79pv1$PpeGNKplj5K97Ka5U@-N~Ot<~D+w#D0e3R_< z*Z02P-+S|UzxO(qd3|Wt3oEGA$v?5`7V>4el^JsodU%cZ zw*~c9gp&QB2wa?ClI9*GI z_QkS7)*8T*dS=?jd!~1dsM813xE9))>P}Q-lAwrPg{u?`h9g&!AwRE7Vy~GGalXVo zkPL0}2INMwL)?IAV=fly4XdIka((fL80(Kpv1d6+5M#U$=S3kbh_WcilEBrjP^z0m z30up{!|9#1;mEgSXwr2pndi&pa-g^US1_H`^0jUA!LR}_mEBLd&fq^Wg}Rk92I)HIdH z1zg02>kyyV)@MzcuIWsg9fquTcO00kNj6&_yX}07#kNB`?v8^5K@DkJr!z8TVSX4p zX319Zj)UY@HnqEZSI;*Vrzw-y({b*&qIa-)J%PK z0zz(Jz^^Lq>3zDPnPq2lf^W4n*1M4nrxh2cNImw4g=kn3M@T)!NImv$A%P%(B!RLe zN7mHz{8YOfk}OFu2T-==Ap1vCT;;B^KrP6lsdC=5i;A1li^>G%En_0VHyVMmURCmd zSukxfEu4xb_;$^}%Q;Jwqo zpf@i>(AvB{3l+O~JrmxcCX-qq^HTgZ5EJ~Ow#LYTe$-pjLdnwXuj5sv zNbbw`w05*Lj&(AEj+!x8D)4jeuVm0l9u~-R3SWOvX

|M!3&GnBk%#f&zvM(xAo+7Zni{FkFxZHDIYL5&$MDk3OgxF8K`%y3Z=K>@=BX;5Q^i;4&e7%oVI8Z%r}L{PwRK^oMU z;i4jf0)`9HpvDXr6%iCLT#yDeX1J(`pn&0mG^jDdMMVS!3>Tz9jTtT~A}CtUaeMFc&`^$t2xW-xLK`kUE275n|!@MG>_FZ$Df&<<9NP$ z#q+&M{!Mtfg3hCZ-~V{-@ZrCXJ^08k>%42jh7I{IdM=R3kn~5-Xhdn{#>Y?1oj?En zmk+GH`RU>6p;T8_*WOb%e!g<)^dCQbzGZHvYyO+($!n6H<@m)9R?Y~kPyDpees67N z|JAW0k1NY>oOfr=KDB@S>XWNxLT9+Y&tBX8@@vahAGvt>j7Ni9n8@z zJ%e}^o3$CXT5w>LNikrtu`#fOEM}VDJpP}`Ift2R0d&9I0BGt7*aA4K>YkZJM0zv3 zr<8^q9st~k=p90MOegBB>FT}b7~^a1mlc2tz=epkghqH&)i7NM;aNf>JTY^zDTl3y l^h@B{%sxwClTsS~!7nv8Ls6WN9-ROH002ovPDHLkV1g*0Q33z} diff --git a/pages/History.qml b/pages/History.qml index 079373bc..ad4bbb60 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -276,7 +276,7 @@ Rectangle { Layout.fillWidth: true height: 10 - color: "#CC000000" + color: "transparent" Rectangle { anchors.top: parent.top diff --git a/pages/Receive.qml b/pages/Receive.qml index 75504387..ee028395 100644 --- a/pages/Receive.qml +++ b/pages/Receive.qml @@ -142,7 +142,6 @@ Rectangle { Clipboard { id: clipboard } - /* main layout */ ColumnLayout { id: mainLayout @@ -159,7 +158,6 @@ Rectangle { property int lineEditFontSize: 12 * scaleRatio property int qrCodeSize: 240 * scaleRatio - ColumnLayout { id: addressRow spacing: 0 @@ -175,7 +173,7 @@ Rectangle { Layout.topMargin: 10 height: 10 - color: "#CC000000" + color: "transparent" Rectangle { anchors.top: parent.top From 5213daad77940ba6162c8c772e5da4213ad6f962 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 02:39:09 +0100 Subject: [PATCH 095/126] Dynamic subaddr table height, dont show history table when there is none --- components/SubaddressTable.qml | 6 +++--- pages/History.qml | 11 +++++++++++ pages/Receive.qml | 4 +++- pages/Transfer.qml | 2 +- pages/TxKey.qml | 20 ++++++++++---------- 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/components/SubaddressTable.qml b/components/SubaddressTable.qml index 027a57ad..12f06d1c 100644 --- a/components/SubaddressTable.qml +++ b/components/SubaddressTable.qml @@ -28,6 +28,7 @@ import QtQuick 2.0 import moneroComponents.Clipboard 1.0 +import "../components" import "." 1.0 ListView { @@ -42,7 +43,7 @@ ListView { delegate: Rectangle { id: delegate height: 74 - color: 'black'; + color: 'transparent'; anchors.topMargin: 0 width: listView.width @@ -57,9 +58,8 @@ ListView { anchors.right: parent.right anchors.leftMargin: 5 anchors.topMargin: 12 - anchors.rightMargin: 40 + anchors.rightMargin: 44 anchors.bottomMargin: 0 - onTextChanged: cursorPosition = 0 text: address showingHeader: false diff --git a/pages/History.qml b/pages/History.qml index ad4bbb60..a1f3142a 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -259,6 +259,16 @@ Rectangle { } } + GridLayout { + Layout.topMargin: 20 + visible: table.count === 0 + + Label { + fontSize: 16 * scaleRatio + text: qsTr("No history yet...") + translationManager.emptyString + } + } + GridLayout { id: tableHeader columns: 1 @@ -274,6 +284,7 @@ Rectangle { Rectangle { id: header Layout.fillWidth: true + visible: table.count > 0 height: 10 color: "transparent" diff --git a/pages/Receive.qml b/pages/Receive.qml index ee028395..774f92c6 100644 --- a/pages/Receive.qml +++ b/pages/Receive.qml @@ -171,6 +171,7 @@ Rectangle { id: header Layout.fillWidth: true Layout.topMargin: 10 + visible: table.count > 0 height: 10 color: "transparent" @@ -210,8 +211,9 @@ Rectangle { Rectangle { id: tableRect + property int table_max_height: 240 Layout.fillWidth: true - Layout.preferredHeight: 240 + Layout.preferredHeight: table.contentHeight < table_max_height ? table.contentHeight : table_max_height color: "transparent" Scroll { diff --git a/pages/Transfer.qml b/pages/Transfer.qml index b5fbfbea..a52a8f92 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -202,7 +202,7 @@ Rectangle { id: addressLineRow Layout.fillWidth: true - LineEditMulti{ + LineEditMulti { id: addressLine spacing: 0 inputLabelText: qsTr("\ diff --git a/pages/TxKey.qml b/pages/TxKey.qml index a9f571ba..18a65abf 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -45,12 +45,12 @@ Rectangle { /* main layout */ ColumnLayout { id: mainLayout - anchors.margins: 40 + anchors.margins: 40 * scaleRatio anchors.left: parent.left anchors.top: parent.top anchors.right: parent.right anchors.bottom: parent.bottom - spacing: 20 + spacing: 20 * scaleRatio // solo ColumnLayout { @@ -58,11 +58,11 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - spacing: 20 + spacing: 20 * scaleRatio Label { id: soloTitleLabel - fontSize: 24 + fontSize: 24 * scaleRatio text: qsTr("Prove Transaction") + translationManager.emptyString } @@ -115,8 +115,8 @@ Rectangle { StandardButton { anchors.left: parent.left - anchors.topMargin: 17 - width: 60 + anchors.topMargin: 17 * scaleRatio + width: 60 * scaleRatio text: qsTr("Generate") + translationManager.emptyString enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) onClicked: { @@ -131,13 +131,13 @@ Rectangle { color: "#404040" Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter - anchors.bottomMargin: 3 + anchors.bottomMargin: 3 * scaleRatio } Label { id: soloTitleLabel2 - fontSize: 24 + fontSize: 24 * scaleRatio text: qsTr("Check Transaction") + translationManager.emptyString } @@ -205,7 +205,7 @@ Rectangle { StandardButton { anchors.left: parent.left - anchors.topMargin: 17 + anchors.topMargin: 17 * scaleRatio width: 60 text: qsTr("Check") + translationManager.emptyString enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) @@ -221,7 +221,7 @@ Rectangle { color: "#404040" Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter - anchors.bottomMargin: 3 + anchors.bottomMargin: 3 * scaleRatio } From 8f368b9b3ba2f1dd00a62a44206fdfd5e3ef4d77 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 02:41:44 +0100 Subject: [PATCH 096/126] Remove seed from WizardFinished for now, as it yields an undefined error --- wizard/WizardFinish.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wizard/WizardFinish.qml b/wizard/WizardFinish.qml index 0ab50706..b0b39017 100644 --- a/wizard/WizardFinish.qml +++ b/wizard/WizardFinish.qml @@ -58,7 +58,9 @@ ColumnLayout { return "" + trStart + qsTr("Language") + trMiddle + wizard.settings["language"] + trEnd + trStart + qsTr("Wallet name") + trMiddle + wizard.settings["account_name"] + trEnd - + trStart + qsTr("Backup seed") + trMiddle + wizard.settings["wallet"].seed + trEnd + // TODO: wizard.settings['wallet'].seed doesnt work anymore; yields undefined. +// + trStart + qsTr("Backup seed") + trMiddle + wizard.settings["wallet"].seed + trEnd + + trStart + qsTr("Backup seed") + trMiddle + '****' + trEnd + trStart + qsTr("Wallet path") + trMiddle + wizard.settings["wallet_path"] + trEnd // + trStart + qsTr("Auto donations") + trMiddle + autoDonationText + trEnd // + (autoDonationEnabled From f544d9ac78bcb032524c1c182cc4d4dc845d1f88 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 03:07:38 +0100 Subject: [PATCH 097/126] Exit application when wallet variable is empty --- main.qml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/main.qml b/main.qml index b380a99a..9cb3bc34 100644 --- a/main.qml +++ b/main.qml @@ -266,6 +266,29 @@ ApplicationWindow { function connectWallet(wallet) { currentWallet = wallet + + // TODO: + // When the wallet variable is undefined, it yields a zero balance. + // This can scare users, restart the GUI (as a quick fix). + // + // To reproduce, follow these steps: + // 1) Open the GUI, load up a wallet that has a balance + // 2) Settings -> close wallet + // 3) Create a new wallet + // 4) Settings -> close wallet + // 5) Open the wallet from step 1 + + if(!wallet || wallet === undefined || wallet.path === undefined){ + informationPopup.title = qsTr("Error") + translationManager.emptyString; + informationPopup.text = qsTr("Couldn't open wallet: ") + 'please restart GUI.'; + informationPopup.icon = StandardIcon.Critical + informationPopup.open() + informationPopup.onCloseCallback = function() { + appWindow.close(); + } + return; + } + walletName = usefulName(wallet.path) updateSyncing(false) From 7c0f704fbd9db39c0ae88349212cf19389b4f07e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 03:42:16 +0100 Subject: [PATCH 098/126] Clip subaddr table items --- components/SubaddressTable.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/SubaddressTable.qml b/components/SubaddressTable.qml index 12f06d1c..c35ef96e 100644 --- a/components/SubaddressTable.qml +++ b/components/SubaddressTable.qml @@ -46,11 +46,12 @@ ListView { color: 'transparent'; anchors.topMargin: 0 width: listView.width + clip: true LineEditMulti { id: addressLine - //borderDisabled: true - fontSize: 12 + + fontSize: 14 readOnly: true width: parent.width anchors.top: parent.top @@ -58,7 +59,7 @@ ListView { anchors.right: parent.right anchors.leftMargin: 5 anchors.topMargin: 12 - anchors.rightMargin: 44 + anchors.rightMargin: 54 anchors.bottomMargin: 0 text: address From 6e794e3c50a5063d79cfe47a69d36d8005568921 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 23:56:53 +0100 Subject: [PATCH 099/126] Redoing the Sign/Verify page --- MiddlePanel.qml | 2 +- components/InputMulti.qml | 5 + components/LineEditMulti.qml | 2 +- components/SubaddressTable.qml | 1 + pages/Sign.qml | 446 ++++++++++++++------------------- pages/Transfer.qml | 2 +- pages/TxKey.qml | 1 - 7 files changed, 194 insertions(+), 265 deletions(-) diff --git a/MiddlePanel.qml b/MiddlePanel.qml index f5a4d285..680372c0 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -136,7 +136,7 @@ Rectangle { }, State { name: "Sign" PropertyChanges { target: root; currentView: signView } - PropertyChanges { target: mainFlickable; contentHeight: minHeight } + PropertyChanges { target: mainFlickable; contentHeight: 1200 * scaleRatio } }, State { name: "Settings" PropertyChanges { target: root; currentView: settingsView } diff --git a/components/InputMulti.qml b/components/InputMulti.qml index f809ca10..9c74d0c1 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -29,6 +29,7 @@ import QtQuick.Controls 2.2 import QtQuick 2.10 +import "../js/TxUtils.js" as TxUtils import "." 1.0 @@ -37,6 +38,7 @@ TextArea { property bool addressValidation: false property bool wrapAnywhere: true property int fontSize: 18 * scaleRatio + id: textArea font.family: Style.fontRegular font.pixelSize: fontSize @@ -56,6 +58,9 @@ TextArea { if(addressValidation){ // js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }` textArea.text = textArea.text.replace(/[^a-z0-9]/gi,''); + var address_ok = TxUtils.checkAddress(textArea.text, appWindow.persistentSettings.testnet); + if(!address_ok) error = true; + else error = false; TextArea.cursorPosition = textArea.text.length; } } diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index dd5199d4..758755d0 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -35,7 +35,7 @@ ColumnLayout { id: lineditmulti property alias text: multiLine.text property alias placeholderText: placeholderLabel.text - property alias inputLabelText: inputLabel.text + property alias labelText: inputLabel.text property alias error: multiLine.error property alias readOnly: multiLine.readOnly property alias addressValidation: multiLine.addressValidation diff --git a/components/SubaddressTable.qml b/components/SubaddressTable.qml index c35ef96e..88856ad3 100644 --- a/components/SubaddressTable.qml +++ b/components/SubaddressTable.qml @@ -65,6 +65,7 @@ ListView { showingHeader: false showBorder: false + addressValidation: false } IconButton { diff --git a/pages/Sign.qml b/pages/Sign.qml index b43985a4..287846f2 100644 --- a/pages/Sign.qml +++ b/pages/Sign.qml @@ -43,10 +43,6 @@ Rectangle { Clipboard { id: clipboard } - function checkAddress(address, nettype) { - return walletManager.addressValid(address, nettype) - } - MessageDialog { // dynamically change onclose handler property var onCloseCallback @@ -88,302 +84,215 @@ Rectangle { // sign / verify ColumnLayout { - anchors.margins: 17 * scaleRatio + anchors.top: parent.top + anchors.margins: 40 * scaleRatio anchors.left: parent.left anchors.right: parent.right - anchors.top: parent.top - anchors.bottom: parent.bottom - spacing: 20 * scaleRatio // sign ColumnLayout { id: signBox - - RowLayout { - - Text { - text: qsTr("Sign a message or file contents with your address:") + translationManager.emptyString - wrapMode: Text.Wrap - Layout.fillWidth: true - font.family: Style.fontRegular - font.pixelSize: 16 * scaleRatio - color: Style.defaultFontColor - } - } + anchors.left: parent.left + anchors.right: parent.right + spacing: 20 * scaleRatio Label { - id: signMessageLabel - text: qsTr("Either message:") + translationManager.emptyString + id: signTitleLabel + fontSize: 24 * scaleRatio + text: qsTr("Sign") + translationManager.emptyString } - RowLayout { + Text { + text: qsTr("This page lets you sign/verify a message (or file contents) with your address.") + translationManager.emptyString + wrapMode: Text.Wrap + Layout.fillWidth: true + font.family: Style.fontRegular + font.pixelSize: 14 * scaleRatio + color: Style.defaultFontColor + } + + ColumnLayout{ id: signMessageRow - anchors.topMargin: 17 - anchors.left: parent.left - anchors.right: parent.right - LineEdit { - id: signMessageLine - anchors.left: parent.left - anchors.right: signMessageButton.left - placeholderText: qsTr("Message to sign") + translationManager.emptyString; - readOnly: false - onTextChanged: signSignatureLine.text = "" - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (signMessageLine.text.length > 0) { - clipboard.setText(signMessageLine.text) - } - } - } - } - - StandardButton { - id: signMessageButton - anchors.right: parent.right - text: qsTr("Sign") + translationManager.emptyString - enabled: true - onClicked: { - var signature = appWindow.currentWallet.signMessage(signMessageLine.text, false) - signSignatureLine.text = signature - } - } - } - - Label { - id: signMessageFileLabel - text: qsTr("Or file:") + translationManager.emptyString - } - - RowLayout { - id: signFileRow - anchors.topMargin: 17 - anchors.left: parent.left - anchors.right: parent.right - - FileDialog { - id: signFileDialog - title: qsTr("Please choose a file to sign") + translationManager.emptyString; - folder: "file://" - nameFilters: [ "*"] - - onAccepted: { - signFileLine.text = walletManager.urlToLocalPath(signFileDialog.fileUrl) - } - } - - StandardButton { - id: loadFileToSignButton - anchors.rightMargin: 17 * scaleRatio - text: qsTr("Select") + translationManager.emptyString - enabled: true - onClicked: { - signFileDialog.open() - } - } - LineEdit { - id: signFileLine - anchors.left: loadFileToSignButton.right - anchors.right: signFileButton.left - placeholderText: qsTr("Filename with message to sign") + translationManager.emptyString; - readOnly: false + RowLayout { Layout.fillWidth: true - onTextChanged: signSignatureLine.text = "" - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (signFileLine.text.length > 0) { - clipboard.setText(signFileLine.text) - } - } + LineEdit { + id: signMessageLine + Layout.fillWidth: true + placeholderText: qsTr("Message to sign") + translationManager.emptyString; + labelText: qsTr("Message") + translationManager.emptyString; + readOnly: false + onTextChanged: signSignatureLine.text = "" } } - StandardButton { - id: signFileButton - anchors.right: parent.right - text: qsTr("Sign") + translationManager.emptyString - enabled: true - onClicked: { - var signature = appWindow.currentWallet.signMessage(signFileLine.text, true) - signSignatureLine.text = signature + RowLayout{ + Layout.fillWidth: true + Layout.topMargin: 18 + + StandardButton { + id: signMessageButton + text: qsTr("Sign") + translationManager.emptyString + enabled: signMessageLine.text !== '' + small: true + onClicked: { + var signature = appWindow.currentWallet.signMessage(signMessageLine.text, false) + signSignatureLine.text = signature + } } } } + ColumnLayout { + id: signFileRow + + RowLayout { + LineEdit { + id: signFileLine + labelText: "Message from file" + placeholderText: qsTr("Path to file") + translationManager.emptyString; + readOnly: false + Layout.fillWidth: true + onTextChanged: signSignatureLine.text = "" + } + } + + RowLayout { + Layout.fillWidth: true + Layout.topMargin: 18 + + StandardButton { + id: loadFileToSignButton + small: true + text: qsTr("Browse") + translationManager.emptyString + enabled: true + onClicked: { + signFileDialog.open(); + } + } + + StandardButton { + id: signFileButton + small: true + anchors.left: loadFileToSignButton.right + anchors.leftMargin: 20 + text: qsTr("Sign") + translationManager.emptyString + enabled: signFileLine.text !== '' + onClicked: { + var signature = appWindow.currentWallet.signMessage(signFileLine.text, true); + signSignatureLine.text = signature; + } + } + } + + } + ColumnLayout { id: signSignatureRow - anchors.topMargin: 17 * scaleRatio - Label { - id: signSignatureLabel - text: qsTr("Signature") + translationManager.emptyString - } - - LineEdit { - id: signSignatureLine - placeholderText: qsTr("Signature") + translationManager.emptyString; - readOnly: true - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (signSignatureLine.text.length > 0) { - clipboard.setText(signSignatureLine.text) - } - } - } - } - } - } - - - // verify - ColumnLayout { - id: verifyBox - - RowLayout { - Text { - text: qsTr("Verify a message or file signature from an address:") + translationManager.emptyString - wrapMode: Text.Wrap - Layout.fillWidth: true - font.family: Style.fontRegular - font.pixelSize: 16 * scaleRatio - color: Style.defaultFontColor - } - - } - - Label { - id: verifyMessageLabel - text: qsTr("Either message:") + translationManager.emptyString - } - - RowLayout { - id: verifyMessageRow - anchors.topMargin: 17 * scaleRatio - anchors.left: parent.left - anchors.right: parent.right - - LineEdit { - id: verifyMessageLine - anchors.left: parent.left - anchors.right: verifyMessageButton.left - placeholderText: qsTr("Message to verify") + translationManager.emptyString; - readOnly: false - Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (verifyMessageLine.text.length > 0) { - clipboard.setText(verifyMessageLine.text) - } - } - } - } - - StandardButton { - id: verifyMessageButton - anchors.right: parent.right - text: qsTr("Verify") + translationManager.emptyString - enabled: true - onClicked: { - var verified = appWindow.currentWallet.verifySignedMessage(verifyMessageLine.text, verifyAddressLine.text, verifySignatureLine.text, false) - displayVerificationResult(verified) + RowLayout { + LineEdit { + id: signSignatureLine + labelText: qsTr("Signature") + placeholderText: qsTr("Signature") + translationManager.emptyString; + readOnly: true + Layout.fillWidth: true + copyButton: true } } } Label { - id: verifyMessageFileLabel - text: qsTr("Or file:") + translationManager.emptyString + id: verifyTitleLabel + fontSize: 24 * scaleRatio + Layout.topMargin: 40 + text: qsTr("Verify") + translationManager.emptyString } - RowLayout { - id: verifyFileRow - anchors.topMargin: 17 * scaleRatio - anchors.left: parent.left - anchors.right: parent.right + ColumnLayout { + RowLayout { + id: verifyMessageRow - FileDialog { - id: verifyFileDialog - title: qsTr("Please choose a file to verify") + translationManager.emptyString; - folder: "file://" - nameFilters: [ "*"] - - onAccepted: { - verifyFileLine.text = walletManager.urlToLocalPath(verifyFileDialog.fileUrl) + LineEdit { + id: verifyMessageLine + Layout.fillWidth: true + labelText: qsTr("Verify message") + placeholderText: qsTr("Message to verify") + translationManager.emptyString; + readOnly: false } } - StandardButton { - id: loadFileToVerifyButton - anchors.rightMargin: 17 * scaleRatio - text: qsTr("Select") + translationManager.emptyString - enabled: true - onClicked: { - verifyFileDialog.open() - } - } - LineEdit { - id: verifyFileLine - anchors.left: loadFileToVerifyButton.right - anchors.right: verifyFileButton.left - placeholderText: qsTr("Filename with message to verify") + translationManager.emptyString; - readOnly: false + RowLayout{ Layout.fillWidth: true + Layout.topMargin: 18 - IconButton { - imageSource: "../images/copyToClipboard.png" + StandardButton { + id: verifyMessageButton + small: true + text: qsTr("Verify") + translationManager.emptyString + enabled: true onClicked: { - if (verifyFileLine.text.length > 0) { - clipboard.setText(verifyFileLine.text) - } + var verified = appWindow.currentWallet.verifySignedMessage(verifyMessageLine.text, verifyAddressLine.text, verifySignatureLine.text, false) + displayVerificationResult(verified) } } } + } - StandardButton { - id: verifyFileButton - anchors.right: parent.right - text: qsTr("Verify") + translationManager.emptyString - enabled: true - onClicked: { - var verified = appWindow.currentWallet.verifySignedMessage(verifyFileLine.text, verifyAddressLine.text, verifySignatureLine.text, true) - displayVerificationResult(verified) + ColumnLayout { + RowLayout { + LineEdit { + id: verifyFileLine + labelText: qsTr("Verify file") + placeholderText: qsTr("Filename with message to verify") + translationManager.emptyString; + readOnly: false + Layout.fillWidth: true + } + } + + RowLayout{ + Layout.fillWidth: true + Layout.topMargin: 18 + + StandardButton { + id: loadFileToVerifyButton + small: true + text: qsTr("Browse") + translationManager.emptyString + enabled: true + onClicked: { + verifyFileDialog.open() + } + } + + StandardButton { + id: verifyFileButton + small: true + anchors.left: loadFileToVerifyButton.right + anchors.leftMargin: 20 + text: qsTr("Verify") + translationManager.emptyString + enabled: true + onClicked: { + var verified = appWindow.currentWallet.verifySignedMessage(verifyFileLine.text, verifyAddressLine.text, verifySignatureLine.text, true) + displayVerificationResult(verified) + } } } } - Text { - id: verifyAddressLabel - text: "" + - qsTr("Signing address") + - " ( " + - qsTr("Paste in or select from Address book") + - " )" + - translationManager.emptyString - wrapMode: Text.Wrap - font.pixelSize: 16 * scaleRatio - Layout.fillWidth: true - textFormat: Text.RichText - onLinkActivated: appWindow.showPageRequest("AddressBook") - } + ColumnLayout { + RowLayout{ - LineEdit { - id: verifyAddressLine - anchors.left: parent.left - anchors.right: parent.right - anchors.top: verifyAddressLabel.bottom - anchors.topMargin: 5 * scaleRatio - placeholderText: "4..." - // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } + LineEditMulti { + id: verifyAddressLine + Layout.fillWidth: true + labelText: qsTr("Address") + addressValidation: true + anchors.topMargin: 5 * scaleRatio + placeholderText: "4..." + } + } } ColumnLayout { @@ -399,18 +308,33 @@ Rectangle { id: verifySignatureLine placeholderText: qsTr("Signature") + translationManager.emptyString; Layout.fillWidth: true - - IconButton { - imageSource: "../images/copyToClipboard.png" - onClicked: { - if (verifySignatureLine.text.length > 0) { - clipboard.setText(verifySignatureLine.text) - } - } - } + copyButton: true } } } + + + FileDialog { + id: signFileDialog + title: qsTr("Please choose a file to sign") + translationManager.emptyString; + folder: "file://" + nameFilters: [ "*"] + + onAccepted: { + signFileLine.text = walletManager.urlToLocalPath(signFileDialog.fileUrl) + } + } + + FileDialog { + id: verifyFileDialog + title: qsTr("Please choose a file to verify") + translationManager.emptyString; + folder: "file://" + nameFilters: [ "*"] + + onAccepted: { + verifyFileLine.text = walletManager.urlToLocalPath(verifyFileDialog.fileUrl) + } + } } function onPageCompleted() { diff --git a/pages/Transfer.qml b/pages/Transfer.qml index a52a8f92..fa33c49b 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -205,7 +205,7 @@ Rectangle { LineEditMulti { id: addressLine spacing: 0 - inputLabelText: qsTr("\ + labelText: qsTr("\ Address ( Address book )") + translationManager.emptyString labelButtonText: qsTr("Resolve") + translationManager.emptyString diff --git a/pages/TxKey.qml b/pages/TxKey.qml index 18a65abf..febcb31b 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -132,7 +132,6 @@ Rectangle { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter anchors.bottomMargin: 3 * scaleRatio - } Label { From 916c7acbb7f0bb658acd3ea050ea4b04581374e2 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 21 Mar 2018 23:58:51 +0100 Subject: [PATCH 100/126] Design polish work --- main.qml | 1 - pages/History.qml | 13 +++++++++++-- pages/Keys.qml | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/main.qml b/main.qml index 9cb3bc34..4d69d217 100644 --- a/main.qml +++ b/main.qml @@ -286,7 +286,6 @@ ApplicationWindow { informationPopup.onCloseCallback = function() { appWindow.close(); } - return; } walletName = usefulName(wallet.path) diff --git a/pages/History.qml b/pages/History.qml index a1f3142a..f6fe8736 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -133,15 +133,24 @@ Rectangle { spacing: 0 GridLayout { - columns: (isMobile)? 1 : 2 + property int column_width: { + if(!isMobile){ + return (parent.width / 2) - 20; + } else { + return parent.width - 20; + } + } + + columns: 2 Layout.fillWidth: true - columnSpacing: 26 * scaleRatio RowLayout { visible: !isMobile + Layout.preferredWidth: parent.column_width } RowLayout { + Layout.preferredWidth: parent.column_width LineEdit { id: searchLine fontSize: 14 * scaleRatio diff --git a/pages/Keys.qml b/pages/Keys.qml index 50928579..37ea3060 100644 --- a/pages/Keys.qml +++ b/pages/Keys.qml @@ -187,6 +187,7 @@ Rectangle { Layout.fillWidth: true font.bold: true font.pixelSize: 16 * scaleRatio + color: Style.defaultFontColor text: (viewOnlyQRCode.visible) ? qsTr("View Only Wallet") + translationManager.emptyString : qsTr("Spendable Wallet") + translationManager.emptyString horizontalAlignment: Text.AlignHCenter } From 72a7fac4675e109080a734ec9e9ad3987b87237d Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 22 Mar 2018 03:51:57 +0100 Subject: [PATCH 101/126] Restyled password dialog --- components/PasswordDialog.qml | 133 ++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 64 deletions(-) diff --git a/components/PasswordDialog.qml b/components/PasswordDialog.qml index e8563a73..80d2a677 100644 --- a/components/PasswordDialog.qml +++ b/components/PasswordDialog.qml @@ -26,8 +26,8 @@ // 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 2.7 +import QtQuick.Controls 2.0 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.4 @@ -38,13 +38,6 @@ 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: passwordInput.text property string walletName @@ -61,7 +54,7 @@ Item { titleBar.enabled = false show() root.visible = true; - passwordInput.focus = true + passwordInput.forceActiveFocus(); passwordInput.text = "" } @@ -82,41 +75,52 @@ Item { ColumnLayout { id: column //anchors {fill: parent; margins: 16 } + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: 400 * scaleRatio Label { - text: root.walletName.length > 0 ? qsTr("Please enter wallet password for:
") + root.walletName : qsTr("Please enter wallet password") - Layout.alignment: Qt.AlignHCenter - Layout.columnSpan: 2 + text: qsTr("Please enter wallet password") + anchors.left: parent.left Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - font.pixelSize: 18 * scaleRatio - font.family: "Arial" - color: "#555555" + + font.pixelSize: 16 * scaleRatio + font.family: Style.fontLight + + color: Style.defaultFontColor } TextField { id : passwordInput + Layout.topMargin: 8 Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - Layout.maximumWidth: 400 * scaleRatio - horizontalAlignment: TextInput.AlignHCenter + anchors.left: parent.left + horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: "Arial" - font.pixelSize: 32 * scaleRatio + font.family: Style.fontLight + font.pixelSize: 24 * scaleRatio echoMode: TextInput.Password KeyNavigation.tab: okButton + bottomPadding: 10 + leftPadding: 10 + topPadding: 10 + color: "white" + background: Rectangle { + radius: 2 + border.color: Qt.rgba(255, 255, 255, 0.35) + border.width: 1 + color: "black" - style: TextFieldStyle { - renderType: Text.NativeRendering - textColor: "#35B05A" - passwordCharacter: "•" - // no background - background: Rectangle { - radius: 0 - border.width: 0 + Image { + width: 12 + height: 16 + source: "../images/lockIcon.png" + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 20 } } + Keys.onReturnPressed: { root.close() root.accepted() @@ -127,44 +131,45 @@ Item { root.rejected() } - - } - // underline - Rectangle { - height: 1 - color: "#DBDBDB" - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - anchors.bottomMargin: 3 - Layout.maximumWidth: passwordInput.width - } - } - // Ok/Cancel buttons - RowLayout { - id: buttons - spacing: 60 * scaleRatio - Layout.alignment: Qt.AlignHCenter - - MoneroComponents.StandardButton { - id: cancelButton - text: qsTr("Cancel") + translationManager.emptyString - KeyNavigation.tab: passwordInput - onClicked: { - root.close() - root.rejected() - } - } - MoneroComponents.StandardButton { - id: okButton - text: qsTr("Continue") - KeyNavigation.tab: cancelButton - onClicked: { - root.close() - root.accepted() + // Ok/Cancel buttons + RowLayout { + id: buttons + spacing: 16 * scaleRatio + Layout.topMargin: 16 + Layout.alignment: Qt.AlignRight + + MoneroComponents.StandardButton { + id: cancelButton + small: true + text: qsTr("Cancel") + translationManager.emptyString + KeyNavigation.tab: passwordInput + onClicked: { + root.close() + root.rejected() + } + } + + MoneroComponents.StandardButton { + id: okButton + small: true + text: qsTr("Continue") + KeyNavigation.tab: cancelButton + onClicked: { + root.close() + root.accepted() + } } } + } } + Rectangle { + id: bg + + anchors.fill: parent + color: "black" + opacity: 0.8 + } } From b38ee48e594e4cc19299afd4c888f39075688101 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 22 Mar 2018 05:06:11 +0100 Subject: [PATCH 102/126] Redesigned NewPasswordDialog --- components/NewPasswordDialog.qml | 81 +++++++++++++------------------- components/PasswordDialog.qml | 2 +- 2 files changed, 33 insertions(+), 50 deletions(-) diff --git a/components/NewPasswordDialog.qml b/components/NewPasswordDialog.qml index af9c0973..4ddf0fde 100644 --- a/components/NewPasswordDialog.qml +++ b/components/NewPasswordDialog.qml @@ -42,8 +42,8 @@ Item { id: bg z: parent.z + 1 anchors.fill: parent - color: "white" - opacity: 0.9 + color: "black" + opacity: 0.8 } property alias password: passwordInput1.text @@ -103,8 +103,8 @@ Item { Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter font.pixelSize: 18 * scaleRatio - font.family: "Arial" - color: "#555555" + font.family: Style.fontLight + color: Style.defaultFontColor } TextField { @@ -121,7 +121,7 @@ Item { style: TextFieldStyle { renderType: Text.NativeRendering - textColor: "#35B05A" + textColor: "black" passwordCharacter: "•" // no background background: Rectangle { @@ -135,15 +135,6 @@ Item { } } - // 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 @@ -160,8 +151,8 @@ Item { Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter font.pixelSize: 18 * scaleRatio - font.family: "Arial" - color: "#555555" + font.family: Style.fontLight + color: Style.defaultFontColor } TextField { @@ -178,7 +169,7 @@ Item { style: TextFieldStyle { renderType: Text.NativeRendering - textColor: "#35B05A" + textColor: "black" passwordCharacter: "•" // no background background: Rectangle { @@ -198,15 +189,6 @@ Item { } } - // 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 @@ -215,30 +197,31 @@ Item { opacity: 0 color: "black" } - } - // Ok/Cancel buttons - RowLayout { - id: buttons - spacing: 60 * scaleRatio - Layout.alignment: Qt.AlignHCenter - - MoneroComponents.StandardButton { - id: cancelButton - text: qsTr("Cancel") + translationManager.emptyString - KeyNavigation.tab: passwordInput1 - onClicked: { - root.close() - root.rejected() + + // Ok/Cancel buttons + RowLayout { + id: buttons + spacing: 60 * scaleRatio + Layout.alignment: Qt.AlignHCenter + + MoneroComponents.StandardButton { + id: cancelButton + text: qsTr("Cancel") + translationManager.emptyString + KeyNavigation.tab: passwordInput1 + onClicked: { + root.close() + root.rejected() + } } - } - MoneroComponents.StandardButton { - id: okButton - text: qsTr("Continue") - KeyNavigation.tab: cancelButton - enabled: passwordInput1.text === passwordInput2.text - onClicked: { - root.close() - root.accepted() + MoneroComponents.StandardButton { + id: okButton + text: qsTr("Continue") + KeyNavigation.tab: cancelButton + enabled: passwordInput1.text === passwordInput2.text + onClicked: { + root.close() + root.accepted() + } } } } diff --git a/components/PasswordDialog.qml b/components/PasswordDialog.qml index 80d2a677..444b2306 100644 --- a/components/PasswordDialog.qml +++ b/components/PasswordDialog.qml @@ -92,7 +92,7 @@ Item { TextField { id : passwordInput - Layout.topMargin: 8 + Layout.topMargin: 6 Layout.fillWidth: true anchors.left: parent.left horizontalAlignment: TextInput.AlignLeft From 625b92318fbe14e06eedb8537a1eabceb4c8a319 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 22 Mar 2018 05:07:09 +0100 Subject: [PATCH 103/126] Restyled warning box (not connected to daemon) --- components/LineEdit.qml | 4 +- images/warning.png | Bin 0 -> 19517 bytes pages/History.qml | 2 +- pages/Transfer.qml | 81 +++++++++++++++++++++++++++------------- qml.qrc | 1 + 5 files changed, 60 insertions(+), 28 deletions(-) create mode 100755 images/warning.png diff --git a/components/LineEdit.qml b/components/LineEdit.qml index f5e8a478..9afb5ebc 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -78,9 +78,9 @@ Item { onTextUpdated: { // check to remove placeholder text when there is content if(item.isEmpty()){ - placeholderLabel.visible = true + placeholderLabel.visible = true; } else { - placeholderLabel.visible = false + placeholderLabel.visible = false; } } diff --git a/images/warning.png b/images/warning.png new file mode 100755 index 0000000000000000000000000000000000000000..8036d84a0e33fdd20a2de1e2c164f5da94a4d3cd GIT binary patch literal 19517 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" + root.startLinkText + warningText.text = qsTr("Wallet is not connected to daemon.") + root.startLinkText return; } if (currentWallet.viewOnly) { - // statusText.text = qsTr("Wallet is view only.") + // warningText.text = qsTr("Wallet is view only.") //return; } - pageRoot.enabled = false; + //pageRoot.enabled = false; switch (currentWallet.connected()) { case Wallet.ConnectionStatus_Disconnected: - statusText.text = qsTr("Wallet is not connected to daemon.") + "
" + root.startLinkText + warningText.text = qsTr("Wallet is not connected to daemon.") + root.startLinkText break case Wallet.ConnectionStatus_WrongVersion: - statusText.text = qsTr("Connected daemon is not compatible with GUI. \n" + + warningText.text = qsTr("Connected daemon is not compatible with GUI. \n" + "Please upgrade or connect to another daemon") break default: if(!appWindow.daemonSynced){ - statusText.text = qsTr("Waiting on daemon synchronization to finish") + warningText.text = qsTr("Waiting on daemon synchronization to finish") } else { // everything OK, enable transfer page // Light wallet is always ready pageRoot.enabled = true; - statusText.text = ""; + warningText.text = ""; } - } } diff --git a/qml.qrc b/qml.qrc index ad4f1f86..0be96187 100644 --- a/qml.qrc +++ b/qml.qrc @@ -203,5 +203,6 @@ components/HistoryTableInnerColumn.qml components/CheckBox2.qml js/TxUtils.js + images/warning.png From 7e8915966b2c1a80debd54e7a2e2dd6275d558a4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 22 Mar 2018 15:56:59 +0100 Subject: [PATCH 104/126] Bring QT version down to 5.7 --- components/Input.qml | 2 +- components/InputMulti.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/Input.qml b/components/Input.qml index c168e8e6..d1ddae89 100644 --- a/components/Input.qml +++ b/components/Input.qml @@ -27,7 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick.Controls 2.2 -import QtQuick 2.10 +import QtQuick 2.7 import "." 1.0 diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 9c74d0c1..24c019b4 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -28,7 +28,7 @@ import QtQuick.Controls 2.2 -import QtQuick 2.10 +import QtQuick 2.7 import "../js/TxUtils.js" as TxUtils import "." 1.0 From 2d7ef434becf86ceb15dbeadc141ac49a96a3308 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 23 Mar 2018 21:50:46 +0100 Subject: [PATCH 105/126] Updated balance card; removes lock icon --- images/card-background.png | Bin 31270 -> 31031 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/images/card-background.png b/images/card-background.png index 82b7c79f450dd6a59e3d1ddd39e7ae377f3465b6..c049e7b0b252059290de9755af5fe08f7abd9cba 100644 GIT binary patch literal 31031 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 From 28608e4ce0dab70ac19b77315b6b2ced220ef6ad Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 23 Mar 2018 21:51:28 +0100 Subject: [PATCH 106/126] Restyling the dialog boxes a bit more --- components/InputDialog.qml | 137 +++++++++++++++---------------- components/NewPasswordDialog.qml | 101 ++++++++++++++--------- components/PasswordDialog.qml | 5 +- 3 files changed, 129 insertions(+), 114 deletions(-) diff --git a/components/InputDialog.qml b/components/InputDialog.qml index 2990c5c9..34e9a6e2 100644 --- a/components/InputDialog.qml +++ b/components/InputDialog.qml @@ -26,8 +26,8 @@ // 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 2.7 +import QtQuick.Controls 2.0 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.4 @@ -38,14 +38,6 @@ 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 @@ -78,42 +70,45 @@ Item { ColumnLayout { id: column - //anchors {fill: parent; margins: 16 } + + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: 400 * scaleRatio Label { id: label - Layout.alignment: Qt.AlignHCenter - // Layout.columnSpan: 2 + anchors.left: parent.left Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - font.pixelSize: 18 * scaleRatio - font.family: "Arial" - color: "#555555" + + font.pixelSize: 16 * scaleRatio + font.family: Style.fontLight + + color: Style.defaultFontColor } TextField { id : input focus: true + Layout.topMargin: 6 Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: TextInput.AlignHCenter + anchors.left: parent.left + horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: "Arial" - font.pixelSize: 32 * scaleRatio - // echoMode: TextInput.Password + font.family: Style.fontLight + font.pixelSize: 24 * scaleRatio KeyNavigation.tab: okButton + bottomPadding: 10 + leftPadding: 10 + topPadding: 10 + color: Style.defaultFontColor - style: TextFieldStyle { - renderType: Text.NativeRendering - textColor: "#35B05A" - // passwordCharacter: "•" - // no background - background: Rectangle { - radius: 0 - border.width: 0 - } + background: Rectangle { + radius: 2 + border.color: Qt.rgba(255, 255, 255, 0.35) + border.width: 1 + color: "black" } + Keys.onReturnPressed: { root.close() root.accepted() @@ -123,51 +118,47 @@ Item { 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 - text: qsTr("Cancel") + translationManager.emptyString - KeyNavigation.tab: input - onClicked: { - root.close() - root.rejected() + + // Ok/Cancel buttons + RowLayout { + id: buttons + spacing: 16 * scaleRatio + Layout.topMargin: 16 + Layout.alignment: Qt.AlignRight + + MoneroComponents.StandardButton { + id: cancelButton + small: true + width: 120 + fontSize: 14 + text: qsTr("Cancel") + translationManager.emptyString + KeyNavigation.tab: input + onClicked: { + root.close() + root.rejected() + } } - } - MoneroComponents.StandardButton { - id: okButton - width: 120 - fontSize: 14 - text: qsTr("Ok") - KeyNavigation.tab: cancelButton - onClicked: { - root.close() - root.accepted() + MoneroComponents.StandardButton { + id: okButton + small: true + width: 120 + fontSize: 14 + text: qsTr("Ok") + KeyNavigation.tab: cancelButton + onClicked: { + root.close() + root.accepted() + } } } } } + + Rectangle { + id: bg + z: parent.z + 1 + anchors.fill: parent + color: "black" + opacity: 0.8 + } } diff --git a/components/NewPasswordDialog.qml b/components/NewPasswordDialog.qml index 4ddf0fde..b1d39f56 100644 --- a/components/NewPasswordDialog.qml +++ b/components/NewPasswordDialog.qml @@ -26,8 +26,8 @@ // 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 2.7 +import QtQuick.Controls 2.0 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.4 @@ -93,42 +93,54 @@ Item { ColumnLayout { id: column - //anchors {fill: parent; margins: 16 } + + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: 400 * scaleRatio Label { text: qsTr("Please enter new password") - Layout.alignment: Qt.AlignHCenter - Layout.columnSpan: 2 + anchors.left: parent.left Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - font.pixelSize: 18 * scaleRatio + + font.pixelSize: 16 * scaleRatio font.family: Style.fontLight + color: Style.defaultFontColor } TextField { id : passwordInput1 + Layout.topMargin: 6 Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - Layout.maximumWidth: 400 * scaleRatio - horizontalAlignment: TextInput.AlignHCenter + anchors.left: parent.left + horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: "Arial" - font.pixelSize: 32 * scaleRatio + font.family: Style.fontLight + font.pixelSize: 24 * scaleRatio echoMode: TextInput.Password + bottomPadding: 10 + leftPadding: 10 + topPadding: 10 + color: Style.defaultFontColor KeyNavigation.tab: passwordInput2 - style: TextFieldStyle { - renderType: Text.NativeRendering - textColor: "black" - passwordCharacter: "•" - // no background - background: Rectangle { - radius: 0 - border.width: 0 + background: Rectangle { + radius: 2 + border.color: Qt.rgba(255, 255, 255, 0.35) + border.width: 1 + color: "black" + + Image { + width: 12 + height: 16 + source: "../images/lockIcon.png" + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 20 } } + Keys.onEscapePressed: { root.close() root.rejected() @@ -146,37 +158,47 @@ Item { Label { text: qsTr("Please confirm new password") - Layout.alignment: Qt.AlignHCenter - Layout.columnSpan: 2 + anchors.left: parent.left Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - font.pixelSize: 18 * scaleRatio + + font.pixelSize: 16 * scaleRatio font.family: Style.fontLight + color: Style.defaultFontColor } TextField { id : passwordInput2 + Layout.topMargin: 6 Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - Layout.maximumWidth: 400 * scaleRatio - horizontalAlignment: TextInput.AlignHCenter + anchors.left: parent.left + horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: "Arial" - font.pixelSize: 32 * scaleRatio + font.family: Style.fontLight + font.pixelSize: 24 * scaleRatio echoMode: TextInput.Password KeyNavigation.tab: okButton + bottomPadding: 10 + leftPadding: 10 + topPadding: 10 + color: Style.defaultFontColor - style: TextFieldStyle { - renderType: Text.NativeRendering - textColor: "black" - passwordCharacter: "•" - // no background - background: Rectangle { - radius: 0 - border.width: 0 + background: Rectangle { + radius: 2 + border.color: Qt.rgba(255, 255, 255, 0.35) + border.width: 1 + color: "black" + + Image { + width: 12 + height: 16 + source: "../images/lockIcon.png" + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 20 } } + Keys.onReturnPressed: { if (passwordInput1.text === passwordInput2.text) { root.close() @@ -201,8 +223,9 @@ Item { // Ok/Cancel buttons RowLayout { id: buttons - spacing: 60 * scaleRatio - Layout.alignment: Qt.AlignHCenter + spacing: 16 * scaleRatio + Layout.topMargin: 16 + Layout.alignment: Qt.AlignRight MoneroComponents.StandardButton { id: cancelButton diff --git a/components/PasswordDialog.qml b/components/PasswordDialog.qml index 444b2306..b313874a 100644 --- a/components/PasswordDialog.qml +++ b/components/PasswordDialog.qml @@ -74,7 +74,7 @@ Item { ColumnLayout { id: column - //anchors {fill: parent; margins: 16 } + Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter Layout.maximumWidth: 400 * scaleRatio @@ -104,7 +104,8 @@ Item { bottomPadding: 10 leftPadding: 10 topPadding: 10 - color: "white" + color: Style.defaultFontColor + background: Rectangle { radius: 2 border.color: Qt.rgba(255, 255, 255, 0.35) From 60f64a30ad0ae5e47db81986da65c9b2fae5ec5c Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 23 Mar 2018 23:50:45 +0100 Subject: [PATCH 107/126] Implement node bootstrap on the Settings page --- pages/Settings.qml | 52 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/pages/Settings.qml b/pages/Settings.qml index c56e6e0c..a5896689 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -229,6 +229,42 @@ Rectangle { } } + RowLayout { + visible: !isMobile && !persistentSettings.useRemoteNode + Layout.fillWidth: true + + LabelSubheader { + text: qsTr("Bootstrap node") + translationManager.emptyString + } + } + + RowLayout { + visible: !isMobile && !persistentSettings.useRemoteNode + + ColumnLayout { + Layout.fillWidth: true + + RemoteNodeEdit { + id: bootstrapNodeEdit + Layout.minimumWidth: 100 * scaleRatio + Layout.bottomMargin: 20 * scaleRatio + + lineEditBackgroundColor: "transparent" + lineEditFontColor: "white" + lineEditBorderColor: Qt.rgba(255, 255, 255, 0.35) + + daemonAddrLabelText: qsTr("Address") + daemonPortLabelText: qsTr("Port") + daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim() + daemonPortText: (persistentSettings.bootstrapNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.bootstrapNodeAddress.split(":")[1] + onEditingFinished: { + persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : ""; + console.log("setting bootstrap node to " + persistentSettings.bootstrapNodeAddress) + } + } + } + } + RowLayout { visible: persistentSettings.useRemoteNode ColumnLayout { @@ -237,13 +273,17 @@ Rectangle { RemoteNodeEdit { id: remoteNodeEdit Layout.minimumWidth: 100 * scaleRatio - daemonAddrLabelText: qsTr("Address") - daemonPortLabelText: qsTr("Port") + lineEditBackgroundColor: "transparent" lineEditFontColor: "white" lineEditBorderColor: Qt.rgba(255, 255, 255, 0.35) - daemonAddrText: persistentSettings.remoteNodeAddress.split(":")[0].trim() - daemonPortText: (persistentSettings.remoteNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1] + + daemonAddrLabelText: qsTr("Address") + daemonPortLabelText: qsTr("Port") + + property var rna: persistentSettings.remoteNodeAddress + daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : "" + daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : rna.split(":")[1] : "" onEditingFinished: { persistentSettings.remoteNodeAddress = remoteNodeEdit.getAddress(); console.log("setting remote node to " + persistentSettings.remoteNodeAddress) @@ -310,8 +350,8 @@ Rectangle { persistentSettings.bootstrapNodeAddress = bootstrapNodeEdit.daemonAddrText ? bootstrapNodeEdit.getAddress() : ""; // Set current daemon address to local - appWindow.currentDaemonAddress = appWindow.localDaemonAddress - appWindow.startDaemon(daemonFlags.text) + appWindow.currentDaemonAddress = appWindow.localDaemonAddress; + appWindow.startDaemon(daemonFlags.text); } } From 84e6461248dc86836d6019f9b959dc067558c2a8 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Fri, 23 Mar 2018 23:53:29 +0100 Subject: [PATCH 108/126] Change 'money' to 'monero' --- main.qml | 4 ++-- pages/Transfer.qml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.qml b/main.qml index 4d69d217..1d41db3b 100644 --- a/main.qml +++ b/main.qml @@ -564,7 +564,7 @@ ApplicationWindow { function onWalletMoneySent(txId, amount) { // refresh transaction history here - console.log("money sent found") + console.log("monero sent found") currentWallet.refresh() currentWallet.history.refresh(currentWallet.currentSubaddressAccount) // this will refresh model } @@ -777,7 +777,7 @@ ApplicationWindow { txid_text += ", " txid_text += txid[i] } - informationPopup.text = (viewOnly)? qsTr("Transaction saved to file: %1").arg(path) : qsTr("Money sent successfully: %1 transaction(s) ").arg(txid.length) + txid_text + translationManager.emptyString + informationPopup.text = (viewOnly)? qsTr("Transaction saved to file: %1").arg(path) : qsTr("Monero sent successfully: %1 transaction(s) ").arg(txid.length) + txid_text + translationManager.emptyString informationPopup.icon = StandardIcon.Information if (transactionDescription.length > 0) { for (var i = 0; i < txid.length; ++i) diff --git a/pages/Transfer.qml b/pages/Transfer.qml index f4020984..c6a4ea5b 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -577,7 +577,7 @@ Rectangle { informationPopup.open(); } else { informationPopup.title = qsTr("Information") + translationManager.emptyString - informationPopup.text = qsTr("Money sent successfully") + translationManager.emptyString + informationPopup.text = qsTr("Monero sent successfully") + translationManager.emptyString informationPopup.icon = StandardIcon.Information informationPopup.onCloseCallback = null informationPopup.open(); From 3f9926487d37e5338ac6490fc81fdcf35caa708d Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 24 Mar 2018 18:22:38 +0100 Subject: [PATCH 109/126] Fixes typo --- wizard/WizardManageWalletUI.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wizard/WizardManageWalletUI.qml b/wizard/WizardManageWalletUI.qml index 6f039415..80407f0c 100644 --- a/wizard/WizardManageWalletUI.qml +++ b/wizard/WizardManageWalletUI.qml @@ -154,7 +154,7 @@ ColumnLayout { Label { Layout.topMargin: 20 * scaleRatio - fontFamily: "Ariel" + fontFamily: "Arial" fontColor: "#555555" fontSize: 14 * scaleRatio text: qsTr("Wallet name") From c001e312410efe8f883bb5163e5554d84126c034 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 24 Mar 2018 20:48:19 +0100 Subject: [PATCH 110/126] Fixes runtime QML warning --- LeftPanel.qml | 3 ++- components/CheckBox2.qml | 2 +- components/DatePicker.qml | 2 +- components/InputDialog.qml | 4 ++-- components/InputMulti.qml | 2 +- components/Label.qml | 2 +- components/LineEdit.qml | 4 ++-- components/LineEditMulti.qml | 4 ++-- components/NetworkStatusItem.qml | 5 +++-- components/NewPasswordDialog.qml | 8 ++++---- components/PasswordDialog.qml | 4 ++-- components/ProgressBar.qml | 5 +++-- components/StandardDialog.qml | 8 +++++--- components/StandardDropdown.qml | 2 +- components/SubaddressTable.qml | 4 ++-- pages/Mining.qml | 2 +- pages/Receive.qml | 2 +- pages/Settings.qml | 9 ++++++++- pages/Sign.qml | 2 +- pages/Transfer.qml | 8 ++++---- pages/TxKey.qml | 6 +++--- 21 files changed, 50 insertions(+), 38 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index 27ac3e5a..0869e63b 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.2 +import QtQuick.Layouts 1.1 import QtGraphicalEffects 1.0 import moneroComponents.Wallet 1.0 import moneroComponents.NetworkType 1.0 @@ -101,7 +102,7 @@ Rectangle { // @TODO: customDecorations? anchors.topMargin: (persistentSettings.customDecorations)? 50 : 0 - Row { + RowLayout { visible: true Item { anchors.left: parent.left diff --git a/components/CheckBox2.qml b/components/CheckBox2.qml index dd48624e..667a950f 100644 --- a/components/CheckBox2.qml +++ b/components/CheckBox2.qml @@ -59,7 +59,7 @@ RowLayout { Text { id: label - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: checkBox.fontSize color: Style.defaultFontColor wrapMode: Text.Wrap diff --git a/components/DatePicker.qml b/components/DatePicker.qml index ace95d2d..45d21406 100644 --- a/components/DatePicker.qml +++ b/components/DatePicker.qml @@ -73,7 +73,7 @@ Item { anchors.top: parent.top anchors.topMargin: 2 anchors.left: parent.left - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: 14 font.bold: false textFormat: Text.RichText diff --git a/components/InputDialog.qml b/components/InputDialog.qml index 34e9a6e2..37354b35 100644 --- a/components/InputDialog.qml +++ b/components/InputDialog.qml @@ -81,7 +81,7 @@ Item { Layout.fillWidth: true font.pixelSize: 16 * scaleRatio - font.family: Style.fontLight + font.family: Style.fontLight.name color: Style.defaultFontColor } @@ -94,7 +94,7 @@ Item { anchors.left: parent.left horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: 24 * scaleRatio KeyNavigation.tab: okButton bottomPadding: 10 diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 24c019b4..2839db3a 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -40,7 +40,7 @@ TextArea { property int fontSize: 18 * scaleRatio id: textArea - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: fontSize font.bold: false horizontalAlignment: TextInput.AlignLeft diff --git a/components/Label.qml b/components/Label.qml index ac0ff487..79b83a5d 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -57,7 +57,7 @@ Item { if(fontFamily){ return fontFamily; } else { - return Style.fontLight; + return Style.fontRegular.name; } } font.pixelSize: fontSize diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 9afb5ebc..1711ee56 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -61,7 +61,7 @@ Item { property alias labelTextFormat: inputLabel.textFormat property string backgroundColor: "transparent" property string tipText: "" - property int labelFontSize: 14 * scaleRatio + property int labelFontSize: 16 * scaleRatio property bool labelFontBold: false property alias labelWrapMode: inputLabel.wrapMode property alias labelHorizontalAlignment: inputLabel.horizontalAlignment @@ -99,7 +99,7 @@ Item { anchors.top: parent.top anchors.left: parent.left anchors.topMargin: 2 * scaleRatio - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: labelFontSize font.bold: labelFontBold textFormat: Text.RichText diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 758755d0..b0669aaa 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -63,8 +63,8 @@ ColumnLayout { id: inputLabel anchors.top: parent.top anchors.left: parent.left - font.family: Style.fontLight - font.pixelSize: 14 * scaleRatio + font.family: Style.fontRegular.name + font.pixelSize: 16 * scaleRatio font.bold: labelFontBold textFormat: Text.RichText color: Style.defaultFontColor diff --git a/components/NetworkStatusItem.qml b/components/NetworkStatusItem.qml index 984ffd03..39ca8f0d 100644 --- a/components/NetworkStatusItem.qml +++ b/components/NetworkStatusItem.qml @@ -27,6 +27,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import QtQuick 2.0 +import QtQuick.Layouts 1.1 import moneroComponents.Wallet 1.0 import "." 1.0 @@ -50,8 +51,8 @@ Rectangle { return qsTr("Invalid connection status") } - Row { - height: 40 * scaleRatio + RowLayout { + Layout.preferredHeight: 40 * scaleRatio Item { id: iconItem diff --git a/components/NewPasswordDialog.qml b/components/NewPasswordDialog.qml index b1d39f56..9d4e4d20 100644 --- a/components/NewPasswordDialog.qml +++ b/components/NewPasswordDialog.qml @@ -104,7 +104,7 @@ Item { Layout.fillWidth: true font.pixelSize: 16 * scaleRatio - font.family: Style.fontLight + font.family: Style.fontLight.name color: Style.defaultFontColor } @@ -116,7 +116,7 @@ Item { anchors.left: parent.left horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: 24 * scaleRatio echoMode: TextInput.Password bottomPadding: 10 @@ -162,7 +162,7 @@ Item { Layout.fillWidth: true font.pixelSize: 16 * scaleRatio - font.family: Style.fontLight + font.family: Style.fontLight.name color: Style.defaultFontColor } @@ -174,7 +174,7 @@ Item { anchors.left: parent.left horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: 24 * scaleRatio echoMode: TextInput.Password KeyNavigation.tab: okButton diff --git a/components/PasswordDialog.qml b/components/PasswordDialog.qml index b313874a..dabf233a 100644 --- a/components/PasswordDialog.qml +++ b/components/PasswordDialog.qml @@ -85,7 +85,7 @@ Item { Layout.fillWidth: true font.pixelSize: 16 * scaleRatio - font.family: Style.fontLight + font.family: Style.fontLight.name color: Style.defaultFontColor } @@ -97,7 +97,7 @@ Item { anchors.left: parent.left horizontalAlignment: TextInput.AlignLeft verticalAlignment: TextInput.AlignVCenter - font.family: Style.fontLight + font.family: Style.fontLight.name font.pixelSize: 24 * scaleRatio echoMode: TextInput.Password KeyNavigation.tab: okButton diff --git a/components/ProgressBar.qml b/components/ProgressBar.qml index f9bb315f..6e691d6e 100644 --- a/components/ProgressBar.qml +++ b/components/ProgressBar.qml @@ -52,6 +52,7 @@ Rectangle { } Item { + anchors.top: item.top anchors.topMargin: 10 * scaleRatio anchors.leftMargin: 15 * scaleRatio anchors.rightMargin: 15 * scaleRatio @@ -59,7 +60,7 @@ Rectangle { Text { id: progressText - anchors.top: item.top + anchors.top: parent.top anchors.topMargin: 6 font.family: Style.fontMedium.name font.pixelSize: 13 * scaleRatio @@ -71,7 +72,7 @@ Rectangle { Text { id: progressTextValue - anchors.top: item.top + anchors.top: parent.top anchors.topMargin: 6 anchors.right: parent.right font.family: Style.fontMedium.name diff --git a/components/StandardDialog.qml b/components/StandardDialog.qml index 44c7c784..5f761ae4 100644 --- a/components/StandardDialog.qml +++ b/components/StandardDialog.qml @@ -34,6 +34,8 @@ import QtQuick.Controls.Styles 1.4 import QtQuick.Window 2.0 import "../components" as MoneroComponents +import "." 1.0 + Rectangle { id: root @@ -105,8 +107,8 @@ Rectangle { Label { id: dialogTitle horizontalAlignment: Text.AlignHCenter - font.pixelSize: 18 * scaleRatio - font.family: "Arial" + fontSize: 18 * scaleRatio + fontFamily: "Arial" color: Style.defaultFontColor } @@ -118,7 +120,7 @@ Rectangle { Layout.fillWidth: true Layout.fillHeight: true renderType: Text.QtRendering - font.family: Style.fontLight + font.family: Style.fontLight.name textFormat: TextEdit.AutoText readOnly: true font.pixelSize: 14 * scaleRatio diff --git a/components/StandardDropdown.qml b/components/StandardDropdown.qml index 0d6e771d..9ab90f4b 100644 --- a/components/StandardDropdown.qml +++ b/components/StandardDropdown.qml @@ -90,7 +90,7 @@ Item { anchors.left: parent.left anchors.leftMargin: 12 * scaleRatio elide: Text.ElideRight - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.bold: dropdown.headerFontBold font.pixelSize: dropdown.fontHeaderSize color: "#FFFFFF" diff --git a/components/SubaddressTable.qml b/components/SubaddressTable.qml index 88856ad3..811d1199 100644 --- a/components/SubaddressTable.qml +++ b/components/SubaddressTable.qml @@ -42,7 +42,7 @@ ListView { delegate: Rectangle { id: delegate - height: 74 + height: 80 color: 'transparent'; anchors.topMargin: 0 width: listView.width @@ -57,7 +57,7 @@ ListView { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - anchors.leftMargin: 5 + anchors.leftMargin: 10 anchors.topMargin: 12 anchors.rightMargin: 54 anchors.bottomMargin: 0 diff --git a/pages/Mining.qml b/pages/Mining.qml index 983fc880..f27a2b19 100644 --- a/pages/Mining.qml +++ b/pages/Mining.qml @@ -74,7 +74,7 @@ Rectangle { text: qsTr("Mining with your computer helps strengthen the Monero network. The more that people mine, the harder it is for the network to be attacked, and every little bit helps.

Mining also gives you a small chance to earn some Monero. Your computer will create hashes looking for block solutions. If you find a block, you will get the associated reward. Good luck!") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: Style.defaultFontColor } diff --git a/pages/Receive.qml b/pages/Receive.qml index 774f92c6..497851e7 100644 --- a/pages/Receive.qml +++ b/pages/Receive.qml @@ -211,7 +211,7 @@ Rectangle { Rectangle { id: tableRect - property int table_max_height: 240 + property int table_max_height: 260 Layout.fillWidth: true Layout.preferredHeight: table.contentHeight < table_max_height ? table.contentHeight : table_max_height color: "transparent" diff --git a/pages/Settings.qml b/pages/Settings.qml index a5896689..e24d05dd 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -256,7 +256,14 @@ Rectangle { daemonAddrLabelText: qsTr("Address") daemonPortLabelText: qsTr("Port") daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim() - daemonPortText: (persistentSettings.bootstrapNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.bootstrapNodeAddress.split(":")[1] + daemonPortText: { + var node_split = persistentSettings.bootstrapNodeAddress.split(":"); + if(node_split.length == 2){ + (node_split[1].trim() == "") ? "18081" : node_split[1]; + } else { + return "" + } + } onEditingFinished: { persistentSettings.bootstrapNodeAddress = daemonAddrText ? bootstrapNodeEdit.getAddress() : ""; console.log("setting bootstrap node to " + persistentSettings.bootstrapNodeAddress) diff --git a/pages/Sign.qml b/pages/Sign.qml index 287846f2..e86ac71a 100644 --- a/pages/Sign.qml +++ b/pages/Sign.qml @@ -107,7 +107,7 @@ Rectangle { text: qsTr("This page lets you sign/verify a message (or file contents) with your address.") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: Style.defaultFontColor } diff --git a/pages/Transfer.qml b/pages/Transfer.qml index c6a4ea5b..f9c91396 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -140,7 +140,7 @@ Rectangle { Layout.preferredHeight: warningText.height + 40 Image { - anchors.verticalCenter: statusRect.verticalCenter + Layout.alignment: Qt.AlignVCenter Layout.preferredHeight: 33 Layout.preferredWidth: 33 Layout.leftMargin: 10 @@ -155,7 +155,7 @@ Rectangle { Layout.leftMargin: 6 text: qsTr("This page lets you sign/verify a message (or file contents) with your address.") + translationManager.emptyString wrapMode: Text.Wrap - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: Style.defaultFontColor textFormat: Text.RichText @@ -210,7 +210,7 @@ Rectangle { Layout.topMargin: 14 text: qsTr("Transaction priority") + translationManager.emptyString fontBold: false - fontSize: 14 + fontSize: 16 } // Note: workaround for translations in listElements // ListElement: cannot use script for property value, so @@ -408,7 +408,7 @@ Rectangle { Layout.fillWidth: true Label { id: privacyLabel - fontSize: 14 + fontSize: 15 text: "" } diff --git a/pages/TxKey.qml b/pages/TxKey.qml index febcb31b..7432aee2 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -71,7 +71,7 @@ Rectangle { "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 Layout.fillWidth: true - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: Style.defaultFontColor } @@ -145,7 +145,7 @@ Rectangle { "For the case with Spend Proof, you don't need to specify the recipient address.") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: Style.defaultFontColor } @@ -228,7 +228,7 @@ Rectangle { text: qsTr("If a payment had several transactions then each must be checked and the results combined.") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true - font.family: Style.fontRegular + font.family: Style.fontRegular.name font.pixelSize: 14 * scaleRatio color: Style.defaultFontColor } From 06bda869e081a874ef6d7fae377970c7a8ace42a Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sat, 24 Mar 2018 21:06:12 +0100 Subject: [PATCH 111/126] font.bold for amount/address/paymentid on the transfer page --- components/InputMulti.qml | 3 ++- components/LineEditMulti.qml | 2 ++ pages/Transfer.qml | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 2839db3a..9917eb52 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -38,11 +38,12 @@ TextArea { property bool addressValidation: false property bool wrapAnywhere: true property int fontSize: 18 * scaleRatio + property bool fontBold: false id: textArea font.family: Style.fontRegular.name font.pixelSize: fontSize - font.bold: false + font.bold: fontBold horizontalAlignment: TextInput.AlignLeft selectByMouse: true color: Style.defaultFontColor diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index b0669aaa..8609aaa4 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -46,6 +46,7 @@ ColumnLayout { property bool wrapAnywhere: true property bool showingHeader: true property bool showBorder: true + property bool fontBold: false property int fontSize: 16 * scaleRatio signal labelButtonClicked(); @@ -103,6 +104,7 @@ ColumnLayout { bottomPadding: 10 * scaleRatio wrapAnywhere: parent.wrapAnywhere fontSize: parent.fontSize + fontBold: parent.fontBold Text { id: placeholderLabel diff --git a/pages/Transfer.qml b/pages/Transfer.qml index f9c91396..a3e038a3 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -189,6 +189,7 @@ Rectangle { labelText: qsTr("Amount") + translationManager.emptyString placeholderText: qsTr("") + translationManager.emptyString width: 100 + fontBold: true inlineButtonText: qsTr("All") + translationManager.emptyString inlineButton.onClicked: amountLine.text = "(all)" @@ -252,6 +253,7 @@ Rectangle { LineEditMulti { id: addressLine spacing: 0 + fontBold: true labelText: qsTr("\ Address ( Address book )") + translationManager.emptyString @@ -308,6 +310,7 @@ Rectangle { // payment id input LineEdit { id: paymentIdLine + fontBold: true labelText: qsTr("Payment ID ( Optional )") + translationManager.emptyString placeholderText: qsTr("16 or 64 hexadecimal characters") + translationManager.emptyString Layout.fillWidth: true From 3d4eb7a5f5f63e52592faeff77cb76838a5add5e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Sun, 25 Mar 2018 00:40:04 +0100 Subject: [PATCH 112/126] Progress bars are always visible after recent change to two bars --- LeftPanel.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index 0869e63b..e99fa9fe 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -577,7 +577,7 @@ Rectangle { anchors.rightMargin: 4 anchors.bottom: (progressBar.visible)? progressBar.top : parent.bottom; connected: Wallet.ConnectionStatus_Disconnected - height: progressBar.visible ? 40 * scaleRatio : 60 * scaleRatio + height: 58 * scaleRatio } ProgressBar { From 3c2404473672991b51cbe6ec6d2d9326e9f85ca8 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 02:03:59 +0200 Subject: [PATCH 113/126] Cleanup after rebase --- LeftPanel.qml | 2 +- components/DatePicker.qml | 2 +- components/HistoryTable.qml | 44 ++++++++++---------------------- components/InputMulti.qml | 2 +- components/NetworkStatusItem.qml | 1 - monero-wallet-gui.pro | 1 + pages/Settings.qml | 10 -------- pages/Transfer.qml | 4 +-- pages/TxKey.qml | 4 +-- wizard/WizardOptions.qml | 24 +++++++++++++++-- 10 files changed, 44 insertions(+), 50 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index e99fa9fe..acefa60f 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -121,7 +121,7 @@ Rectangle { Text { id: testnetLabel - visible: persistentSettings.testnet + visible: persistentSettings.nettype text: qsTr("Testnet") + translationManager.emptyString anchors.top: parent.top anchors.topMargin: 8 diff --git a/components/DatePicker.qml b/components/DatePicker.qml index 45d21406..5d3c44bd 100644 --- a/components/DatePicker.qml +++ b/components/DatePicker.qml @@ -288,7 +288,7 @@ Item { gridVisible: false background: Rectangle { color: "transparent" } dayDelegate: Item { - z: 8 + z: parent.z + 1 implicitHeight: implicitWidth implicitWidth: calendar.width / 7 diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index e5abbc65..bcb869f2 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -163,30 +163,6 @@ ListView { color: "#808080" } -// // -- "BlockHeight" value -// TextEdit { -// readOnly: true -// selectByMouse: true -// width: 85 -// anchors.bottom: parent.bottom -// //elide: Text.ElideRight -// font.family: "Arial" -// font.pixelSize: 13 -// color: (confirmations < confirmationsRequired)? "#FF6C3C" : "#545454" -// text: { -// if (!isPending) -// if(confirmations < confirmationsRequired) -// return blockHeight + " " + qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired) -// else -// return blockHeight -// if (!isOut) -// return qsTr("UNCONFIRMED") + translationManager.emptyString -// if (isFailed) -// return qsTr("FAILED") + translationManager.emptyString -// return qsTr("PENDING") + translationManager.emptyString -// } -// } - Text { id: amountLabel anchors.left: arrowImage.right @@ -375,12 +351,20 @@ ListView { HistoryTableInnerColumn{ anchors.left: parent.left anchors.leftMargin: 30 * scaleRatio - labelHeader: qsTr("Payment ID") - labelValue: paymentId !== "" && !paymentId.startsWith("00000000") ? paymentId.substring(0, 32) + "..." : "-" - copyValue: { - if(paymentId !== "") { return paymentId } - else { return undefined } + labelHeader: qsTr("Blockheight") + labelValue: { + if (!isPending) + if(confirmations < confirmationsRequired) + return blockHeight + " " + qsTr("(%1/%2 confirmations)").arg(confirmations).arg(confirmationsRequired); + else + return blockHeight; + if (!isOut) + return qsTr("UNCONFIRMED") + translationManager.emptyString + if (isFailed) + return qsTr("FAILED") + translationManager.emptyString + return qsTr("PENDING") + translationManager.emptyString } + copyValue: labelValue } // right column @@ -433,7 +417,7 @@ ListView { return; } - var checked = (TxUtils.checkTxID(hash) && TxUtils.checkAddress(address, appWindow.persistentSettings.testnet)); + var checked = (TxUtils.checkTxID(hash) && TxUtils.checkAddress(address, appWindow.persistentSettings.nettype)); if(!checked){ console.log('getProof: Error checking TxId and/or address'); } diff --git a/components/InputMulti.qml b/components/InputMulti.qml index 9917eb52..3b860fdf 100644 --- a/components/InputMulti.qml +++ b/components/InputMulti.qml @@ -59,7 +59,7 @@ TextArea { if(addressValidation){ // js replacement for `RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }` textArea.text = textArea.text.replace(/[^a-z0-9]/gi,''); - var address_ok = TxUtils.checkAddress(textArea.text, appWindow.persistentSettings.testnet); + var address_ok = TxUtils.checkAddress(textArea.text, appWindow.persistentSettings.nettype); if(!address_ok) error = true; else error = false; TextArea.cursorPosition = textArea.text.length; diff --git a/components/NetworkStatusItem.qml b/components/NetworkStatusItem.qml index 39ca8f0d..f1916457 100644 --- a/components/NetworkStatusItem.qml +++ b/components/NetworkStatusItem.qml @@ -79,7 +79,6 @@ Rectangle { return "../images/lightning-white.png" } } - //getConnectionStatusImage(item.connected) } } diff --git a/monero-wallet-gui.pro b/monero-wallet-gui.pro index 61732a26..50d3e0e0 100644 --- a/monero-wallet-gui.pro +++ b/monero-wallet-gui.pro @@ -276,6 +276,7 @@ linux { -lboost_chrono \ -lboost_program_options \ -lssl \ + -llmdb \ -lcrypto if(!android) { diff --git a/pages/Settings.qml b/pages/Settings.qml index e24d05dd..abfc0e05 100644 --- a/pages/Settings.qml +++ b/pages/Settings.qml @@ -784,16 +784,6 @@ Rectangle { } - // fires on every page load - function onPageCompleted() { - console.log("Settings page loaded"); - initSettings(); - - - if(typeof daemonManager != "undefined") - appWindow.daemonRunning = daemonManager.running(persistentSettings.nettype) - } - // fires only once Component.onCompleted: { if(typeof daemonManager != "undefined") diff --git a/pages/Transfer.qml b/pages/Transfer.qml index a3e038a3..8f212dd9 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -265,7 +265,7 @@ Rectangle { if (result) { var parts = result.split("|") if (parts.length == 2) { - var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.testnet) + var address_ok = walletManager.addressValid(parts[1], appWindow.persistentSettings.nettype) if (parts[0] === "true") { if (address_ok) { addressLine.text = parts[1] @@ -332,7 +332,7 @@ Rectangle { rightIcon: "../images/rightIcon.png" Layout.topMargin: 4 * scaleRatio text: qsTr("Send") + translationManager.emptyString - 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.nettype) onClicked: { console.log("Transfer: paymentClicked") var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority diff --git a/pages/TxKey.qml b/pages/TxKey.qml index 7432aee2..791d8f7c 100644 --- a/pages/TxKey.qml +++ b/pages/TxKey.qml @@ -118,7 +118,7 @@ Rectangle { anchors.topMargin: 17 * scaleRatio width: 60 * scaleRatio text: qsTr("Generate") + translationManager.emptyString - enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.testnet)) + enabled: TxUtils.checkTxID(getProofTxIdLine.text) && (getProofAddressLine.text.length == 0 || TxUtils.checkAddress(getProofAddressLine.text, appWindow.persistentSettings.nettype)) onClicked: { console.log("getProof: Generate clicked: txid " + getProofTxIdLine.text + ", address " + getProofAddressLine.text + ", message: " + getProofMessageLine.text); root.getProofClicked(getProofTxIdLine.text, getProofAddressLine.text, getProofMessageLine.text) @@ -207,7 +207,7 @@ Rectangle { anchors.topMargin: 17 * scaleRatio width: 60 text: qsTr("Check") + translationManager.emptyString - enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.testnet))) + enabled: TxUtils.checkTxID(checkProofTxIdLine.text) && TxUtils.checkSignature(checkProofSignatureLine.text) && ((checkProofSignatureLine.text.indexOf("SpendProofV") === 0 && checkProofAddressLine.text.length == 0) || (checkProofSignatureLine.text.indexOf("SpendProofV") !== 0 && TxUtils.checkAddress(checkProofAddressLine.text, appWindow.persistentSettings.nettype))) onClicked: { 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) diff --git a/wizard/WizardOptions.qml b/wizard/WizardOptions.qml index fb6d83f3..7a9ffa62 100644 --- a/wizard/WizardOptions.qml +++ b/wizard/WizardOptions.qml @@ -245,11 +245,31 @@ ColumnLayout { CheckBox { id: testNet text: qsTr("Testnet") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio - checked: appWindow.persistentSettings.testnet; + checkedIcon: "../images/checkedVioletIcon.png" + uncheckedIcon: "../images/uncheckedIcon.png" + checked: appWindow.persistentSettings.nettype === NetworkType.TESTNET; + onClicked: { + persistentSettings.nettype = testNet.checked ? NetworkType.TESTNET : NetworkType.MAINNET + stageNet.checked = false; + console.log("Network type set to ", persistentSettings.nettype === NetworkType.TESTNET ? "Testnet" : "Mainnet") + } + } + } + + Rectangle { + width: 100 * scaleRatio + CheckBox { + id: stageNet + text: qsTr("Stagenet") + translationManager.emptyString + background: "#FFFFFF" + fontColor: "#4A4646" + fontSize: 16 * scaleRatio + checkedIcon: "../images/checkedVioletIcon.png" + uncheckedIcon: "../images/uncheckedIcon.png" + checked: appWindow.persistentSettings.nettype === NetworkType.STAGENET; onClicked: { persistentSettings.nettype = stageNet.checked ? NetworkType.STAGENET : NetworkType.MAINNET testNet.checked = false; From 0bfff8844e113d36a538d2bb0109541a3edc95e6 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 20:41:15 +0200 Subject: [PATCH 114/126] nettype comparison needs to be loose --- LeftPanel.qml | 5 ++--- components/CheckBox2.qml | 1 - main.qml | 4 ++-- wizard/WizardOptions.qml | 8 ++++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index acefa60f..b9577591 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -99,7 +99,6 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top - // @TODO: customDecorations? anchors.topMargin: (persistentSettings.customDecorations)? 50 : 0 RowLayout { @@ -121,8 +120,8 @@ Rectangle { Text { id: testnetLabel - visible: persistentSettings.nettype - text: qsTr("Testnet") + translationManager.emptyString + visible: persistentSettings.nettype != NetworkType.MAINNET + text: (persistentSettings.nettype == NetworkType.TESTNET ? qsTr("Testnet") : qsTr("Stagenet")) + translationManager.emptyString anchors.top: parent.top anchors.topMargin: 8 anchors.left: parent.left diff --git a/components/CheckBox2.qml b/components/CheckBox2.qml index 667a950f..367037c2 100644 --- a/components/CheckBox2.qml +++ b/components/CheckBox2.qml @@ -80,7 +80,6 @@ RowLayout { anchors.centerIn: parent source: "../images/whiteDropIndicator.png" rotation: checkBox.checked ? 180 * scaleRatio : 0 - verticalAlignment: parent.verticalCenter } } diff --git a/main.qml b/main.qml index 1d41db3b..5b1cabfb 100644 --- a/main.qml +++ b/main.qml @@ -73,7 +73,7 @@ ApplicationWindow { property bool remoteNodeConnected: false property bool androidCloseTapped: false; // Default daemon addresses - readonly property string localDaemonAddress : persistentSettings.nettype === NetworkType.MAINNET ? "localhost:18081" : persistentSettings.nettype === NetworkType.TESTNET ? "localhost:28081" : "localhost:38081" + readonly property string localDaemonAddress : persistentSettings.nettype == NetworkType.MAINNET ? "localhost:18081" : persistentSettings.nettype == NetworkType.TESTNET ? "localhost:28081" : "localhost:38081" property string currentDaemonAddress; property bool startLocalNodeCancelled: false @@ -232,7 +232,7 @@ ApplicationWindow { if(isIOS) wallet_path = moneroAccountsDir + wallet_path; // console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.walletPassword); - console.log("opening wallet at: ", wallet_path, ", network type: ", persistentSettings.nettype === NetworkType.MAINNET ? "mainnet" : persistentSettings.nettype === NetworkType.TESTNET ? "testnet" : "stagenet"); + console.log("opening wallet at: ", wallet_path, ", network type: ", persistentSettings.nettype == NetworkType.MAINNET ? "mainnet" : persistentSettings.nettype == NetworkType.TESTNET ? "testnet" : "stagenet"); walletManager.openWalletAsync(wallet_path, walletPassword, persistentSettings.nettype); } diff --git a/wizard/WizardOptions.qml b/wizard/WizardOptions.qml index 7a9ffa62..3579f147 100644 --- a/wizard/WizardOptions.qml +++ b/wizard/WizardOptions.qml @@ -250,11 +250,11 @@ ColumnLayout { fontSize: 16 * scaleRatio checkedIcon: "../images/checkedVioletIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" - checked: appWindow.persistentSettings.nettype === NetworkType.TESTNET; + checked: appWindow.persistentSettings.nettype == NetworkType.TESTNET; onClicked: { persistentSettings.nettype = testNet.checked ? NetworkType.TESTNET : NetworkType.MAINNET stageNet.checked = false; - console.log("Network type set to ", persistentSettings.nettype === NetworkType.TESTNET ? "Testnet" : "Mainnet") + console.log("Network type set to ", persistentSettings.nettype == NetworkType.TESTNET ? "Testnet" : "Mainnet") } } } @@ -269,11 +269,11 @@ ColumnLayout { fontSize: 16 * scaleRatio checkedIcon: "../images/checkedVioletIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" - checked: appWindow.persistentSettings.nettype === NetworkType.STAGENET; + checked: appWindow.persistentSettings.nettype == NetworkType.STAGENET; onClicked: { persistentSettings.nettype = stageNet.checked ? NetworkType.STAGENET : NetworkType.MAINNET testNet.checked = false; - console.log("Network type set to ", persistentSettings.nettype === NetworkType.STAGENET ? "Stagenet" : "Mainnet") + console.log("Network type set to ", persistentSettings.nettype == NetworkType.STAGENET ? "Stagenet" : "Mainnet") } } } From da2c6e8bc82d10a358748d83dabaa963ea64054e Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 20:41:42 +0200 Subject: [PATCH 115/126] Fixes javascript error; .trim() on undefined --- wizard/WizardDaemonSettings.qml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index bec134df..ac19aa87 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -183,7 +183,14 @@ ColumnLayout { opacity: localNode.checked id: bootstrapNodeEdit daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim() - daemonPortText: (persistentSettings.bootstrapNodeAddress.split(":")[1].trim() == "") ? "18081" : persistentSettings.bootstrapNodeAddress.split(":")[1] + daemonPortText: { + var node_split = persistentSettings.bootstrapNodeAddress.split(":"); + if(node_split.length == 2){ + (node_split[1].trim() == "") ? "18081" : node_split[1]; + } else { + return "" + } + } } } From 1d34d21a60ad83c2ebb814d06019db8e11fca306 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 20:43:52 +0200 Subject: [PATCH 116/126] Removing unused function get_color() --- components/HistoryTable.qml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index bcb869f2..660b89d9 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -81,14 +81,6 @@ ListView { } } - function get_color(i){ - if (i === 0){ - return "green"; - } else { - return "red"; - } - } - delegate: Rectangle { id: delegate property bool collapsed: index ? false : true From b35d60db2d8b7508127e8d365d22a82d58bd9dc6 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 20:44:47 +0200 Subject: [PATCH 117/126] Remove unused whatIsIcon.png related code --- components/Label.qml | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/components/Label.qml b/components/Label.qml index 79b83a5d..b77a614c 100644 --- a/components/Label.qml +++ b/components/Label.qml @@ -65,34 +65,4 @@ Item { color: fontColor onLinkActivated: item.linkActivated() } - -// @TODO: figure out significance of whatIsIcon.png, remove for now -// Image { -// id: icon -// anchors.verticalCenter: parent.verticalCenter -// anchors.left: label.right -// anchors.leftMargin: 5 * scaleRatio -// source: "../images/whatIsIcon.png" -// visible: appWindow.whatIsEnable -// } - -// MouseArea { -// anchors.fill: icon -// enabled: appWindow.whatIsEnable -// hoverEnabled: true -// onEntered: { -// icon.visible = false -// var pos = appWindow.mapFromItem(icon, 0, -15) -// tipItem.text = item.tipText -// tipItem.x = pos.x -// if(tipItem.height > 30) -// pos.y -= tipItem.height - 28 -// tipItem.y = pos.y -// tipItem.visible = true -// } -// onExited: { -// icon.visible = Qt.binding(function(){ return appWindow.whatIsEnable; }) -// tipItem.visible = false -// } -// } } From 9afaa7cf0f4ff3ba954a96b9bfd5f462040d452b Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 20:47:15 +0200 Subject: [PATCH 118/126] Avoid logging addresses and other sensitive data --- components/HistoryTable.qml | 2 +- components/HistoryTableInnerColumn.qml | 2 +- components/LineEdit.qml | 6 +++--- components/LineEditMulti.qml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index 660b89d9..2fce34f0 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -242,7 +242,7 @@ ListView { } onClicked: { if(parent.address){ - console.log(parent.address + " copied to clipboard"); + console.log("Address copied to clipboard"); clipboard.setText(parent.address); appWindow.showStatusMessage(qsTr("Address copied to clipboard"),3) } diff --git a/components/HistoryTableInnerColumn.qml b/components/HistoryTableInnerColumn.qml index 61c39deb..23ff766e 100644 --- a/components/HistoryTableInnerColumn.qml +++ b/components/HistoryTableInnerColumn.qml @@ -82,7 +82,7 @@ Rectangle{ } onClicked: { if(copyValue){ - console.log(copyValue + " copied to clipboard"); + console.log("Copied to clipboard"); clipboard.setText(copyValue); appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) } diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 1711ee56..115b92b3 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -119,9 +119,9 @@ Item { anchors.right: parent.right onClicked: { if (input.text.length > 0) { - console.log(input.text + " copied to clipboard") - clipboard.setText(input.text) - appWindow.showStatusMessage(qsTr("Copied to clipboard"),3) + console.log("Copied to clipboard"); + clipboard.setText(input.text); + appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3); } } visible: copyButton && input.text !== "" diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml index 8609aaa4..b013156a 100644 --- a/components/LineEditMulti.qml +++ b/components/LineEditMulti.qml @@ -86,7 +86,7 @@ ColumnLayout { anchors.rightMargin: labelButton.visible? 4 : 0 onClicked: { if (multiLine.text.length > 0) { - console.log(multiLine.text + " copied to clipboard"); + console.log("Copied to clipboard"); clipboard.setText(multiLine.text); appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3); } From 0b7966f625207968c99b86efd52dda5b1b0df1ae Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 21:12:10 +0200 Subject: [PATCH 119/126] Fixes transaction confirmation dialog and also makes sure you will not be able to transfer funds when the daemon is not up (to date) --- main.qml | 1 + pages/Transfer.qml | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/main.qml b/main.qml index 5b1cabfb..ba9064c2 100644 --- a/main.qml +++ b/main.qml @@ -611,6 +611,7 @@ ApplicationWindow { // here we show confirmation popup; transactionConfirmationPopup.title = qsTr("Please confirm transaction:\n") + translationManager.emptyString; + transactionConfirmationPopup.text = ""; transactionConfirmationPopup.text += (address === "" ? "" : (qsTr("\n\nAddress: ") + address)) + (paymentId === "" ? "" : (qsTr("\nPayment ID: ") + paymentId)) diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 8f212dd9..db46f04d 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -332,7 +332,13 @@ Rectangle { rightIcon: "../images/rightIcon.png" Layout.topMargin: 4 * scaleRatio text: qsTr("Send") + translationManager.emptyString - enabled : !appWindow.viewOnly && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype) + enabled : { + // Send button is enabled when: + // 1) Currently opened wallet is not view-only + // 2) There is no warning box displayed + // 3) The transactional information is correct + return !appWindow.viewOnly && warningText.text === '' && pageRoot.checkInformation(amountLine.text, addressLine.text, paymentIdLine.text, appWindow.persistentSettings.nettype); + } onClicked: { console.log("Transfer: paymentClicked") var priority = priorityModelV5.get(priorityDropdown.currentIndex).priority From d2d6e3ad6605ff4fced29384147654002d33fbaa Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 21:32:39 +0200 Subject: [PATCH 120/126] Fixes the placeholder texts for inputboxes in the wallet recovery wizard --- components/LineEdit.qml | 13 ++++++++++--- components/Style.qml | 1 + wizard/WizardManageWalletUI.qml | 18 +++++++++++++++++- wizard/WizardMemoTextInput.qml | 1 + 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 115b92b3..f7266d2c 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -32,9 +32,15 @@ import "." 1.0 Item { id: item property alias text: input.text + property alias placeholderText: placeholderLabel.text property bool placeholderCenter: false + property string placeholderFontFamily: Style.fontRegular.name + property bool placeholderFontBold: false property int placeholderFontSize: 18 * scaleRatio + property string placeholderColor: Style.defaultFontColor + property real placeholderOpacity: 0.25 + property alias validator: input.validator property alias readOnly : input.readOnly property alias cursorPosition: input.cursorPosition @@ -148,10 +154,11 @@ Item { else { return 10 * scaleRatio; } } - opacity: 0.25 - color: Style.defaultFontColor - font.family: Style.fontRegular.name + opacity: item.placeholderOpacity + color: item.placeholderColor + font.family: item.placeholderFontFamily font.pixelSize: placeholderFontSize * scaleRatio + font.bold: item.placeholderFontBold text: "" z: 3 } diff --git a/components/Style.qml b/components/Style.qml index ffe9c194..3b917f97 100644 --- a/components/Style.qml +++ b/components/Style.qml @@ -16,6 +16,7 @@ QtObject { property string inputBoxBackground: "black" property string inputBoxBackgroundError: "#FFDDDD" property string inputBoxColor: "white" + property string legacy_placeholderFontColor: "#BABABA" property string buttonBackgroundColor: "#FA6800" property string buttonBackgroundColorHover: "#E65E00" diff --git a/wizard/WizardManageWalletUI.qml b/wizard/WizardManageWalletUI.qml index 80407f0c..51eb8204 100644 --- a/wizard/WizardManageWalletUI.qml +++ b/wizard/WizardManageWalletUI.qml @@ -236,7 +236,11 @@ ColumnLayout { id: addressLine Layout.maximumWidth: 600 * scaleRatio Layout.minimumWidth: 200 * scaleRatio + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor placeholderText: qsTr("Account address (public)") + translationManager.emptyString + placeholderOpacity: 1.0 onTextUpdated: checkNextButton() borderColor: Qt.rgba(0, 0, 0, 0.15) backgroundColor: "white" @@ -248,7 +252,11 @@ ColumnLayout { id: viewKeyLine Layout.maximumWidth: 600 * scaleRatio Layout.minimumWidth: 200 * scaleRatio + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor placeholderText: qsTr("View key (private)") + translationManager.emptyString + placeholderOpacity: 1.0 onTextUpdated: checkNextButton() borderColor: Qt.rgba(0, 0, 0, 0.15) backgroundColor: "white" @@ -261,7 +269,11 @@ ColumnLayout { Layout.maximumWidth: 600 * scaleRatio Layout.minimumWidth: 200 * scaleRatio id: spendKeyLine + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor placeholderText: qsTr("Spend key (private)") + translationManager.emptyString + placeholderOpacity: 1.0 onTextUpdated: checkNextButton() borderColor: Qt.rgba(0, 0, 0, 0.15) backgroundColor: "white" @@ -277,7 +289,11 @@ ColumnLayout { Layout.fillWidth: true Layout.maximumWidth: 600 * scaleRatio Layout.minimumWidth: 200 * scaleRatio + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor placeholderText: qsTr("Restore height (optional)") + translationManager.emptyString + placeholderOpacity: 1.0 validator: IntValidator { bottom:0 } @@ -294,7 +310,7 @@ ColumnLayout { Layout.fillWidth: true Layout.topMargin: 20 * scaleRatio fontSize: 14 - fontFamily: "Ariel" + fontFamily: "Arial" fontColor: "#555555" text: qsTr("Your wallet is stored in") + ": " + fileUrlInput.text; } diff --git a/wizard/WizardMemoTextInput.qml b/wizard/WizardMemoTextInput.qml index 9611977d..a796fc3f 100644 --- a/wizard/WizardMemoTextInput.qml +++ b/wizard/WizardMemoTextInput.qml @@ -41,6 +41,7 @@ Column { font.pixelSize: 16 * scaleRatio anchors.margins: 8 * scaleRatio font.bold:true + font.family: "Arial" text: qsTr("Enter your 25 (or 24) word mnemonic seed") + translationManager.emptyString color: "#BABABA" visible: !memoTextInput.text/* && !parent.focus*/ From 408878290e848f02f942d3d698d4d038a797d181 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 21:34:30 +0200 Subject: [PATCH 121/126] nettype comparison needs to be loose --- main.qml | 2 +- wizard/WizardFinish.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main.qml b/main.qml index ba9064c2..4efbe71d 100644 --- a/main.qml +++ b/main.qml @@ -1018,7 +1018,7 @@ ApplicationWindow { property bool allow_background_mining : false property bool miningIgnoreBattery : true property var nettype: NetworkType.MAINNET - property string daemon_address: nettype === NetworkType.TESTNET ? "localhost:28081" : nettype === NetworkType.STAGENET ? "localhost:38081" : "localhost:18081" + property string daemon_address: nettype == NetworkType.TESTNET ? "localhost:28081" : nettype == NetworkType.STAGENET ? "localhost:38081" : "localhost:18081" property string payment_id property int restore_height : 0 property bool is_recovering : false diff --git a/wizard/WizardFinish.qml b/wizard/WizardFinish.qml index b0b39017..a25fc1c1 100644 --- a/wizard/WizardFinish.qml +++ b/wizard/WizardFinish.qml @@ -52,7 +52,7 @@ ColumnLayout { backgroundMiningEnabled = wizard.settings["allow_background_mining"] === true, backgroundMiningText = backgroundMiningEnabled ? qsTr("Enabled") : qsTr("Disabled"), nettype = appWindow.persistentSettings.nettype, - networkText = nettype === NetworkType.TESTNET ? qsTr("Testnet") : nettype === NetworkType.STAGENET ? qsTr("Stagenet") : qsTr("Mainnet"), + networkText = nettype == NetworkType.TESTNET ? qsTr("Testnet") : nettype == NetworkType.STAGENET ? qsTr("Stagenet") : qsTr("Mainnet"), restoreHeightEnabled = wizard.settings['restore_height'] !== undefined; return "
" From 6e503cd0e2a18dda13aa8f79786efc6c6c68eee4 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 21:45:16 +0200 Subject: [PATCH 122/126] Replace violet checkbox mark with a black one --- images/checkedBlackIcon.png | Bin 0 -> 15055 bytes qml.qrc | 1 + wizard/WizardDaemonSettings.qml | 2 +- wizard/WizardOptions.qml | 4 ++-- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100755 images/checkedBlackIcon.png diff --git a/images/checkedBlackIcon.png b/images/checkedBlackIcon.png new file mode 100755 index 0000000000000000000000000000000000000000..d73b70bfa6c02ee37af2e3f4694ea7972845c522 GIT binary patch literal 15055 zcmeI3&u`pB6vrnZP)S>x0_L<7I7JCcfD`k zeBT>?X5QEre_UU_baMK|X@tpWl6-5-hWvx{|BO zHFutDT8q0LxxBl)YV2+qnwdIZnJ)Eo8lXc0Ec7~U+t+*LR1{aI|HEb}B}83cYI^5h0h(i-w{oLP1L_xnf4my(Xx#l9OajQe;t9bVb%xS?C|B$~65~^30aL zQoYzuN3C*dGYDK=lDge)x|>Nm-iD-TnkLDrq^ctAA^JOZfP13tpN)eI;#7%mc$OPj zjxB_7ansoj%BfVCXn6FmtK$w6*?ylLr6~2VD=BGNnj|ufp~l_z+R@NVLn3X`A$H(X zoib79ZaRVEZ#svh9J&upOy{Il8|I!k-cDy?YCl-GN)hytPE`7kijwS`h+`Uh%kerms8}7mK_u7SC`qHnM9<->(&wGFO*ELAJCA#GWvZsv*FDi$)LtkEBZWMvT-2o_D55K~cPLoS*T z#9A#W9}8V|jP0;mXy|xjF&%@39}SCWtyV$JsA5KG(~hQwu%v! z2cftRw2p=~RQ6@o_;el(K^#9JKRicwlh~~CibF-c4iDlxt)PoNGP^-n$Wbakj(SiA z!=A`KSspy6mU7tiOx${JMb zcqNv?o0Cqfn64-sRgY4V#@a@i}aVVfKmn-B1E zTmT5$HaRXfAK>M<01&pxak2RTFUJLduuYDO%?Efn zE&zmWa$Iaaz{_y~AZ(N4V)FrBjtc-`n;aLL5Abqa00`UUxY&Gvm*WCJ*e1ut<^#MO z7XZRGIW9II;N`dg5Vpy2vH1Wm#|40}O^%Dr2Y5Ly0EBIFTx>qT%W(l9Y?I?+^8sFt z3jkr892c7p@N!%L2;1bi*nEJO;{rg~Cdb9*1H2p;0KztzxTZ(1a1xuox7npHXx^WD z`6PY0Q!o}+Y6$I~L+JX42>rEB&%YzIEhBWlfspg;Oomu5qF z=@@;3;hjdK@o;Z%uW{kdulx1CZ#;W<|Lbd?WRJ@i{&_I9e*N^_6ZN}m=RW%B$Lp7- z-n#YR=ef^Y*KVG={pF`;s@Bb^r=Ga+`f1_x?HL*v?e9N{X1=L@`|$X^Goih-uw1<} H*ZAOH_yR`V literal 0 HcmV?d00001 diff --git a/qml.qrc b/qml.qrc index 0be96187..8f00900f 100644 --- a/qml.qrc +++ b/qml.qrc @@ -204,5 +204,6 @@ components/CheckBox2.qml js/TxUtils.js images/warning.png + images/checkedBlackIcon.png diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index ac19aa87..69947f74 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -124,7 +124,7 @@ ColumnLayout { CheckBox { id: localNode text: qsTr("Start a node automatically in background (recommended)") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" + checkedIcon: "../images/checkedBlackIcon.png" background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio diff --git a/wizard/WizardOptions.qml b/wizard/WizardOptions.qml index 3579f147..ef9a4d1c 100644 --- a/wizard/WizardOptions.qml +++ b/wizard/WizardOptions.qml @@ -248,7 +248,7 @@ ColumnLayout { background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio - checkedIcon: "../images/checkedVioletIcon.png" + checkedIcon: "../images/checkedBlackIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" checked: appWindow.persistentSettings.nettype == NetworkType.TESTNET; onClicked: { @@ -267,7 +267,7 @@ ColumnLayout { background: "#FFFFFF" fontColor: "#4A4646" fontSize: 16 * scaleRatio - checkedIcon: "../images/checkedVioletIcon.png" + checkedIcon: "../images/checkedBlackIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" checked: appWindow.persistentSettings.nettype == NetworkType.STAGENET; onClicked: { From d98221ac56140b3e7a0b0b0348b6d06bfb9abb77 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 22:04:18 +0200 Subject: [PATCH 123/126] Fixes the placeholder texts for RemoteNodeEdit in the wallet creation wizard --- components/RemoteNodeEdit.qml | 20 +++++++++++++++++++- wizard/WizardDaemonSettings.qml | 17 +++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/components/RemoteNodeEdit.qml b/components/RemoteNodeEdit.qml index 4d44c156..6655e629 100644 --- a/components/RemoteNodeEdit.qml +++ b/components/RemoteNodeEdit.qml @@ -40,6 +40,14 @@ GridLayout { property alias daemonAddrLabelText: daemonAddr.labelText property alias daemonPortLabelText: daemonPort.labelText + // TODO: LEGACY; remove these placeHolder variables when + // the wizards get redesigned to the black-theme + property string placeholderFontFamily: Style.fontRegular.name + property bool placeholderFontBold: false + property int placeholderFontSize: 18 * scaleRatio + property string placeholderColor: Style.defaultFontColor + property real placeholderOpacity: 0.25 + property string lineEditBorderColor: Qt.rgba(0, 0, 0, 0.15) property string lineEditBackgroundColor: "white" property string lineEditFontColor: "black" @@ -55,6 +63,11 @@ GridLayout { id: daemonAddr Layout.fillWidth: true placeholderText: qsTr("Remote Node Hostname / IP") + translationManager.emptyString + placeholderFontFamily: root.placeholderFontFamily + placeholderFontBold: root.placeholderFontBold + placeholderFontSize: root.placeholderFontSize + placeholderColor: root.placeholderColor + placeholderOpacity: root.placeholderOpacity onEditingFinished: root.editingFinished() borderColor: lineEditBorderColor backgroundColor: lineEditBackgroundColor @@ -66,8 +79,13 @@ GridLayout { id: daemonPort Layout.fillWidth: true placeholderText: qsTr("Port") + translationManager.emptyString + placeholderFontFamily: root.placeholderFontFamily + placeholderFontBold: root.placeholderFontBold + placeholderFontSize: root.placeholderFontSize + placeholderColor: root.placeholderColor + placeholderOpacity: root.placeholderOpacity onEditingFinished: root.editingFinished() - + legacyWizardStyle: true borderColor: lineEditBorderColor backgroundColor: lineEditBackgroundColor fontColor: lineEditFontColor diff --git a/wizard/WizardDaemonSettings.qml b/wizard/WizardDaemonSettings.qml index 69947f74..c0a45e7a 100644 --- a/wizard/WizardDaemonSettings.qml +++ b/wizard/WizardDaemonSettings.qml @@ -152,6 +152,10 @@ ColumnLayout { Layout.preferredWidth: 200 * scaleRatio Layout.fillWidth: true text: persistentSettings.blockchainDataDir + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor + placeholderOpacity: 1.0 placeholderText: qsTr("(optional)") + translationManager.emptyString borderColor: Qt.rgba(0, 0, 0, 0.15) @@ -182,6 +186,12 @@ ColumnLayout { Layout.minimumWidth: 300 * scaleRatio opacity: localNode.checked id: bootstrapNodeEdit + + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor + placeholderOpacity: 1.0 + daemonAddrText: persistentSettings.bootstrapNodeAddress.split(":")[0].trim() daemonPortText: { var node_split = persistentSettings.bootstrapNodeAddress.split(":"); @@ -198,6 +208,7 @@ ColumnLayout { CheckBox { id: remoteNode text: qsTr("Connect to a remote node") + translationManager.emptyString + checkedIcon: "../images/checkedBlackIcon.png" Layout.topMargin: 20 * scaleRatio background: "#FFFFFF" fontColor: "#4A4646" @@ -218,6 +229,12 @@ ColumnLayout { property var rna: persistentSettings.remoteNodeAddress daemonAddrText: rna.search(":") != -1 ? rna.split(":")[0].trim() : "" daemonPortText: rna.search(":") != -1 ? (rna.split(":")[1].trim() == "") ? "18081" : persistentSettings.remoteNodeAddress.split(":")[1] : "" + + placeholderFontBold: true + placeholderFontFamily: "Arial" + placeholderColor: Style.legacy_placeholderFontColor + placeholderOpacity: 1.0 + lineEditBorderColor: Qt.rgba(0, 0, 0, 0.15) lineEditBackgroundColor: "white" lineEditFontColor: "black" From fb6b467dcb638161bf3eef1697aade3ee1ff75fb Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Tue, 27 Mar 2018 22:12:05 +0200 Subject: [PATCH 124/126] Removed unused property --- components/RemoteNodeEdit.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/components/RemoteNodeEdit.qml b/components/RemoteNodeEdit.qml index 6655e629..1f22956f 100644 --- a/components/RemoteNodeEdit.qml +++ b/components/RemoteNodeEdit.qml @@ -85,7 +85,6 @@ GridLayout { placeholderColor: root.placeholderColor placeholderOpacity: root.placeholderOpacity onEditingFinished: root.editingFinished() - legacyWizardStyle: true borderColor: lineEditBorderColor backgroundColor: lineEditBackgroundColor fontColor: lineEditFontColor From 011e30132417a92b9b0733435a9d92cb48292c3a Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Wed, 28 Mar 2018 21:12:00 +0200 Subject: [PATCH 125/126] Turn the SharedRing page black --- LeftPanel.qml | 2 +- pages/SharedRingDB.qml | 40 ++++++++++++---------------------------- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index b9577591..3136a5c2 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -467,7 +467,7 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.leftMargin: 16 - color: "#505050" + color: "#313131" height: 1 } // ------------- Shared RingDB tab --------------- diff --git a/pages/SharedRingDB.qml b/pages/SharedRingDB.qml index 53ea34e1..f1a002f6 100644 --- a/pages/SharedRingDB.qml +++ b/pages/SharedRingDB.qml @@ -37,7 +37,7 @@ import moneroComponents.Clipboard 1.0 Rectangle { - color: "#F0EEEE" + color: "transparent" Clipboard { id: clipboard } @@ -90,6 +90,7 @@ Rectangle { "This database is meant for use by Monero wallets as well as wallets from Monero clones which reuse the Monero keys.") + translationManager.emptyString wrapMode: Text.Wrap Layout.fillWidth: true; + color: Style.defaultFontColor } Text { @@ -117,6 +118,7 @@ Rectangle { sharedRingDBDialog.icon = StandardIcon.Information sharedRingDBDialog.open() } + color: Style.defaultFontColor } RowLayout { @@ -140,11 +142,8 @@ Rectangle { id: selectBlackballFileButton anchors.rightMargin: 17 * scaleRatio text: qsTr("Select") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: true + small: true onClicked: { loadBlackballFileDialog.open() } @@ -172,10 +171,7 @@ Rectangle { id: loadBlackballFileButton anchors.right: parent.right text: qsTr("Load") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + small: true enabled: !!appWindow.currentWallet onClicked: appWindow.currentWallet.blackballOutputs(walletManager.urlToLocalPath(loadBlackballFileDialog.fileUrl), true) } @@ -209,10 +205,7 @@ Rectangle { StandardButton { id: blackballButton text: qsTr("Blackball") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + small: true enabled: !!appWindow.currentWallet && validHex32(blackballOutputLine.text) onClicked: appWindow.currentWallet.blackballOutput(blackballOutputLine.text) } @@ -221,10 +214,7 @@ Rectangle { id: unblackballButton anchors.right: parent.right text: qsTr("Unblackball") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + small: true enabled: !!appWindow.currentWallet && validHex32(blackballOutputLine.text) onClicked: appWindow.currentWallet.unblackballOutput(blackballOutputLine.text) } @@ -255,6 +245,7 @@ Rectangle { sharedRingDBDialog.icon = StandardIcon.Information sharedRingDBDialog.open() } + color: Style.defaultFontColor } RowLayout { @@ -281,10 +272,7 @@ Rectangle { StandardButton { id: getRingButton text: qsTr("Get Ring") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" + small: true enabled: !!appWindow.currentWallet && validHex32(keyImageLine.text) onClicked: { var ring = appWindow.currentWallet.getRing(keyImageLine.text) @@ -322,7 +310,7 @@ Rectangle { id: setRingRelative checked: true text: qsTr("Relative") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" + checkedIcon: "../images/checkedBlackIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" } LineEdit { @@ -344,10 +332,6 @@ Rectangle { StandardButton { id: setRingButton text: qsTr("Set Ring") + translationManager.emptyString - shadowReleasedColor: "#FF4304" - shadowPressedColor: "#B32D00" - releasedColor: "#FF6C3C" - pressedColor: "#FF4304" enabled: !!appWindow.currentWallet && validHex32(keyImageLine.text) && validRing(setRingLine.text.trim(), setRingRelative.checked) onClicked: { var outs = setRingLine.text.trim() @@ -360,7 +344,7 @@ Rectangle { id: segregatePreForkOutputs checked: persistentSettings.segregatePreForkOutputs text: qsTr("I intend to spend on key-reusing fork(s)") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" + checkedIcon: "../images/checkedBlackIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" onClicked: { persistentSettings.segregatePreForkOutputs = segregatePreForkOutputs.checked @@ -373,7 +357,7 @@ Rectangle { id: keyReuseMitigation2 checked: persistentSettings.keyReuseMitigation2 text: qsTr("I might want to spend on key-reusing fork(s)") + translationManager.emptyString - checkedIcon: "../images/checkedVioletIcon.png" + checkedIcon: "../images/checkedBlackIcon.png" uncheckedIcon: "../images/uncheckedIcon.png" onClicked: { persistentSettings.keyReuseMitigation2 = keyReuseMitigation2.checked From b32b308332acf5521c935b056beecdc26180e214 Mon Sep 17 00:00:00 2001 From: Sander Ferdinand Date: Thu, 29 Mar 2018 21:30:09 +0200 Subject: [PATCH 126/126] Dont use displayAmount, use amount instead --- components/HistoryTable.qml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index 2fce34f0..87c9be76 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -165,18 +165,15 @@ ListView { font.pixelSize: 18 * scaleRatio font.bold: true text: { - var amount = (displayAmount * 1); // * 1 removes trailing zeros - - // sometimes, displayAmount is 0 - no idea why. - // in that case, we try to get the amount from - // the `destinations` string. - if(amount === 0){ - amount = TxUtils.destinationsToAmount(destinations); - amount = (amount *1); + var _amount = amount; + if(_amount === 0){ + // *sometimes* amount is 0, while the 'destinations string' + // has the correct amount, so we try to fetch it from that instead. + _amount = TxUtils.destinationsToAmount(destinations); + _amount = (_amount *1); } - // sometimes this destinations string also shows 0 at which point we run out of options. - return amount + " XMR"; + return _amount + " XMR"; } color: isOut ? "white" : "#2eb358" }

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