diff --git a/programs/light_client/ClientDataModel.hpp b/programs/light_client/ClientDataModel.hpp index 9aab8112..fd1a209e 100644 --- a/programs/light_client/ClientDataModel.hpp +++ b/programs/light_client/ClientDataModel.hpp @@ -11,14 +11,25 @@ #include #include +#include #include #include +#include using boost::multi_index_container; using namespace boost::multi_index; Q_DECLARE_METATYPE(std::function) +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 diff --git a/programs/light_client/main.cpp b/programs/light_client/main.cpp index ccd7a600..2c733daa 100644 --- a/programs/light_client/main.cpp +++ b/programs/light_client/main.cpp @@ -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("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 diff --git a/programs/light_client/qml/.gitignore b/programs/light_client/qml/.gitignore new file mode 100644 index 00000000..c6593022 --- /dev/null +++ b/programs/light_client/qml/.gitignore @@ -0,0 +1 @@ +*.depends diff --git a/programs/light_client/qml/FormBox.qml b/programs/light_client/qml/FormBox.qml index 7d50959c..1df969ef 100644 --- a/programs/light_client/qml/FormBox.qml +++ b/programs/light_client/qml/FormBox.qml @@ -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" } } ] diff --git a/programs/light_client/qml/Scaling.qml b/programs/light_client/qml/Scaling.qml new file mode 100644 index 00000000..52ab128e --- /dev/null +++ b/programs/light_client/qml/Scaling.qml @@ -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) + } +} diff --git a/programs/light_client/qml/TransferForm.qml b/programs/light_client/qml/TransferForm.qml index fdbc1515..deab6255 100644 --- a/programs/light_client/qml/TransferForm.qml +++ b/programs/light_client/qml/TransferForm.qml @@ -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() + } + } + } } diff --git a/programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js b/programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js new file mode 100755 index 00000000..dd0b1065 --- /dev/null +++ b/programs/light_client/qml/jdenticon/jdenticon-1.0.1.min.js @@ -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;dc)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;cmain.qml TransferForm.qml FormBox.qml + jdenticon/jdenticon-1.0.1.min.js + Scaling.qml diff --git a/programs/light_client/qml/qmldir b/programs/light_client/qml/qmldir new file mode 100644 index 00000000..79c7d88a --- /dev/null +++ b/programs/light_client/qml/qmldir @@ -0,0 +1 @@ +singleton Scaling Scaling.qml