Browse Source

Ready for beta

pull/45/head
dsc 4 months ago
parent
commit
8b1250030b
  1. 1
      src/CMakeLists.txt
  2. 10
      src/appcontext.cpp
  3. 6
      src/appcontext.h
  4. 2
      src/main.cpp
  5. 1
      src/utils/config.cpp
  6. 1
      src/utils/config.h
  7. 5
      src/utils/utils.cpp
  8. 1
      src/utils/utils.h
  9. 6
      src/utils/wsserver.cpp
  10. 39
      src/vr/assets/themes.json
  11. 46
      src/vr/main.cpp
  12. 42
      src/vr/main.h
  13. 171
      src/vr/main.qml
  14. 4
      src/vr/overlaycontroller.cpp
  15. 6
      src/vr/qml.qrc
  16. 7
      src/vr/qml/AboutPage.qml
  17. 69
      src/vr/qml/DashboardPage.qml
  18. 124
      src/vr/qml/SettingsPage.qml
  19. 96
      src/vr/qml/common/BackgroundGradientDebug.qml
  20. 36
      src/vr/qml/common/ImageMask.qml
  21. 14
      src/vr/qml/common/MyComboBox.qml
  22. 9
      src/vr/qml/common/MyDialogOkCancelPopup.qml
  23. 17
      src/vr/qml/common/MyDialogOkPopup.qml
  24. 24
      src/vr/qml/common/MyNumPadButton.qml
  25. 45
      src/vr/qml/common/MyNumPadSendAmount.qml
  26. 43
      src/vr/qml/common/MyPushButton.qml
  27. 2
      src/vr/qml/common/MySlider.qml
  28. 107
      src/vr/qml/common/MyStackViewPage.qml
  29. 6
      src/vr/qml/common/MyText.qml
  30. 4
      src/vr/qml/common/MyTextField.qml
  31. 31
      src/vr/qml/common/Style.qml
  32. 1
      src/vr/qml/common/qmldir
  33. 14
      src/vr/qml/wallet/HistoryTable.qml
  34. 20
      src/vr/qml/wallet/ReceivePage.qml
  35. 3
      src/vr/qml/wallet/WalletDashBoardPage.qml
  36. 4
      src/vr/qml/wallet/send/SendPage.qml
  37. 41
      src/vr/qml/wallet/send/SendPageDashboard.qml
  38. 44
      src/vr/qml/wallet/send/SendPageDashboardButton.qml
  39. 50
      src/vr/qml/wallet/send/SendPagePIN.qml
  40. 2
      src/vr/qml/wallet/send/SendPageQR.qml
  41. 109
      src/vr/qml/wallet/send/SendPageTransfer.qml

1
src/CMakeLists.txt

@ -186,6 +186,7 @@ target_compile_definitions(wowlet PUBLIC VR_API_PUBLIC)
if(QML)
qt5_import_qml_plugins(${PROJECT_NAME})
target_compile_definitions(wowlet PRIVATE HAS_QML=1)
endif()
target_compile_definitions(wowlet

10
src/appcontext.cpp

@ -829,9 +829,16 @@ void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QStr
// tx created, but not sent yet. ask user to verify first.
emit createTransactionSuccess(tx, address);
if(this->autoCommitTx) {
this->currentWallet->commitTransactionAsync(tx);
}
}
QString AppContext::getAddress(quint32 accountIndex, quint32 addressIndex) {
return this->currentWallet->address(accountIndex, addressIndex);
}
#if defined(HAS_OPENVR)
void AppContext::onAskReceivingPIN() {
// request new receiving PIN from wowlet-backend
if(this->currentWallet == nullptr)
@ -870,7 +877,6 @@ void AppContext::onLookupReceivingPIN(QString pin) {
QJsonDocument doc = QJsonDocument(obj);
this->ws->sendMsg(doc.toJson(QJsonDocument::Compact));
}
#endif
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());

6
src/appcontext.h

@ -78,6 +78,11 @@ public:
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
quint32 tx_mixin = static_cast<const quint32 &>(10);
QString seedLanguage = "English"; // 14 word `monero-seed` only has English
// turn this on if you want to auto commit tx's after they have
// been created. Caution while using this setting is advised. This
// probably also breaks the default QtWidgets GUI. It is meant for
// alternative users of AppContext.
bool autoCommitTx = false;
QNetworkAccessManager *network;
QNetworkAccessManager *networkClearnet;
@ -142,6 +147,7 @@ public slots:
void onPreferredFiatCurrencyChanged(const QString &symbol);
Q_INVOKABLE void onAskReceivingPIN();
Q_INVOKABLE void onLookupReceivingPIN(QString pin);
Q_INVOKABLE QString getAddress(quint32 accountIndex, quint32 addressIndex);
private slots:
void onWSNodes(const QJsonArray &nodes);

2
src/main.cpp

@ -114,7 +114,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
qRegisterMetaType<QVector<QString>>();
#ifdef QML
#ifdef HAS_QML
qputenv("QML_DISABLE_DISK_CACHE", "1");
#endif

1
src/utils/config.cpp

