[GUI] Add name field and identicon to transfer form

This commit is contained in:
Nathan Hourt 2015-07-13 17:22:06 -04:00
parent 6fd566e6f7
commit 3ad1c1715d
11 changed files with 157 additions and 22 deletions

View file

@ -11,14 +11,25 @@
#include <fc/thread/thread.hpp>
#include <graphene/app/api.hpp>
#include <QCryptographicHash>
#include <QObject>
#include <QQmlListProperty>
#include <QtQml>
using boost::multi_index_container;
using namespace boost::multi_index;
Q_DECLARE_METATYPE(std::function<void()>)
class Crypto {
Q_GADGET
public:
Q_INVOKABLE QString sha256(QByteArray data) {
return QCryptographicHash::hash(data, QCryptographicHash::Sha256).toHex();
}
};
QML_DECLARE_TYPE(Crypto)
class Asset : public QObject {
Q_OBJECT

View file

@ -4,7 +4,6 @@
#include "ClientDataModel.hpp"
int main(int argc, char *argv[])
{
fc::thread::current().set_name( "main" );
@ -22,6 +21,9 @@ int main(int argc, char *argv[])
qmlRegisterType<GrapheneApplication>("Graphene.Client", 0, 1, "GrapheneApplication");
QQmlApplicationEngine engine;
QVariant crypto;
crypto.setValue(Crypto());
engine.rootContext()->setContextProperty("Crypto", crypto);
#ifdef NDEBUG
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
#else

1
programs/light_client/qml/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.depends

View file

@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.2
Rectangle {
id: greySheet
state: "HIDDEN"
color: Qt.rgba(0, 0, 0, showOpacity)
property real showOpacity: .5
property int animationTime: 300
@ -18,8 +19,11 @@ Rectangle {
/// Emitted when closed, following fade-out animation
signal closed
function showForm(formType, closedCallback) {
formLoader.sourceComponent = formType
function showForm(formType, params, closedCallback) {
if (formType.status === Component.Error)
console.log(formType.errorString())
formContainer.data = [formType.createObject(formContainer, params)]
if (closedCallback instanceof Function)
internal.callback = closedCallback
state = "SHOWN"
@ -35,12 +39,12 @@ Rectangle {
acceptedButtons: Qt.AllButtons
}
MouseArea {
anchors.fill: formLoader
anchors.fill: formContainer
acceptedButtons: Qt.AllButtons
onClicked: mouse.accepted = true
}
Loader {
id: formLoader
Item {
id: formContainer
anchors.centerIn: parent
width: parent.width / 2
height: parent.height / 2
@ -51,7 +55,7 @@ Rectangle {
name: "HIDDEN"
PropertyChanges {
target: greySheet
color: Qt.rgba(0, 0, 0, 0)
opacity: 0
enabled: false
}
StateChangeScript {
@ -63,10 +67,12 @@ Rectangle {
StateChangeScript {
name: "postHidden"
script: {
console.log("Post")
greySheet.closed()
formLoader.sourceComponent = undefined
formContainer.data = []
if (internal.callback instanceof Function)
internal.callback()
internal.callback = undefined
}
}
},
@ -74,7 +80,7 @@ Rectangle {
name: "SHOWN"
PropertyChanges {
target: greySheet
color: Qt.rgba(0, 0, 0, showOpacity)
opacity: 1
enabled: true
}
StateChangeScript {
@ -95,22 +101,28 @@ Rectangle {
Transition {
from: "HIDDEN"
to: "SHOWN"
ScriptAction { scriptName: "preShown" }
ColorAnimation {
target: greySheet
duration: animationTime
SequentialAnimation {
ScriptAction { scriptName: "preShown" }
PropertyAnimation {
target: greySheet
property: "opacity"
duration: animationTime
}
ScriptAction { scriptName: "postShown" }
}
ScriptAction { scriptName: "postShown" }
},
Transition {
from: "SHOWN"
to: "HIDDEN"
ScriptAction { scriptName: "preHidden" }
ColorAnimation {
target: greySheet
duration: animationTime
SequentialAnimation {
ScriptAction { scriptName: "preHidden" }
PropertyAnimation {
target: greySheet
property: "opacity"
duration: animationTime
}
ScriptAction { scriptName: "postHidden" }
}
ScriptAction { scriptName: "postHidden" }
}
]

View file

@ -0,0 +1,12 @@
pragma Singleton
import QtQuick 2.5
import QtQuick.Window 2.2
Item {
function mm(millimeters) {
return Screen.pixelDensity * millimeters
}
function cm(centimeters) {
return mm(centimeters * 10)
}
}

View file

@ -1,8 +1,60 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import "."
import "jdenticon/jdenticon-1.0.1.min.js" as Jdenticon
Rectangle {
anchors.fill: parent
Component.onCompleted: console.log("Made a transfer form")
Component.onDestruction: console.log("Destroyed a transfer form")
Column {
anchors.centerIn: parent
RowLayout {
Canvas {
id: identicon
width: Scaling.cm(2)
height: Scaling.cm(2)
contextType: "2d"
onPaint: {
if (nameField.text)
Jdenticon.draw(identicon, nameField.text)
else {
var context = identicon.context
context.reset()
var draw_circle = function(context, x, y, radius) {
context.beginPath()
context.arc(x, y, radius, 0, 2 * Math.PI, false)
context.fillStyle = "rgba(0, 0, 0, 0.1)"
context.fill()
}
var size = Math.min(identicon.height, identicon.width)
var centerX = size / 2
var centerY = size / 2
var radius = size/15
draw_circle(context, centerX, centerY, radius)
draw_circle(context, 2*radius, 2*radius, radius)
draw_circle(context, centerX, 2*radius, radius)
draw_circle(context, size - 2*radius, 2*radius, radius)
draw_circle(context, size - 2*radius, centerY, radius)
draw_circle(context, size - 2*radius, size - 2*radius, radius)
draw_circle(context, centerX, size - 2*radius, radius)
draw_circle(context, 2*radius, size - 2*radius, radius)
draw_circle(context, 2*radius, centerY, radius)
}
}
}
TextField {
id: nameField
Layout.fillWidth: true
onTextChanged: identicon.requestPaint()
}
}
}
}

View file

@ -0,0 +1,18 @@
// Jdenticon 1.0.1 | jdenticon.com | zlib licensed | (c) 2014-2015 Daniel Mester Pirttijärvi
/*Alteration to official Jdenticon code: make jdenticon() a variable in this context instead of a property of window*/
var jdenticon=function(){function h(){}function n(b,a,c,d){this.h=b;this.i=a;this.k=c;this.f=d}function u(b,a){this.e=b;this.g=a||n.q;b.beginPath()}function r(b,a,c){var d=(b="string"===typeof b?document.querySelector(b):b).getContext("2d");c=Math.min(b.width)*(1-2*(c===t?.08:c));d.save();d.clearRect(0,0,b.width,b.height);d.translate(0|(b.width-c)/2,0|(b.height-c)/2);v(d,a||b.getAttribute("data-jdenticon-hash"),c);d.restore()}function v(b,a,c){function d(b,c,d,e,g){e=e?parseInt(a.charAt(e),16):
0;c=c[parseInt(a.charAt(d),16)%c.length];var f;for(d=0;d<g.length;d++)f=new n(g[d][0]*p,g[d][1]*p,p,e++%4),f=new u(b,f),c(f,p,d),f.fill()}function e(a){if(0<=a.indexOf(k))for(var b=0;b<a.length;b++)if(0<=l.indexOf(a[b]))return!0}function g(a){b.fillStyle=m[l[a]].toString()}if(30>c)throw Error("Jdenticon cannot render identicons smaller than 30 pixels.");if(!/^[0-9a-f]{10,}$/i.test(a))throw Error("Invalid hash passed to Jdenticon.");c|=0;for(var p=2*(0|c/8),f=parseInt(a.substr(-7),16)/268435455,m=
[h.o(76,76,76),h.m(f,.6),h.o(230,230,230),h.m(f,.8),h.n(f,.4)],l=[],k,f=0;3>f;f++){k=parseInt(a.charAt(8+f),16)%m.length;if(e([0,4])||e([2,3]))k=1;l.push(k)}b.clearRect(0,0,c,c);g(0);d(b,w,2,3,[[1,0],[2,0],[2,3],[1,3],[0,1],[3,1],[3,2],[0,2]]);g(1);d(b,w,4,5,[[0,0],[3,0],[3,3],[0,3]]);g(2);d(b,y,1,null,[[1,1],[2,1],[2,2],[1,2]])}function q(){for(var b,a=document.getElementsByTagName("canvas"),c=0;c<a.length;c++)(b=a[c].getAttribute("data-jdenticon-hash"))&&r(a[c],b)}var t,x=window.jQuery;h.o=function(b,
a,c){var d=new h;d.p="rgba("+(b&255)+","+(a&255)+","+(c&255)+","+(void 0===t?1:void 0)+")";return d};h.n=function(b,a){var c=new h;c.p="hsla("+(360*b|0)+",50%,"+(100*a|0)+"%,"+(void 0===t?1:void 0)+")";return c};h.m=function(b,a){return h.n(b,1-[.95,1,1,1,.7,.8,.8][6*b+.5|0]*(1-a))};h.prototype={toString:function(){return this.p}};n.q=new n(0,0,0,0);n.prototype={j:function(b,a,c,d){var e=this.h+this.k,g=this.i+this.k;return 1===this.f?[e-a-(d||0),this.i+b]:2===this.f?[e-b-(c||0),g-a-(d||0)]:3===this.f?
[this.h+a,g-b-(c||0)]:[this.h+b,this.i+a]}};u.prototype={c:function(b,a){var c=a?-2:2,d=a?b.length-2:0,e=this.e;e.moveTo.apply(e,this.g.j(b[d],b[d+1]));for(d+=c;d<b.length&&0<=d;d+=c)e.lineTo.apply(e,this.g.j(b[d],b[d+1]));e.closePath()},d:function(b,a,c,d,e){var g=this.e;a=this.g.j(b,a,c,d);b=a[0];a=a[1];var h=c/2*.5522848,f=d/2*.5522848,m=b+c,l=a+d;c=b+c/2;var k=a+d/2;e&&(l=a,a+=d,f=-f);g.moveTo(b,k);g.bezierCurveTo(b,k-f,c-h,a,c,a);g.bezierCurveTo(c+h,a,m,k-f,m,k);g.bezierCurveTo(m,k+f,c+h,l,c,
l);g.bezierCurveTo(c-h,l,b,k+f,b,k);g.closePath()},a:function(b,a,c,d,e){this.c([b,a,b+c,a,b+c,a+d,b,a+d],e)},b:function(b,a,c,d,e,g){b=[b+c,a,b+c,a+d,b,a+d,b,a];b.splice((e||0)%4,2);this.c(b,g)},l:function(b,a,c,d,e){this.c([b+c/2,a,b+c,a+d/2,b+c/2,a+d,b,a+d/2],e)},fill:function(){this.e.fill()}};var y=[function(b,a){var c=.42*a;b.c([0,0,a,0,a,a-2*c,a-c,a,0,a])},function(b,a){var c=0|.4*a;b.b(a-c,a-2*c,c,2*c,1)},function(b,a){var c=0|a/3;b.a(c,c,a-c,a-c)},function(b,a){var c=0|.1*a,d=0|.25*a;b.a(d,
d,a-c-d,a-c-d)},function(b,a){var c=0|.15*a,d=0|.5*a;b.d(a-d-c,a-d-c,d,d)},function(b,a){var c=.1*a,d=4*c;b.a(0,0,a,a);b.c([d,d,a-c,d,d+(a-d-c)/2,a-c],!0)},function(b,a){b.b(0,0,a,a,0)},function(b,a){b.b(a/2,a/2,a/2,a/2,0)},function(b,a){b.a(0,0,a,a/2);b.a(0,a/2,a/2,a/2);b.b(a/2,a/2,a/2,a/2,1)},function(b,a){var c=0|.14*a,d=0|.35*a;b.a(0,0,a,a);b.a(d,d,a-d-c,a-d-c,!0)},function(b,a){var c=.12*a,d=3*c;b.a(0,0,a,a);b.d(d,d,a-c-d,a-c-d,!0)},function(b,a){b.b(a/2,a/2,a/2,a/2,3)},function(b,a){var c=.25*
a;b.a(0,0,a,a);b.l(c,c,a-c,a-c,!0)},function(b,a,c){var d=.4*a;a*=1.2;c||b.d(d,d,a,a)}],w=[function(b,a){b.b(0,0,a,a,0)},function(b,a){b.b(0,a/2,a,a/2,0)},function(b,a){b.l(0,0,a,a)},function(b,a){var c=a/6;b.d(c,c,a-2*c,a-2*c)}];q.drawIcon=v;q.update=r;x&&(x.fn.jdenticon=function(b,a){this.each(function(c,d){r(d,b,a)});return this});/*Alteration to official Jdenticon code: Removed call to schedule a render immediately on load*/return q}();
// The following functions were added, and are not part of the official Jdenticon code
/// @param canvas The canvas to draw on
/// @param data The data to generate an identicon for (this will be hashed to generate the identicon)
function draw(canvas, data) {
jdenticon.drawIcon(canvas.context, Crypto.sha256(data), Math.min(canvas.width, canvas.height))
}

View file

@ -0,0 +1,21 @@

Jdenticon
Copyright (c) 2014 Daniel Mester Pirttijärvi
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View file

@ -1,6 +1,7 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Window 2.2
import Qt.labs.settings 1.0
@ -47,9 +48,10 @@ ApplicationWindow {
anchors.centerIn: parent
Button {
text: "Transfer"
onClicked: formBox.showForm(Qt.createComponent("TransferForm.qml"), function() {
console.log("Closed form")
})
onClicked: formBox.showForm(Qt.createComponent("TransferForm.qml"), {},
function() {
console.log("Closed form")
})
}
TextField {
id: nameField
@ -73,6 +75,7 @@ ApplicationWindow {
})
}
}
}
FormBox {

View file

@ -3,6 +3,8 @@
<file>main.qml</file>
<file>TransferForm.qml</file>
<file>FormBox.qml</file>
<file>jdenticon/jdenticon-1.0.1.min.js</file>
<file>Scaling.qml</file>
</qresource>
</RCC>

View file

@ -0,0 +1 @@
singleton Scaling Scaling.qml