@ -25,6 +25,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::homeWidget,{QS("homeWidget"), "ccs"}},
{Config::donateBeg,{QS("donateBeg"), 1}},
{Config::skin,{QS("skin"), "light"}},
{Config::openVRSkin,{QS("openVRSkin"), "default"}},
{Config::preferredFiatCurrency,{QS("preferredFiatCurrency"), "USD"}},
{Config::blockExplorer,{QS("blockExplorer"), "explore.wownero.com"}},
{Config::walletDirectory,{QS("walletDirectory"), ""}},

1
src/utils/config.h

@ -28,6 +28,7 @@ public:
donateBeg,
autoOpenWalletPath,
skin,
openVRSkin,
preferredFiatCurrency,
blockExplorer,
walletDirectory,

5
src/utils/utils.cpp

@ -399,6 +399,11 @@ QLocale Utils::getCurrencyLocale(const QString &currencyCode) {
return locale;
}
double Utils::roundUp(double value, int decimal_places) {
const double multiplier = std::pow(10.0, decimal_places);
return std::ceil(value * multiplier) / multiplier;
}
QString Utils::amountToCurrencyString(double amount, const QString &currencyCode) {
QLocale locale = getCurrencyLocale(currencyCode);

1
src/utils/utils.h

@ -73,6 +73,7 @@ public:
static QLocale getCurrencyLocale(const QString &currencyCode);
static QString amountToCurrencyString(double amount, const QString &currencyCode);
static int maxLength(const QVector<QString> &array);
static double roundUp(double value, int decimal_places);
static QMap<QString, QLocale> localeCache;
static QString balanceFormat(quint64 balance);
static QTextCharFormat addressTextFormat(const SubaddressIndex &index);

6
src/utils/wsserver.cpp

@ -38,6 +38,9 @@ WSServer::WSServer(AppContext *ctx, const QHostAddress &host, const quint16 port
if (!m_pWebSocketServer->listen(QHostAddress::Any, port))
return;
// turn on auto tx commits
ctx->autoCommitTx = true;
qDebug() << "websocket server listening on port" << port;
connect(m_pWebSocketServer, &QWebSocketServer::newConnection, this, &WSServer::onNewConnection);
@ -364,8 +367,7 @@ void WSServer::onCreateTransactionError(const QString &message) {
}
void WSServer::onCreateTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address) {
// auto-commit all tx's
m_ctx->currentWallet->commitTransactionAsync(tx);
}
void WSServer::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList &txid) {

39
src/vr/assets/themes.json

@ -0,0 +1,39 @@
{
"default": {
"fontColor": "white",
"fontColorDimmed": "#cccccc",
"fontColorBright": "white",
"backgroundGradientStartColor": "#194f64",
"backgroundGradientStopColor": "#192e43",
"backgroundColor": "#1b2939",
"divideColor": "50ffffff",
"btnEnteredColor": "#aa3b689b",
"btnExitedColor": "#aa375c87",
"btnPressedColor": "#aa467dbb",
"btnTextHoverColor": "white",
"btnTextColor": "white",
"btnMainMenuBackground": "#aa3b689b",
"historyBackgroundColor": "#2c435d",
"historyBackgroundColorBright": "#406288",
"historyFontColorPlusAmount": "#00d304",
"historyFontColorMinAmount": "red"
},
"wownero": {
"fontColor": "#bd93f9",
"fontColorBright": "#e5d3ff",
"backgroundGradientStartColor": "#383a59",
"backgroundGradientStopColor": "#282a36",
"backgroundColor": "#282a36",
"divideColor": "50ffffff",
"btnEnteredColor": "#bd93f9",
"btnExitedColor": "#50000000",
"btnPressedColor": "#bd93f9",
"btnTextHoverColor": "black",
"btnTextColor": "#bcc2cd",
"btnMainMenuBackground": "#50000000",
"historyBackgroundColor": "#30314d",
"historyBackgroundColorBright": "#383a59",
"historyFontColorPlusAmount": "#00d304",
"historyFontColorMinAmount": "red"
}
}

46
src/vr/main.cpp

@ -32,8 +32,15 @@ namespace wowletvr {
WowletVR::WowletVR(AppContext *ctx, QCommandLineParser *parser, QObject *parent) :
QObject(parent), ctx(ctx), m_parser(parser) {
desktopMode = m_parser->isSet("openvr-debug");
AppContext::isQML = true;
m_pClipboard = QGuiApplication::clipboard();
desktopMode = m_parser->isSet("openvr-debug");
// Init QML themes
this->readThemes();
// turn on auto tx commits
ctx->autoCommitTx = true;
// write icon to disk so openvr overlay can refer to it
auto icon = ":/assets/images/wowlet.png";
@ -47,7 +54,7 @@ namespace wowletvr {
#ifdef Q_OS_WIN
if(desktopMode)
qputenv("QMLSCENE_DEVICE", "softwarecontext");
qputenv("QMLSCENE_DEVICE", "softwarecontext"); // virtualbox
#endif
qDebug() << "QMLSCENE_DEVICE: " << qgetenv("QMLSCENE_DEVICE");
qInfo() << "OPENSSL VERSION: " << QSslSocket::sslLibraryBuildVersionString();
@ -59,10 +66,11 @@ namespace wowletvr {
m_engine.rootContext()->setContextProperty("ctx", ctx);
// qmlRegisterType<clipboardAdapter>("moneroComponents.Clipboard", 1, 0, "Clipboard");
m_engine.rootContext()->setContextProperty("WowletVR", this);
qRegisterMetaType<NetworkType::Type>();
qmlRegisterType<NetworkType>("wowlet.NetworkType", 1, 0, "NetworkType");
qmlRegisterUncreatableType<WalletKeysFiles>("wowlet.WalletKeysFiles", 1, 0, "WalletKeysFiles", "lol");
qmlRegisterUncreatableType<WalletKeysFiles>("wowlet.WalletKeysFiles", 1, 0, "WalletKeysFiles", "WalletKeysFiles can't be instantiated directly");
qmlRegisterUncreatableType<Wallet>("wowlet.Wallet", 1, 0, "Wallet", "Wallet can't be instantiated directly");
qmlRegisterType<WalletManager>("wowlet.WalletManager", 1, 0, "WalletManager");
@ -82,11 +90,11 @@ namespace wowletvr {
if(!desktopMode) {
if(!openvr_init::initializeOpenVR(openvr_init::OpenVrInitializationType::Overlay))
throw std::runtime_error("Error: initializeOpenVR()");
m_controller = new wowletvr::OverlayController(desktopMode, m_engine);
m_engine.rootContext()->setContextProperty("OverlayController", m_controller);
}
m_controller = new wowletvr::OverlayController(desktopMode, m_engine);
m_engine.rootContext()->setContextProperty("OverlayController", m_controller);
auto widgetUrl = QUrl(QStringLiteral("qrc:///main"));
m_component = new QQmlComponent(&m_engine, widgetUrl);
@ -116,8 +124,30 @@ namespace wowletvr {
m_controller->SetWidget(quickObjItem, displayName, appKey, iconPath.toStdString());
}
WowletVR::~WowletVR() {
int weoignwieog = 1;
void WowletVR::readThemes() {
theme_names = QVariantList();
themes = QVariantMap();
auto lol = Utils::fileOpen(":/qml_themes.json");
auto doc = QJsonDocument::fromJson(lol);
QJsonObject obj = doc.object();
foreach(const QString &themeName, obj.keys()) {
theme_names << themeName;
QJsonValue value = obj.value(themeName);
QJsonObject theme = value.toObject();
QVariantMap map;
foreach(const QString &key, theme.keys()) {
map[key] = theme.value(key).toString();
}
themes[themeName] = map;
}
};
WowletVR::~WowletVR() {
// bla
}
}

42
src/vr/main.h

@ -8,9 +8,13 @@
#include <QQmlError>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QGuiApplication>
#include <QClipboard>
#include <globals.h>
#include "overlaycontroller.h"
#include "appcontext.h"
#include "utils/config.h"
namespace wowletvr {
@ -20,9 +24,46 @@ namespace wowletvr {
explicit WowletVR(AppContext *ctx, QCommandLineParser *cmdargs, QObject *parent = nullptr);
~WowletVR() override;
void readThemes();
void render();
QList<QQmlError> errors;
QVariantList theme_names;
QVariantMap themes;
Q_INVOKABLE QVariantMap getThemes() {
return themes;
}
Q_INVOKABLE QString getCurrentTheme() {
return config()->get(Config::openVRSkin).toString();
}
Q_INVOKABLE void setCurrentTheme(QString theme) {
config()->set(Config::openVRSkin, theme);
}
Q_INVOKABLE double cdiv(double amount) { return amount / globals::cdiv; }
Q_INVOKABLE double add(double x, double y) const { return Utils::roundUp(x + y, 4); } // round ceil 4 decimals
Q_INVOKABLE double sub(double x, double y) const { return Utils::roundUp(x - y, 4); } // round ceil 4 decimals
Q_INVOKABLE void onCreateTransaction(const QString &address, const QString &amount_str, const QString description, bool all) {
auto amount = WalletManager::amountFromString(amount_str);
ctx->onCreateTransaction(address, amount, description, false);
}
Q_INVOKABLE void setClipboard(const QString &text) {
m_pClipboard->setText(text, QClipboard::Clipboard);
m_pClipboard->setText(text, QClipboard::Selection);
}
Q_INVOKABLE QString amountToFiat(double amount) {
auto preferredFiatCurrency = config()->get(Config::preferredFiatCurrency).toString();
if (amount <= 0) return QString("0.00 %1").arg(preferredFiatCurrency);
double conversionAmount = AppContext::prices->convert("WOW", preferredFiatCurrency, amount);
return QString("~%1 %2").arg(QString::number(conversionAmount, 'f', 2), preferredFiatCurrency);
}
private:
AppContext *ctx;
@ -31,6 +72,7 @@ namespace wowletvr {
QQmlComponent *m_component;
bool desktopMode = false;
wowletvr::OverlayController *m_controller;
QClipboard *m_pClipboard;
};
}

171
src/vr/main.qml

@ -5,6 +5,7 @@ import QtGraphicalEffects 1.0
import QtQuick.Window 2.0
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtGraphicalEffects 1.0
import "."
@ -18,16 +19,58 @@ Rectangle {
id: appWindow
width: 1600
height: 800
color: "#1b2939"
color: "transparent"
property var themes: {}
property string theme: "wownero"
signal initTheme();
// Components that have been dynamically created need to redraw
// after theme change (such as Repeater{}, Flow{} items, etc) so
// that the changes propogate.
signal redraw();
// For gradient background
property int start_x: 0
property int start_y: 64
property int end_x: 1080
property int end_y: 416
property double gradientTicks: 1.0;
LinearGradient {
anchors.fill: parent
start: Qt.point(start_x, start_y)
end: Qt.point(end_x, end_y)
gradient: Gradient {
GradientStop { position: 0.0; color: Style.backgroundGradientStartColor }
GradientStop { position: 1.0; color: Style.backgroundGradientStopColor }
}
}
Timer {
// animates the gradient background a bit.
id: gradientBackgroundTimer
repeat: true
interval: 10
triggeredOnStart: true
onTriggered: {
appWindow.gradientTicks += 0.004; // speed
let newx = ((1080 - 200) * Math.sin(appWindow.gradientTicks) + 1080 + 200) / 2;
appWindow.end_x = newx;
}
}
property var currentWallet;
property bool disconnected: currentWallet ? currentWallet.disconnected : false
property string walletTitle: "long wallet name"
property string walletTitle: "placeholder"
property string walletPath: ""
property string statusText: "Idle"
property string balanceFormatted: "Balance: 25928.9543 WOW"
property string balanceFormatted: "Balance: 0.0 WOW"
property bool wsConnected: false
property int connectionStatus: Wallet.ConnectionStatus_Disconnected;
signal aboutClicked();
property var balance: 0.0
property var spendable: 0.0
@ -36,6 +79,10 @@ Rectangle {
visible: false
}
property SettingsPage settingsPage: SettingsPage {
visible: false
}
property AboutPage aboutPage: AboutPage {
visible: false
}
@ -66,13 +113,14 @@ Rectangle {
Layout.rightMargin: 16
MyText {
fontColor: Style.fontColorBright
text: "Password: "
}
MyTextField {
id: walletOpenPassword
keyBoardUID: 591
color: "#cccccc"
color: Style.fontColorDimmed
text: ""
Layout.fillWidth: true
font.pointSize: 20
@ -110,13 +158,14 @@ Rectangle {
Layout.rightMargin: 16
MyText {
fontColor: Style.fontColorBright
text: "Name: "
}
MyTextField {
id: newWalletName
keyBoardUID: 590
color: "#cccccc"
color: Style.fontColorDimmed
text: ""
Layout.fillWidth: true
font.pointSize: 20
@ -132,13 +181,14 @@ Rectangle {
Layout.rightMargin: 16
MyText {
fontColor: Style.fontColorBright
text: "Password: "
}
MyTextField {
id: newWalletPassword
keyBoardUID: 592
color: "#cccccc"
color: Style.fontColorDimmed
text: ""
Layout.fillWidth: true
font.pointSize: 20
@ -152,7 +202,7 @@ Rectangle {
Layout.topMargin: 20
Layout.leftMargin: 16
fontSize: 16
fontColor: "#cccccc"
fontColor: Style.fontColorDimmed
text: "The password field is optional."
}
@ -174,8 +224,35 @@ Rectangle {
}
}
// About/credits button
Rectangle {
visible: mainView.currentItem == dashboardPage
color: "transparent"
width: 140
height: 60
anchors.bottom: parent.bottom
anchors.right: parent.right
MyText {
text: "Credits"
fontSize: 12
opacity: 0.3
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
fontColor: Style.fontColor
}
MouseArea {
anchors.fill: parent
onClicked: {
aboutClicked();
}
}
}
StackView {
id: mainView
visible: true
anchors.fill: parent
pushEnter: Transition {
@ -225,6 +302,54 @@ Rectangle {
ctx.initTor();
ctx.initWS();
}
// Start animating the background
gradientBackgroundTimer.start();
try {
appWindow.themes = WowletVR.getThemes();
appWindow.theme = WowletVR.getCurrentTheme();
}
catch(err) {
// for debugging purposes - do not change color codes here, use themes.json instead.
appWindow.themes = {
"default": {
"fontColor": "white",
"fontColorDimmed": "#cccccc",
"fontColorBright": "#white",
"backgroundGradientStartColor": "#194f64",
"backgroundGradientStopColor": "#192e43",
},
"wownero": {
"fontColor": "#bd93f9",
"fontColorDimmed": "#cccccc",
"fontColorBright": "#e5d3ff",
"backgroundGradientStartColor": "#383a59",
"backgroundGradientStopColor": "#282a36",
}
}
}
appWindow.changeTheme(appWindow.theme);
appWindow.initTheme();
}
function changeTheme(theme) {
console.log("changeTheme", theme);
for (var key in appWindow.themes[theme]){
let val = appWindow.themes[theme][key];
if(Style.hasOwnProperty(key))
Style[key] = val;
}
if(appWindow.theme != theme) {
appWindow.theme = theme;
try { WowletVR.setCurrentTheme(theme); }
catch(err) {}
}
appWindow.redraw();
}
Connections {
@ -251,17 +376,6 @@ Rectangle {
appWindow.currentWallet.connectionStatusChanged.connect(onConnectionStatusChanged);
}
// function onWalletOpened(Wallet *wallet) {
// currentWallet.moneySpent.connect(onWalletMoneySent)
// currentWallet.moneyReceived.connect(onWalletMoneyReceived)
// currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived)
// currentWallet.transactionCreated.connect(onTransactionCreated)
// currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
// currentWallet.transactionCommitted.connect(onTransactionCommitted);
// middlePanel.paymentClicked.connect(handlePayment);
// }
function onBlockchainSync(height, target) {
let blocks = (target > height) ? (target - height) : "?";
let heightText = "Blockchain sync: " + blocks + " blocks remaining";
@ -277,8 +391,6 @@ Rectangle {
function onWalletClosed() {
console.log("onWalletClosed");
appWindow.currentWallet.connectionStatusChanged.disconnect(onConnectionStatusChanged);
appWindow.walletTitle = "";
appWindow.balanceFormatted = "";
appWindow.balance = 0.0;
@ -291,8 +403,9 @@ Rectangle {
}
function onBalanceUpdated(balance, spendable) {
appWindow.balance = balance;
appWindow.spendable = spendable;
appWindow.balance = WowletVR.cdiv(balance);
appWindow.spendable = WowletVR.cdiv(spendable);
console.log("onBalanceUpdated", appWindow.spendable);
}
function onWalletOpenedError(err) {
@ -327,8 +440,6 @@ Rectangle {
}
function onCreateTransactionSuccess(tx, address) { // PendingTransaction
// auto-commit all tx's
//m_ctx->currentWallet->commitTransactionAsync(tx);
console.log("onCreateTransactionSuccess", address)
}
@ -337,6 +448,18 @@ Rectangle {
}
}
Connections {
target: OverlayController
function onDashboardDeactivated() {
gradientBackgroundTimer.stop();
}
function onDashboardActivated() {
gradientBackgroundTimer.start();
}
}
function onConnectionStatusChanged(status) {
console.log("onConnectionStatusChanged", status)
appWindow.connectionStatus = status;

4
src/vr/overlaycontroller.cpp

@ -73,7 +73,7 @@ OverlayController::OverlayController(bool desktopMode, QQmlEngine& qmlEngine) :
m_offscreenSurface.create();
m_openGLContext.makeCurrent( &m_offscreenSurface );
if (!vr::VROverlay()){
if (!vr::VROverlay() && !desktopMode){
QMessageBox::critical(nullptr, "Wowlet VR Overlay", "Is OpenVR running?");
throw std::runtime_error( std::string( "No Overlay interface" ) );
}
@ -418,6 +418,8 @@ void OverlayController::mainEventLoop() {
void OverlayController::showKeyboard(QString existingText, unsigned long userValue)
{
if(m_desktopMode) return;
vr::VROverlay()->ShowKeyboardForOverlay(
m_ulOverlayHandle,
vr::k_EGamepadTextInputModeNormal,

6
src/vr/qml.qrc

@ -39,6 +39,7 @@
<file alias="status_connected">assets/img/status_connected.svg</file>
<file alias="status_waiting">assets/img/status_waiting.svg</file>
<file alias="status_lagging">assets/img/status_lagging.svg</file>
<file alias="qml_themes.json">assets/themes.json</file>
<file alias="main">main.qml</file>
<file>qml/common/HourComboBox.qml</file>
@ -56,12 +57,15 @@
<file>qml/common/MyText.qml</file>
<file>qml/common/MyToggleButton.qml</file>
<file>qml/common/MyPushButton.qml</file>
<file>qml/common/Style.qml</file>
<file>qml/common/qmldir</file>
<file>qml/common/MySlider.qml</file>
<file>qml/common/mainwidget.qml</file>
<file>qml/common/MyNumPad.qml</file>
<file>qml/common/MyNumPadButton.qml</file>
<file>qml/common/MyNumPadSendAmount.qml</file>
<file>qml/common/MyStackViewPage.qml</file>
<file>qml/common/ImageMask.qml</file>
<file>qml/wallet/ReceivePage.qml</file>
<file>qml/wallet/HistoryTable.qml</file>
<file>qml/wallet/WalletDashBoardPage.qml</file>
@ -69,9 +73,11 @@
<file>qml/DashboardPage.qml</file>
<file>qml/WalletPage.qml</file>
<file>qml/AboutPage.qml</file>
<file>qml/SettingsPage.qml</file>
<file>qml/wallet/send/SendPage.qml</file>
<file>qml/wallet/send/SendPageDashboard.qml</file>
<file>qml/wallet/send/SendPageDashboardButton.qml</file>
<file>qml/wallet/send/SendPageNavBack.qml</file>
<file>qml/wallet/send/SendPagePIN.qml</file>
<file>qml/wallet/send/SendPageQR.qml</file>

7
src/vr/qml/AboutPage.qml

@ -28,8 +28,6 @@ ColumnLayout {
source: "qrc:/illuminati"
}
}
ColumnLayout {
@ -39,11 +37,9 @@ ColumnLayout {
Layout.leftMargin: 40
Layout.rightMargin: 40
Layout.fillWidth: true
text: "Wowlet VR is an alternative QML interface for wowlet and was made over a 4 week period whilst eating lots of pizzas. It is the world's first cryptocurrency wallet with support for VR. Wowlet is Free and open-source (BSD-3) software and the source code can be studied on git.wownero.com/wowlet/wowlet"
text: "Wowlet VR is an alternative QML interface for wowlet and was made over a 4 week period eating lots of pizzas. It is the world's first cryptocurrency wallet with support for VR. Wowlet is Free and open-source (BSD-3) software and the source code can be studied on git.wownero.com/wowlet/wowlet"
wrap: true
}
}
}
@ -52,6 +48,7 @@ ColumnLayout {
Layout.rightMargin: 40
Layout.fillWidth: true
text: "Greetings: matzman666, qvqc, ez, Gatto, cisme, wowario, lza_menace, jwinterm, nioc, asymptotically, azy, selsta, kico, laura, thrmo, rottensox, solar, bl4sty, scoobybejesus"
fontSize: 14
wrap: true
}

69
src/vr/qml/DashboardPage.qml

@ -14,9 +14,6 @@ ColumnLayout {
height: 800
property var walletList: [];
property string enteredColor: "#365473"
property string exitedColor: "#2c435d"
property string pressedColor: "#406288"
Layout.fillWidth: true
Layout.fillHeight: true
@ -48,13 +45,13 @@ ColumnLayout {
anchors.right: parent.right
anchors.bottom: parent.bottom
fontSize: 14
text: "Version 0.1 (Qt " + qtRuntimeVersion + ")"
text: "Version beta (Qt " + qtRuntimeVersion + ")"
}
}
}
Rectangle {
color: "#cccccc"
color: Style.dividerColor
height: 1
Layout.topMargin: 10
Layout.fillWidth: true
@ -80,29 +77,28 @@ ColumnLayout {
model: walletList
delegate: Rectangle {
// inherited roles from walletKeysFilesModel:
// index, fileName, modified, accessed, path, networktype, address
// @TODO: maybe enforce networktype === 0 (mainnet)
id: item
property var currentItem: walletList[index]
property bool about: currentItem.hasOwnProperty("about")
property bool settings: currentItem.hasOwnProperty("settings")
property bool create: currentItem.hasOwnProperty("create")
color: root.enteredColor
height: 256
width: 256
property bool exit: currentItem.hasOwnProperty("exit")
color: Style.btnMainMenuBackground
height: 242
width: 232
Image {
width: 182
height: 182
width: 158
height: 158
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
source: {
if(about) {
if(settings) {
return "qrc:/hypnotoad";
} else if(create) {
return "qrc:/wizard";
} else if(exit) {
return "qrc:/tutorial";
} else {
return "qrc:/chest";
}
@ -110,12 +106,15 @@ ColumnLayout {
}
Text {
color: "white"
id: btnText
color: Style.btnTextColor
text: {
if(about) {
return "About";
if(settings) {
return "Settings";
} else if(create) {
return "Create wallet";
} else if(exit) {
return "Exit";
} else {
return currentItem['fileName'].replace(".keys", "");
}
@ -133,16 +132,20 @@ ColumnLayout {
cursorShape: Qt.PointingHandCursor
onEntered: {
parent.color = root.pressedColor
parent.color = Style.btnPressedColor;
btnText.color = Style.btnTextHoverColor;
}
onExited: {
parent.color = root.enteredColor;
parent.color = Style.btnMainMenuBackground;
btnText.color = Style.btnTextColor;
}
onClicked: {
if(about) {
mainView.push(aboutPage);
if(settings) {
mainView.push(settingsPage);
} else if(create) {
createWalletDialog.openPopup();
} else if(exit) {
OverlayController.exitApp();
} else {
appWindow.walletPath = currentItem['path'];
ctx.onOpenWallet(currentItem['path'], "");
@ -161,6 +164,7 @@ ColumnLayout {
function onPageCompleted(previousView){
console.log("list wallets");
root.walletList = [];
let wallets = [];
if(typeof ctx !== 'undefined')
wallets = ctx.listWallets();
@ -168,16 +172,27 @@ ColumnLayout {
let _walletList = [];
for(var i = 0; i != wallets.length; i++) {
if(i == 8) // draw 10 items at any time
if(i == 9) // draw 10 items at any time
break;
_walletList.push(wallets[i]);
}
_walletList.push({"create": true});
_walletList.push({"about": true});
_walletList.push({"settings": true});
_walletList.push({"exit": true});
root.walletList = _walletList;
}
}
// OverlayController.exitApp();
Connections {
target: appWindow
function onAboutClicked() {
mainView.push(aboutPage);
}
function onRedraw() {
console.log("hooray");
onPageCompleted(1);
}
}
}

124
src/vr/qml/SettingsPage.qml

@ -0,0 +1,124 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.2
import "."
import "common"
ColumnLayout {
id: root
property bool needsRestart: false
spacing: 30
Layout.fillHeight: true
Layout.fillWidth: true
ColumnLayout {
spacing: 30
Layout.topMargin: 40
Layout.fillWidth: true
Layout.leftMargin: 40
Layout.rightMargin: 40
MyText {
Layout.fillWidth: true
fontSize: 26
text: "Settings"
wrap: true
}
RowLayout {
spacing: 30
MyText {
text: "Theme"
}
MyComboBox {
id: themeCombo
Layout.preferredHeight: 60
Layout.preferredWidth: 378
displayText: "-"
model: [""]
delegate: ItemDelegate {
width: parent.width
text: modelData.text
hoverEnabled: true
contentItem: MyText {
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: parent.text
color: parent.enabled ? Style.fontColor : Style.fontColorDimmed
}
background: Rectangle {
color: parent.pressed ? "#406288" : (parent.hovered ? "#365473" : "#2c435d")
}
}
onCurrentIndexChanged: {
displayText = themeCombo.model[currentIndex]["text"];
if(displayText !== "" && displayText !== appWindow.theme) {
appWindow.changeTheme(displayText);
needsRestart = true;
}
}
}
}
}
Component.onCompleted: {
}
MyDialogOkPopup {
id: restartPopup
dialogTitle: "Restart required"
dialogText: "WowletVR needs a restart to load the theme. Exiting."
onClosed: {
OverlayController.exitApp();
}
}
MyPushButton {
text: "Back"
Layout.leftMargin: 40
Layout.preferredWidth: 220
onClicked: {
if(root.needsRestart) {
restartPopup.open();
} else {
mainView.pop();
}
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
function onPageCompleted(previousView){
}
Connections {
target: appWindow
function onInitTheme() {
// populate combobox
let themeComboBoxItems = [{ value: 0, text: ""}];
for (let _theme in appWindow.themes){
if (!appWindow.themes.hasOwnProperty(_theme))
continue;
themeComboBoxItems.push({ value: 0, text: _theme });
}
themeCombo.model = themeComboBoxItems;
themeCombo.displayText = appWindow.theme;
}
}
}
// OverlayController.exitApp();

96
src/vr/qml/common/BackgroundGradientDebug.qml

@ -0,0 +1,96 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.2
import "."
// This file is used to debug the background gradient animation and can be ignored.
ColumnLayout {
property int start_x: 0
property int start_y: 64
property int end_x: 1080
property int end_y: 416
visible: false
width: parent.width
height: parent.height
MyText {
fontColor: "red"
text: "start_x: " + start_x
}
MySlider {
from: 0
to: 1600
value: start_x
Layout.fillWidth: true
Layout.preferredHeight: 40
onValueChanged: {
appWindow.start_x = value;
}
}
MyText {
fontColor: "red"
text: "start_y: " + start_y
}
MySlider {
from: 0
to: 1600
value: start_y
Layout.fillWidth: true
Layout.preferredHeight: 40
onValueChanged: {
appWindow.start_y = value;
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
MyText {
fontColor: "red"
text: "end_x: " + end_x
}
MySlider {
from: 0
to: 1600
value: end_x
Layout.fillWidth: true
Layout.preferredHeight: 40
onValueChanged: {
appWindow.end_x = value;
}
}
MyText {
fontColor: "red"
text: "end_y: " + end_y
}
MySlider {
from: 0
to: 1600
value: end_y
Layout.fillWidth: true
Layout.preferredHeight: 40
onValueChanged: {
appWindow.end_y = value;
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
}

36
src/vr/qml/common/ImageMask.qml

@ -0,0 +1,36 @@
// Copyright (c) 2014-2019, The Monero Project
import QtQuick 2.9
import QtGraphicalEffects 1.0
Item {
// Use this component to color+opacity change images with transparency (svg/png)
// Does not work in low graphics mode, use fontAwesome fallback option.
id: root
property string image: ""
property string color: ""
property alias svgMask: svgMask
property alias imgMockColor: imgMockColor
width: 0
height: 0
Image {
id: svgMask
source: root.image
sourceSize.width: root.width
sourceSize.height: root.height
smooth: true
mipmap: true
visible: false
}
ColorOverlay {
id: imgMockColor
anchors.fill: root
source: svgMask
color: root.color
}
}

14
src/vr/qml/common/MyComboBox.qml

@ -14,7 +14,7 @@ ComboBox {
leftPadding: 0
rightPadding: parent.indicator.width + parent.spacing
text: parent.displayText
horizontalAlignment: Text.AlignLeft
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
@ -27,7 +27,7 @@ ComboBox {
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: parent.text
color: parent.enabled ? "#ffffff" : "#909090"
color: parent.enabled ? Style.fontColor : Style.fontColorDimmed
}
background: Rectangle {
color: parent.pressed ? "#406288" : (parent.hovered ? "#365473" : "#2c435d")
@ -61,11 +61,11 @@ ComboBox {
}
}
onActivated: {
if (activeFocus) {
MyResources.playActivationSound()
}
}
// onActivated: {
// if (activeFocus) {
// MyResources.playActivationSound()
// }
// }
Component.onCompleted: {
popup.background.color = "#2c435d"

9
src/vr/qml/common/MyDialogOkCancelPopup.qml

@ -2,6 +2,8 @@ import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import "."
Popup {
id: myDialogPopup
@ -18,6 +20,7 @@ Popup {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: true
fontColor: Style.fontColor
}
property bool okClicked: false
@ -37,8 +40,8 @@ Popup {
implicitHeight: dialogHeight
anchors.centerIn: parent
radius: 24
color: "#1b2939"
border.color: "#cccccc"
color: Style.backgroundColor
border.color: Style.fontColorDimmed
border.width: 2
ColumnLayout {
anchors.fill: parent
@ -49,7 +52,7 @@ Popup {
text: dialogTitle
}
Rectangle {
color: "#cccccc"
color: Style.fontColorDimmed
height: 1
Layout.fillWidth: true
}

17
src/vr/qml/common/MyDialogOkPopup.qml

@ -2,28 +2,32 @@ import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import "."
Popup {
id: myDialogPopup
property bool dismissible: true
implicitHeight: parent.height
implicitWidth: parent.width
property string dialogTitle: ""
property string dialogText: ""
property int dialogWidth: 800
property int dialogWidth: 900
property int dialogHeight: 300
property Item dialogContentItem: MyText {
fontSize:16
fontSize: 16
text: dialogText
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: true
wrap: true
}
property bool okClicked: false
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
closePolicy: myDialogPopup.dismissible ? Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent : Popup.NoAutoClose
background: Rectangle {
color: "black"
@ -36,8 +40,8 @@ Popup {
implicitHeight: dialogHeight
anchors.centerIn: parent
radius: 24
color: "#1b2939"
border.color: "#cccccc"
color: Style.backgroundColor
border.color: Style.fontColorDimmed
border.width: 2
ColumnLayout {
anchors.fill: parent
@ -48,7 +52,7 @@ Popup {
text: dialogTitle
}
Rectangle {
color: "#cccccc"
color: Style.fontColorDimmed
height: 1
Layout.fillWidth: true
}
@ -64,6 +68,7 @@ Popup {
Layout.fillWidth: true
}
RowLayout {
visible: myDialogPopup.dismissible
Layout.fillWidth: true
Layout.leftMargin: 24
Layout.rightMargin: 24

24
src/vr/qml/common/MyNumPadButton.qml

@ -6,21 +6,20 @@ Rectangle {
id: root
property string text: ""
property int fontSize: 22
property string enteredColor: "#365473"
property string exitedColor: "#2c435d"
property string pressedColor: "#406288"
property alias mouseArea: mouseArea
property alias btnTextColor: btnText.fontColor
signal clicked;
Layout.preferredWidth: 92
Layout.preferredHeight: 92
color: root.exitedColor
color: Style.btnExitedColor
MyText {
id: btnText
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
color: "white"
fontColor: Style.btnTextColor
text: root.text
fontSize: root.fontSize
fontBold: true
@ -30,9 +29,18 @@ Rectangle {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
onEntered: parent.color = root.enteredColor
onExited: parent.color = root.exitedColor
onPressed: parent.color = root.pressedColor
onEntered: {
parent.color = Style.btnEnteredColor
btnText.color = Style.btnTextHoverColor
}
onExited: {
parent.color = Style.btnExitedColor
btnText.color = Style.btnTextColor
}
onPressed: {
parent.color = Style.btnPressedColor
btnText.color = Style.btnTextHoverColor
}
onClicked: {
root.clicked();
}

45
src/vr/qml/common/MyNumPadSendAmount.qml

@ -8,10 +8,6 @@ RowLayout {
property double amount: 0.0;
property bool add: true;
property string enteredColor: "#365473"
property string exitedColor: "#2c435d"
property string pressedColor: "#406288"
signal amountUpdated(double amount);
spacing: 24
@ -28,8 +24,8 @@ RowLayout {
Layout.preferredWidth: 128
Layout.preferredHeight: 112
color: root.add ? root.exitedColor : root.enteredColor
color: root.add ? Style.btnExitedColor : Style.btnPressedColor
btnTextColor: !root.add ? Style.btnTextHoverColor : Style.btnTextColor
text: "-"
MouseArea {
@ -37,15 +33,18 @@ RowLayout {
hoverEnabled: true
onEntered: {
if(!root.add) return;
parent.color = root.enteredColor
parent.color = Style.btnPressedColor
parent.btnTextColor = Style.btnTextHoverColor
}
onExited: {
if(!root.add) return;
parent.color = root.exitedColor
parent.color = Style.btnExitedColor
Style.btnTextHoverColor
}
onClicked: {
root.add = false;
plusButton.color = root.exitedColor
plusButton.color = Style.btnExitedColor
plusButton.btnTextColor = Style.btnTextColor;
}
}
}
@ -58,8 +57,8 @@ RowLayout {
Layout.preferredWidth: 128
Layout.preferredHeight: 112
color: root.add ? root.enteredColor : root.exitedColor
color: root.add ? Style.btnPressedColor : Style.btnExitedColor
btnTextColor: root.add ? Style.btnTextHoverColor : Style.btnTextColor
text: "+"
MouseArea {
@ -67,21 +66,23 @@ RowLayout {
hoverEnabled: true
onEntered: {
if(root.add) return;
parent.color = root.enteredColor
parent.color = Style.btnPressedColor
parent.btnTextColor = Style.btnTextHoverColor
}
onExited: {
if(root.add) return;
parent.color = root.exitedColor
parent.color = Style.btnExitedColor
}