diff --git a/Dockerfile.windows b/Dockerfile.windows index 7c65ee0..c2ac24d 100644 --- a/Dockerfile.windows +++ b/Dockerfile.windows @@ -8,7 +8,7 @@ ENV OPENSSL_ROOT_DIR=/usr/local/openssl/ ENV TOR_BIN=/usr/local/tor/bin/tor.exe RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt install -y curl wget zip automake build-essential cmake gcc-mingw-w64 g++-mingw-w64 gettext git libtool pkg-config \ + DEBIAN_FRONTEND=noninteractive apt install -y curl nano wget zip automake build-essential cmake gcc-mingw-w64 g++-mingw-w64 gettext git libtool pkg-config \ python && \ rm -rf /var/lib/apt/lists/* @@ -27,8 +27,12 @@ RUN make -j$THREADS -C /depends HOST=x86_64-w64-mingw32 NO_QT=1 RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \ cd qt5 && \ git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \ git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \ git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \ git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \ git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \ git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \ @@ -38,8 +42,8 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \ ./configure --prefix=/depends/x86_64-w64-mingw32 -xplatform win32-g++ \ -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \ -I $(pwd)/qtbase/src/3rdparty/angle/include \ - -opensource -confirm-license -release -static -static-runtime -no-opengl \ - -no-avx -openssl -I /depends/x86_64-w64-mingw32/include -L /depends/x86_64-w64-mingw32/lib \ + -opensource -confirm-license -release -static -static-runtime -opengl dynamic -no-angle \ + -no-feature-qml-worker-script -no-avx -openssl -I /depends/x86_64-w64-mingw32/include -L /depends/x86_64-w64-mingw32/lib \ -qt-freetype -qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \ -skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras \ -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc \ @@ -47,7 +51,6 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \ -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport \ -skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel \ -skip qtwebengine -skip qtwebview -skip qtwinextras -skip qtx11extras \ - -skip qtdeclarative -skip qtquickcontrols -skip qtquickcontrols2 \ -skip serialbus -skip webengine \ -nomake examples -nomake tests -nomake tools && \ make -j$THREADS && \ @@ -94,7 +97,7 @@ RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \ # libpng -> libqrencode RUN git clone -b libpng16 --depth 1 https://github.com/glennrp/libpng.git && \ cd libpng && \ - git reset --hard dbe3e0c43e549a1602286144d94b0666549b18e6 && \ + git reset --hard a37d4836519517bdce6cb9d956092321eca3e73b && \ CPPFLAGS="-I/depends/x86_64-w64-mingw32/include" LDFLAGS="-L/depends/x86_64-w64-mingw32/lib" \ ./configure --host=x86_64-w64-mingw32 --prefix=/depends/x86_64-w64-mingw32 && \ make -j$THREADS && \ @@ -122,11 +125,11 @@ RUN wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz && \ rm -rf $(pwd) # OpenSSL -> Tor -RUN wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \ - echo "e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242 openssl-1.1.1i.tar.gz" | sha256sum -c && \ - tar -xzf openssl-1.1.1i.tar.gz && \ - rm openssl-1.1.1i.tar.gz && \ - cd openssl-1.1.1i && \ +RUN wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz && \ + echo "892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5 openssl-1.1.1k.tar.gz" | sha256sum -c && \ + tar -xzf openssl-1.1.1k.tar.gz && \ + rm openssl-1.1.1k.tar.gz && \ + cd openssl-1.1.1k && \ ./Configure mingw64 no-shared no-dso --cross-compile-prefix=x86_64-w64-mingw32- --prefix=/usr/local/openssl && \ make -j$THREADS && \ make -j$THREADS install_sw && \ @@ -146,10 +149,9 @@ RUN wget https://github.com/libevent/libevent/releases/download/release-2.1.11-s make -j$THREADS install && \ rm -rf $(pwd) -ENV TOR_VERSION=0.4.5.5-rc -RUN git clone -b tor-0.4.5.5-rc --depth 1 https://git.torproject.org/tor.git && \ +RUN git clone -b tor-0.4.5.7 --depth 1 https://git.torproject.org/tor.git && \ cd tor && \ - git reset --hard b36a00e9a9d3eb4b2949951afaa72e45fb7e68cd && \ + git reset --hard 83f895c015de55201e5f226f84a866f30f5ee14b && \ ./autogen.sh && \ ./configure --host=x86_64-w64-mingw32 \ --disable-asciidoc \ @@ -172,7 +174,7 @@ RUN git clone -b tor-0.4.5.5-rc --depth 1 https://git.torproject.org/tor.git && rm -rf $(pwd) && \ strip -s -D /usr/local/tor/bin/tor.exe -RUN git clone https://git.wownero.com/wowlet/monero-seed.git && \ +RUN git clone https://git.featherwallet.org/feather/monero-seed.git && \ cd monero-seed && \ git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \ cmake -DCMAKE_INSTALL_PREFIX=/depends/x86_64-w64-mingw32 \ diff --git a/contrib/openvr/src/vrcommon/pathtools_public.cpp b/contrib/openvr/src/vrcommon/pathtools_public.cpp index 1d1cb54..a2fa8b9 100755 --- a/contrib/openvr/src/vrcommon/pathtools_public.cpp +++ b/contrib/openvr/src/vrcommon/pathtools_public.cpp @@ -187,7 +187,7 @@ bool Path_IsAbsolute( const std::string & sPath ) if( sPath.empty() ) return false; -#if defined( WIN32 ) +#ifdef _WIN32 if ( sPath.size() < 3 ) // must be c:\x or \\x at least return false; @@ -515,7 +515,7 @@ bool Path_Exists( const std::string & sPath ) if( sFixedPath.empty() ) return false; -#if defined( WIN32 ) +#ifdef _WIN32 struct _stat buf; std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() ); if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 ) @@ -886,7 +886,7 @@ std::string Path_UrlToFilePath( const std::string & sFileUrl ) // ----------------------------------------------------------------------------------------------------- std::string GetUserDocumentsPath() { -#if defined( WIN32 ) +#ifdef _WIN32 WCHAR rwchPath[MAX_PATH]; if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) ) @@ -925,7 +925,7 @@ std::string GetUserDocumentsPath() // ----------------------------------------------------------------------------------------------------- bool Path_UnlinkFile( const std::string &strFilename ) { -#if defined( WIN32 ) +#ifdef _WIN32 std::wstring wsFilename = UTF8to16( strFilename.c_str() ); return ( 0 != DeleteFileW( wsFilename.c_str() ) ); #else diff --git a/contrib/openvr/src/vrcommon/vrpathregistry_public.cpp b/contrib/openvr/src/vrcommon/vrpathregistry_public.cpp index 3c991b4..675ea94 100755 --- a/contrib/openvr/src/vrcommon/vrpathregistry_public.cpp +++ b/contrib/openvr/src/vrcommon/vrpathregistry_public.cpp @@ -7,7 +7,7 @@ #include #include -#if defined( WIN32 ) +#ifdef _WIN32 #include #include @@ -36,7 +36,7 @@ /** Returns the root of the directory the system wants us to store user config data in */ static std::string GetAppSettingsPath() { -#if defined( WIN32 ) +#ifdef _WIN32 WCHAR rwchPath[MAX_PATH]; if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) ) diff --git a/src/appcontext.cpp b/src/appcontext.cpp index 387b2a9..910fd0c 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -21,12 +21,14 @@ TxFiatHistory *AppContext::txFiatHistory = nullptr; double AppContext::balance = 0; QMap AppContext::txDescriptionCache; QMap AppContext::txCache; +bool AppContext::isQML = false; AppContext::AppContext(QCommandLineParser *cmdargs) { this->m_walletKeysFilesModel = new WalletKeysFilesModel(this, this); this->network = new QNetworkAccessManager(); this->networkClearnet = new QNetworkAccessManager(); this->cmdargs = cmdargs; + AppContext::isQML = false; #if defined(Q_OS_MAC) this->isTorSocks = qgetenv("DYLD_INSERT_LIBRARIES").indexOf("libtorsocks") >= 0; @@ -105,7 +107,7 @@ AppContext::AppContext(QCommandLineParser *cmdargs) { connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes); // Tor & socks proxy - this->ws = new WSClient(this, m_wsUrl); + this->ws = new WSClient(this, wsUrl); connect(this->ws, &WSClient::WSMessage, this, &AppContext::onWSMessage); connect(this->ws, &WSClient::connectionEstablished, this, &AppContext::wsConnected); connect(this->ws, &WSClient::closed, this, &AppContext::wsDisconnected); @@ -163,11 +165,10 @@ void AppContext::initTor() { this->tor = new Tor(this, this); this->tor->start(); - if (!(isWhonix)) { + if (!isWhonix && wsUrl.contains(".onion")) { this->networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort); this->network->setProxy(*networkProxy); - if (m_wsUrl.host().endsWith(".onion")) - this->ws->webSocket.setProxy(*networkProxy); + this->ws->webSocket.setProxy(*networkProxy); } } @@ -409,7 +410,7 @@ void AppContext::onWSMessage(const QJsonObject &msg) { emit blockHeightWSUpdated(this->heights); } - else if(cmd == "nodes") { + else if(cmd == "rpc_nodes") { this->onWSNodes(msg.value("data").toArray()); } #if defined(HAS_XMRIG) @@ -431,7 +432,7 @@ void AppContext::onWSMessage(const QJsonObject &msg) { this->onWSReddit(reddit_data); } - else if(cmd == "wfs") { + else if(cmd == "funding_proposals") { auto ccs_data = msg.value("data").toArray(); this->onWSCCS(ccs_data); } @@ -445,6 +446,23 @@ void AppContext::onWSMessage(const QJsonObject &msg) { auto txFiatHistory_data = msg.value("data").toObject(); AppContext::txFiatHistory->onWSData(txFiatHistory_data); } +#if defined(HAS_OPENVR) + else if(cmd == "requestPIN") { + auto pin = msg.value("data").toString(); + emit pinReceived(pin); + } + + else if(cmd == "lookupPIN") { + auto lookup_data = msg.value("data").toObject(); + auto address = lookup_data.value("address").toString(); + auto pin = lookup_data.value("PIN").toString(); + + if(address.isEmpty()) + emit pinLookupErrorReceived(); + else + emit pinLookupReceived(address, pin); + } +#endif } void AppContext::onWSNodes(const QJsonArray &nodes) { @@ -813,6 +831,47 @@ void AppContext::onTransactionCreated(PendingTransaction *tx, const QVectorcurrentWallet == nullptr) + return; + + auto address = this->currentWallet->address(0, 1); + QString signature = this->currentWallet->signMessage(address, false, address); + + QJsonObject data; + data["signature"] = signature; + data["address"] = address; + + QJsonObject obj; + obj["cmd"] = "requestPIN"; + obj["data"] = data; + + QJsonDocument doc = QJsonDocument(obj); + this->ws->sendMsg(doc.toJson(QJsonDocument::Compact)); +} + +void AppContext::onLookupReceivingPIN(QString pin) { + // lookup PIN -> address + if(this->currentWallet == nullptr) + return; + + auto address = this->currentWallet->address(0, 1); + QString signature = this->currentWallet->signMessage(address, false, address); + + QJsonObject data; + data["PIN"] = pin; + + QJsonObject obj; + obj["cmd"] = "lookupPIN"; + obj["data"] = data; + + 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()); this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount()); diff --git a/src/appcontext.h b/src/appcontext.h index efc3021..bd33572 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -57,6 +57,8 @@ public: QString defaultWalletDir; QString defaultWalletDirRoot; QString tmpTxDescription; + QString wsUrl = "51.195.148.161:1338"; +// QString wsUrl = "feathercitimllbmdktu6cmjo3fizgmyfrntntqzu6xguqa2rlq5cgid.onion"; QString walletPath; QString walletPassword = ""; @@ -91,6 +93,7 @@ public: static QMap txDescriptionCache; static QMap txCache; static TxFiatHistory *txFiatHistory; + static bool isQML; // libwalletqt bool refreshed = false; @@ -111,7 +114,7 @@ public: void setWindowTitle(bool mining = false); // Closes the currently opened wallet - void closeWallet(bool emitClosedSignal = true, bool storeWallet = false); + Q_INVOKABLE void closeWallet(bool emitClosedSignal = true, bool storeWallet = false); void storeWallet(); Q_INVOKABLE QVariantList listWallets() { @@ -137,6 +140,8 @@ public slots: void onOpenAliasResolve(const QString &openAlias); void onSetRestoreHeight(quint64 height); void onPreferredFiatCurrencyChanged(const QString &symbol); + Q_INVOKABLE void onAskReceivingPIN(); + Q_INVOKABLE void onLookupReceivingPIN(QString pin); private slots: void onWSNodes(const QJsonArray &nodes); @@ -186,6 +191,9 @@ signals: void suchWowUpdated(const QJsonArray &such_data); void nodeSourceChanged(NodeSource nodeSource); void XMRigDownloads(const QJsonObject &data); + void pinLookupReceived(QString address, QString pin); + void pinLookupErrorReceived(); + void pinReceived(QString pin); void setCustomNodes(QList nodes); void openAliasResolveError(const QString &msg); void openAliasResolved(const QString &address, const QString &openAlias); @@ -201,8 +209,6 @@ private: WalletKeysFilesModel *m_walletKeysFilesModel; const int m_donationBoundary = 15; QTimer m_storeTimer; - // @TODO: Replace url - QUrl m_wsUrl = QUrl(QStringLiteral("ws://feathercitimllbmdktu6cmjo3fizgmyfrntntqzu6xguqa2rlq5cgid.onion/ws")); }; #endif //WOWLET_APPCONTEXT_H diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 4e4d905..49fc6f3 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 1156 - 496 + 502 @@ -101,11 +101,11 @@ true - + - SuchWow + /r/Wownero - + 0 @@ -119,22 +119,15 @@ 0 - - - - 0 - 320 - - - + - + - WFS + SuchWow - + 0 @@ -148,15 +141,22 @@ 0 - + + + + 0 + 320 + + + - + - /r/Wownero + WFS - + 0 @@ -170,7 +170,7 @@ 0 - + @@ -326,7 +326,7 @@ 0 0 1156 - 30 + 20 diff --git a/src/model/TransactionHistoryModel.cpp b/src/model/TransactionHistoryModel.cpp index 8158d1f..7ac747d 100644 --- a/src/model/TransactionHistoryModel.cpp +++ b/src/model/TransactionHistoryModel.cpp @@ -51,7 +51,12 @@ int TransactionHistoryModel::columnCount(const QModelIndex &parent) const { return 0; } - return TransactionInfoRole::COUNT; + // When wowlet is in QtWidgets mode, it will only use the first 5 columns, + // the rest should be hidden, because it shows in the GUI. So by default we'll + // use 5 as column count. When in QtQuick (QML) mode, we want to expose more columns + // so we can change the column count here. + + return AppContext::isQML ? this->COUNT : 5; } QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const { diff --git a/src/model/TransactionHistoryModel.h b/src/model/TransactionHistoryModel.h index bdc0f3d..93d0d25 100644 --- a/src/model/TransactionHistoryModel.h +++ b/src/model/TransactionHistoryModel.h @@ -50,6 +50,7 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role) override; + int customColumnCount = 5; signals: void transactionHistoryChanged(); diff --git a/src/utils/prices.cpp b/src/utils/prices.cpp index 1ff5085..445b493 100644 --- a/src/utils/prices.cpp +++ b/src/utils/prices.cpp @@ -85,9 +85,8 @@ double Prices::convert(const QString &symbolFrom, const QString &symbolTo, doubl } void Prices::fiatPricesReceived(const QJsonObject &data) { - QJsonObject rates = data.value("rates").toObject(); for(const auto ¤cy: fiat.keys()) - if(rates.contains(currency)) - this->rates.insert(currency, rates.value(currency).toDouble()); + if(data.contains(currency)) + this->rates.insert(currency, data.value(currency).toDouble()); emit fiatPricesUpdated(); } diff --git a/src/utils/wsclient.cpp b/src/utils/wsclient.cpp index e816e94..b5c0204 100644 --- a/src/utils/wsclient.cpp +++ b/src/utils/wsclient.cpp @@ -8,16 +8,16 @@ #include "wsclient.h" #include "appcontext.h" -WSClient::WSClient(AppContext *ctx, const QUrl &url, QObject *parent) : +WSClient::WSClient(AppContext *ctx, const QString &url, QObject *parent) : QObject(parent), - url(url), m_ctx(ctx) { connect(&this->webSocket, &QWebSocket::binaryMessageReceived, this, &WSClient::onbinaryMessageReceived); connect(&this->webSocket, &QWebSocket::connected, this, &WSClient::onConnected); connect(&this->webSocket, &QWebSocket::disconnected, this, &WSClient::closed); connect(&this->webSocket, QOverload::of(&QWebSocket::error), this, &WSClient::onError); - m_tor = url.host().endsWith(".onion"); + m_tor = url.contains(".onion"); + this->url = QString("ws://%1/ws").arg(url); // Keep websocket connection alive connect(&m_pingTimer, &QTimer::timeout, [this]{ diff --git a/src/utils/wsclient.h b/src/utils/wsclient.h index 0192b53..90b6f75 100644 --- a/src/utils/wsclient.h +++ b/src/utils/wsclient.h @@ -14,11 +14,11 @@ class WSClient : public QObject Q_OBJECT public: - explicit WSClient(AppContext *ctx, const QUrl &url, QObject *parent = nullptr); + explicit WSClient(AppContext *ctx, const QString &url, QObject *parent = nullptr); void start(); void sendMsg(const QByteArray &data); QWebSocket webSocket; - QUrl url; + QString url; signals: void closed(); diff --git a/src/vr/main.cpp b/src/vr/main.cpp index cd8cdfe..5870284 100644 --- a/src/vr/main.cpp +++ b/src/vr/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -32,13 +33,24 @@ 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; + + // write icon to disk so openvr overlay can refer to it + auto icon = ":/assets/images/wowlet.png"; + if (Utils::fileExists(icon)) { + QFile f(icon); + QFileInfo fileInfo(f); + auto icon_path = QDir(ctx->configDirectory).filePath(fileInfo.fileName()); + f.copy(icon_path); + f.close(); + } #ifdef Q_OS_WIN if(desktopMode) qputenv("QMLSCENE_DEVICE", "softwarecontext"); #endif - qDebug() << "QMLSCENE_DEVICE: " << qgetenv("QMLSCENE_DEVICE"); + qInfo() << "OPENSSL VERSION: " << QSslSocket::sslLibraryBuildVersionString(); m_engine.rootContext()->setContextProperty("homePath", QDir::homePath()); m_engine.rootContext()->setContextProperty("applicationDirectory", QApplication::applicationDirPath()); @@ -67,17 +79,20 @@ namespace wowletvr { // QCoreApplication::setAttribute( Qt::AA_UseDesktopOpenGL ); // QCoreApplication::setAttribute( Qt::AA_Use96Dpi ); + 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); + } + auto widgetUrl = QUrl(QStringLiteral("qrc:///main")); m_component = new QQmlComponent(&m_engine, widgetUrl); this->errors = m_component->errors(); for (auto &e : this->errors) qCritical() << "QML Error: " << e.toString().toStdString().c_str(); - - if(!desktopMode) { - openvr_init::initializeOpenVR(openvr_init::OpenVrInitializationType::Overlay); - m_controller = new wowletvr::OverlayController(desktopMode, m_engine); - } } void WowletVR::render() { @@ -97,7 +112,8 @@ namespace wowletvr { return; } - m_controller->SetWidget(quickObjItem, displayName, appKey); + auto iconPath = ctx->configDirectory + "/wowlet.png"; + m_controller->SetWidget(quickObjItem, displayName, appKey, iconPath.toStdString()); } WowletVR::~WowletVR() { diff --git a/src/vr/main.qml b/src/vr/main.qml index 2660c12..696261d 100644 --- a/src/vr/main.qml +++ b/src/vr/main.qml @@ -7,11 +7,6 @@ import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.2 import "." -import "mock/Windows.js" as Windows -import "mock/Version.js" as Version -import "mock/NetworkType.js" as NetworkType -import "mock/Settings.js" as Settings -import "mock" import "qml/common" import "qml/." @@ -27,10 +22,10 @@ Rectangle { property var currentWallet; property bool disconnected: currentWallet ? currentWallet.disconnected : false - property string walletTitle: "lol123" + property string walletTitle: "long wallet name" property string walletPath: "" property string statusText: "Idle" - property string balanceFormatted: "Balance: 25928.9543 WOW (+3902.32 WOW unconfirmed)" + property string balanceFormatted: "Balance: 25928.9543 WOW" property bool wsConnected: false property int connectionStatus: Wallet.ConnectionStatus_Disconnected; @@ -60,9 +55,9 @@ Rectangle { MyDialogOkCancelPopup { id: enterPasswordDialog - dialogTitle: "Enter Password" + dialogTitle: "Enter Wallet Password" dialogWidth: 700 - dialogHeight: 400 + dialogHeight: 380 dialogContentItem: ColumnLayout { RowLayout { @@ -76,7 +71,7 @@ Rectangle { MyTextField { id: walletOpenPassword - keyBoardUID: 590 + keyBoardUID: 591 color: "#cccccc" text: "" Layout.fillWidth: true @@ -105,9 +100,10 @@ Rectangle { id: createWalletDialog dialogTitle: "Create New Wallet" dialogWidth: 700 - dialogHeight: 400 + dialogHeight: 440 dialogContentItem: ColumnLayout { + spacing: 10 RowLayout { Layout.topMargin: 16 Layout.leftMargin: 16 @@ -141,7 +137,7 @@ Rectangle { MyTextField { id: newWalletPassword - keyBoardUID: 591 + keyBoardUID: 592 color: "#cccccc" text: "" Layout.fillWidth: true @@ -153,7 +149,10 @@ Rectangle { } MyText { + Layout.topMargin: 20 + Layout.leftMargin: 16 fontSize: 16 + fontColor: "#cccccc" text: "The password field is optional." } @@ -253,19 +252,11 @@ Rectangle { } // function onWalletOpened(Wallet *wallet) { - - // currentWallet.heightRefreshed.connect(onHeightRefreshed); - // currentWallet.refreshed.connect(onWalletRefresh) - // currentWallet.updated.connect(onWalletUpdate) - // currentWallet.newBlock.connect(onWalletNewBlock) // currentWallet.moneySpent.connect(onWalletMoneySent) // currentWallet.moneyReceived.connect(onWalletMoneyReceived) // currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived) // currentWallet.transactionCreated.connect(onTransactionCreated) // currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged) - // currentWallet.deviceButtonRequest.connect(onDeviceButtonRequest); - // currentWallet.deviceButtonPressed.connect(onDeviceButtonPressed); - // currentWallet.walletPassphraseNeeded.connect(onWalletPassphraseNeededWallet); // currentWallet.transactionCommitted.connect(onTransactionCommitted); // middlePanel.paymentClicked.connect(handlePayment); diff --git a/src/vr/openvr_init.cpp b/src/vr/openvr_init.cpp index 2596e04..bae2884 100755 --- a/src/vr/openvr_init.cpp +++ b/src/vr/openvr_init.cpp @@ -6,7 +6,12 @@ #include #include #include + #include "openvr_init.h" +#include "utils/utils.h" +#include +#include + namespace openvr_init { @@ -34,6 +39,14 @@ bool initializeProperly(const OpenVrInitializationType initType) { bool initializeOpenVR(const OpenVrInitializationType initType) { + QString vr_pathreg_override = qgetenv("VR_PATHREG_OVERRIDE"); + if(!vr_pathreg_override.isEmpty()) { + if(Utils::fileExists(vr_pathreg_override)) { + qCritical() << "Filepath supplied in VR_PATHREG_OVERRIDE not found. Does this path exist?"; + return false; + } + } + bool res = initializeProperly(initType); if(!res) return false; diff --git a/src/vr/overlaycontroller.cpp b/src/vr/overlaycontroller.cpp index d09ff5b..b01f20b 100755 --- a/src/vr/overlaycontroller.cpp +++ b/src/vr/overlaycontroller.cpp @@ -81,27 +81,6 @@ OverlayController::OverlayController(bool desktopMode, QQmlEngine& qmlEngine) : // Set qml context qmlEngine.rootContext()->setContextProperty("applicationVersion", "1337"); qmlEngine.rootContext()->setContextProperty("vrRuntimePath", getVRRuntimePathUrl()); - - // Pretty disgusting trick to allow qmlRegisterSingletonType to continue - // working with the lambdas that were already there. The callback function - // in qmlRegisterSingletonType won't work with any lambdas that capture the - // environment. The alternative to making a static pointer to this was - // rewriting all QML to not be singletons, which should probably be done - // whenever possible. - static OverlayController* const objectAddress = this; - constexpr auto qmlSingletonImportName = "ovrwow.wowletvr"; - qmlRegisterSingletonType( - qmlSingletonImportName, - 1, - 0, - "OverlayController", - []( QQmlEngine*, QJSEngine* ) { - QObject* obj = objectAddress; - QQmlEngine::setObjectOwnership( obj, QQmlEngine::CppOwnership ); - return obj; - }); - - qInfo() << "OPENSSL VERSION: " << QSslSocket::sslLibraryBuildVersionString(); } OverlayController::~OverlayController() { @@ -138,9 +117,7 @@ void OverlayController::Shutdown() { m_pFbo.reset(); } -void OverlayController::SetWidget( QQuickItem* quickItem, - const std::string& name, - const std::string& key ) +void OverlayController::SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key, const std::string& iconPath) { if ( !m_desktopMode ) { @@ -171,14 +148,9 @@ void OverlayController::SetWidget( QQuickItem* quickItem, vr::VROverlayFlags_SendVRSmoothScrollEvents, true ); - constexpr auto thumbiconFilename = "img/icons/thumbicon.png"; - const auto thumbIconPath = paths::binaryDirectoryFindFile( thumbiconFilename ); - if ( !thumbIconPath.empty() ) { - vr::VROverlay()->SetOverlayFromFile( m_ulOverlayThumbnailHandle, thumbIconPath.c_str() ); - } - else { - qCritical() << "Could not find thumbnail icon \"" << thumbiconFilename << "\""; - } + // Overlay icon + if (!iconPath.empty()) + vr::VROverlay()->SetOverlayFromFile( m_ulOverlayThumbnailHandle, iconPath.c_str() ); // Too many render calls in too short time overwhelm Qt and an // assertion gets thrown. Therefore we use an timer to delay render @@ -401,6 +373,7 @@ void OverlayController::mainEventLoop() { case vr::VREvent_DashboardActivated: { qDebug() << "Dashboard activated"; + emit dashboardActivated(); m_dashboardVisible = true; } break; @@ -408,14 +381,17 @@ void OverlayController::mainEventLoop() { case vr::VREvent_DashboardDeactivated: { qDebug() << "Dashboard deactivated"; + emit dashboardDeactivated(); m_dashboardVisible = false; } break; case vr::VREvent_KeyboardDone: { + qDebug() << "VREvent_KeyboardDone"; char keyboardBuffer[1024]; vr::VROverlay()->GetKeyboardText( keyboardBuffer, 1024 ); + qDebug() << "emit keyBoardInputSignal()"; emit keyBoardInputSignal( QString( keyboardBuffer ), static_cast( vrEvent.data.keyboard.uUserValue ) ); @@ -447,7 +423,7 @@ void OverlayController::showKeyboard(QString existingText, unsigned long userVal vr::k_EGamepadTextInputModeNormal, vr::k_EGamepadTextInputLineModeSingleLine, 0, - "Advanced Settings Overlay", + "Wowlet VR", 1024, existingText.toStdString().c_str(), userValue); diff --git a/src/vr/overlaycontroller.h b/src/vr/overlaycontroller.h index 4cb7cde..6ca0dc5 100755 --- a/src/vr/overlaycontroller.h +++ b/src/vr/overlaycontroller.h @@ -50,6 +50,7 @@ namespace wowletvr class OverlayController : public QObject { Q_OBJECT + Q_PROPERTY( bool m_desktopMode READ isDesktopMode ) public: OverlayController(bool desktopMode, QQmlEngine& qmlEngine); @@ -64,9 +65,7 @@ public: return m_dashboardVisible; } - void SetWidget( QQuickItem* quickItem, - const std::string& name, - const std::string& key = "" ); + void SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key = "", const std::string& iconPath = ""); bool isDesktopMode() { @@ -129,6 +128,8 @@ public slots: signals: void keyBoardInputSignal( QString input, unsigned long userValue = 0 ); + void dashboardDeactivated(); + void dashboardActivated(); }; } // namespace wowletvr diff --git a/src/vr/qml.qrc b/src/vr/qml.qrc index 3b5d696..82363f1 100644 --- a/src/vr/qml.qrc +++ b/src/vr/qml.qrc @@ -40,13 +40,6 @@ assets/img/status_waiting.svg assets/img/status_lagging.svg - mock/NetworkType.js - mock/OverlayController.js - mock/Settings.js - mock/Translation.js - mock/Version.js - mock/Windows.js - main.qml qml/common/HourComboBox.qml qml/common/MinuteSecondComboBox.qml diff --git a/src/vr/qml/AboutPage.qml b/src/vr/qml/AboutPage.qml index 4a4cc2c..d951ef1 100644 --- a/src/vr/qml/AboutPage.qml +++ b/src/vr/qml/AboutPage.qml @@ -39,7 +39,7 @@ 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 by 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 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" wrap: true } @@ -51,7 +51,16 @@ ColumnLayout { Layout.leftMargin: 40 Layout.rightMargin: 40 Layout.fillWidth: true - text: "By \"dsc\" - April 2021. Shoutouts: OpenVR-AdvancedSettings, qvqc, Gatto, cisme, wowario, lza_menace, jwinterm, nioc, asymptotically, azy, selsta, kico, laura, thrmo, rottensox, solar, bl4sty, scoobybejesus (sorry if I forgot anyone!)" + text: "Greetings: matzman666, qvqc, ez, Gatto, cisme, wowario, lza_menace, jwinterm, nioc, asymptotically, azy, selsta, kico, laura, thrmo, rottensox, solar, bl4sty, scoobybejesus" + wrap: true + } + + MyText { + Layout.leftMargin: 40 + Layout.rightMargin: 40 + Layout.fillWidth: true + fontSize: 14 + text: "dsc - April 2021" wrap: true } diff --git a/src/vr/qml/CreateWalletDialog.qml b/src/vr/qml/CreateWalletDialog.qml deleted file mode 100644 index 9f15dba..0000000 --- a/src/vr/qml/CreateWalletDialog.qml +++ /dev/null @@ -1,12 +0,0 @@ -// import QtQuick 2.7 -// import QtQuick.Controls 2.0 -// import QtQuick.Layouts 1.2 -// import QtGraphicalEffects 1.0 -// import QtQuick.Window 2.0 -// import QtQuick.Controls.Styles 1.4 -// import QtQuick.Dialogs 1.2 - -// //import ovrwow.wowletvr 1.0 - -// import "common" - diff --git a/src/vr/qml/common/MyStackViewPage.qml b/src/vr/qml/common/MyStackViewPage.qml index fad7c5c..dbac0ba 100755 --- a/src/vr/qml/common/MyStackViewPage.qml +++ b/src/vr/qml/common/MyStackViewPage.qml @@ -9,6 +9,7 @@ import wowlet.Wallet 1.0 Rectangle { + id: root color: "#1b2939" width: 1600 height: 800 @@ -17,46 +18,64 @@ Rectangle { property string headerText: "Header Title" property bool headerShowBackButton: true + property string enteredColor: "#365473" + property string exitedColor: "transparent" + property string pressedColor: "#406288" + signal backClicked(); property Item header: ColumnLayout { RowLayout { - Button { - id: headerBackButton - Layout.preferredHeight: 50 - Layout.preferredWidth: 50 - hoverEnabled: true - enabled: headerShowBackButton - visible: headerShowBackButton - contentItem: Image { - source: "qrc:/backarrow" - sourceSize.width: 50 - sourceSize.height: 50 + Rectangle { + color: "transparent" + Layout.preferredWidth: headerBackButton.width + headerTitleContainer.width + 20 + Layout.preferredHeight: 70 + + RowLayout { anchors.fill: parent + + Rectangle { + id: headerBackButton + visible: headerShowBackButton + color: "transparent" + Layout.preferredHeight: 50 + Layout.preferredWidth: 50 + + Image { + source: "qrc:/backarrow" + sourceSize.width: 50 + sourceSize.height: 50 + anchors.fill: parent + } + } + + Rectangle { + id: headerTitleContainer + color: "transparent" + Layout.preferredHeight: 50 + Layout.preferredWidth: headerTitle.width + + MyText { + id: headerTitle + text: headerText + font.pointSize: 26 + anchors.verticalCenter: parent.verticalCenter + } + } } - background: Rectangle { - opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0) - color: "#406288" - radius: 4 + + MouseArea { + enabled: headerShowBackButton anchors.fill: parent - } - onHoveredChanged: { - if (hovered) { - forceActiveFocus() - } else { - focus = false + hoverEnabled: true + onEntered: parent.color = root.enteredColor + onExited: parent.color = root.exitedColor + onPressed: parent.color = root.pressedColor + onClicked: { + stackView.pop(); + backClicked(); } } - onClicked: { - backClicked(); - stackView.pop(); - } - } - MyText { - id: headerTitle - text: headerText - font.pointSize: 30 - Layout.leftMargin: headerShowBackButton ? 32 : 0 } Item { @@ -64,6 +83,7 @@ Rectangle { Layout.preferredHeight: 50 } + Rectangle { Layout.preferredWidth: 720 Layout.preferredHeight: 50 diff --git a/src/vr/qml/common/MyTextField.qml b/src/vr/qml/common/MyTextField.qml index fd1bb5a..da19807 100755 --- a/src/vr/qml/common/MyTextField.qml +++ b/src/vr/qml/common/MyTextField.qml @@ -23,6 +23,7 @@ TextField { } } onActiveFocusChanged: { + console.log("QML activeFocus()"); if (activeFocus) { if (!OverlayController.desktopMode) { OverlayController.showKeyboard(text, keyBoardUID) @@ -32,11 +33,24 @@ TextField { } } onEditingFinished: { + console.log("QML onEditingFinished()"); if (OverlayController.desktopMode && savedText !== text) { myTextField.onInputEvent(text) } } function onInputEvent(input) { text = input - } + } + + Connections { + target: OverlayController + function onKeyBoardInputSignal(input, userValue) { + console.log("QML onKeyBoardInputSignal(input, userValue)", keyBoardUID); + if (userValue == keyBoardUID) { + if (myTextField.text !== input) { + myTextField.onInputEvent(input) + } + } + } + } } diff --git a/src/vr/qml/dashboard/CreateWallet.qml b/src/vr/qml/dashboard/CreateWallet.qml deleted file mode 100644 index e69de29..0000000 diff --git a/src/vr/qml/dashboard/HelpPage.qml b/src/vr/qml/dashboard/HelpPage.qml deleted file mode 100644 index e69de29..0000000 diff --git a/src/vr/qml/wallet/HistoryTable.qml b/src/vr/qml/wallet/HistoryTable.qml index 14a84c6..b3ffccf 100755 --- a/src/vr/qml/wallet/HistoryTable.qml +++ b/src/vr/qml/wallet/HistoryTable.qml @@ -13,7 +13,8 @@ import "../common" Item { id: root - property var modelx + property var txModel + property int txCount: 0 property var txModelData: [] property int sideMargin: 20 @@ -24,6 +25,12 @@ Item { anchors.fill: parent spacing: 0 + MyText { + visible: txCount == 0 + opacity: 0.75 + text: "No transactions to display." + } + ListView { id: listView visible: true @@ -31,11 +38,11 @@ Item { Layout.fillWidth: true Layout.fillHeight: true spacing: 10 - model: modelx + model: txModel interactive: false delegate: Rectangle { - id: delegate + id: delegate anchors.left: parent ? parent.left : undefined anchors.right: parent ? parent.right : undefined height: 54 @@ -64,6 +71,7 @@ Item { confirmationsRequired = getTxData(index, TransactionHistoryModel.TransactionConfirmationsRequiredRole); confirmed = confirmations >= confirmationsRequired; + root.txCount = index; } RowLayout { @@ -74,16 +82,16 @@ Item { anchors.right: parent.right Rectangle { - Layout.preferredWidth: 56 - Layout.fillHeight: true - color: "#406288" - - Image { - width: 32 - height: 32 - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - source: { + Layout.preferredWidth: 56 + Layout.fillHeight: true + color: "#406288" + + Image { + width: 32 + height: 32 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: { if(failed) return "qrc:/assets/images/warning.png" else if(pending) return "qrc:/assets/images/unconfirmed.png" else if(!confirmed) return "qrc:/assets/images/clock1.png" @@ -91,98 +99,89 @@ Item { else return "qrc:/assets/images/confirmed.png" //confirmed ? "qrc:/checkmark_icon" : "qrc:/expired_icon" } - } + } } Rectangle { - Layout.preferredWidth: 300 - Layout.leftMargin: 10 - Layout.rightMargin: 10 - Layout.fillHeight: true - color: "transparent" + Layout.preferredWidth: 300 + Layout.leftMargin: 10 + Layout.rightMargin: 10 + Layout.fillHeight: true + color: "transparent" - MyText { + MyText { // date - anchors.verticalCenter: parent.verticalCenter - fontSize: 12 + anchors.verticalCenter: parent.verticalCenter + fontSize: 12 fontColor: "white" - text: date + text: date - Component.onCompleted: { - parent.Layout.preferredWidth = width; - } - } + Component.onCompleted: { + parent.Layout.preferredWidth = width; + } + } } Rectangle { - Layout.fillHeight: true - Layout.leftMargin: 10 - color: "transparent" - - MyText { - anchors.verticalCenter: parent.verticalCenter - fontSize: 14 - text: description !== "" ? description : "..." + Layout.fillHeight: true + Layout.leftMargin: 10 + color: "transparent" + + MyText { + anchors.verticalCenter: parent.verticalCenter + fontSize: 14 + text: description !== "" ? description : "..." fontColor: description !== "" ? "white" : "#cccccc" - Component.onCompleted: { - parent.Layout.preferredWidth = width; - } - } + Component.onCompleted: { + parent.Layout.preferredWidth = width; + } + } } Item { - Layout.fillWidth: true + Layout.fillWidth: true } Rectangle { - Layout.preferredWidth: 420 - Layout.fillHeight: true - color: "#406288" - - MyText { - anchors.right: parent.right - anchors.rightMargin: 10 - - anchors.verticalCenter: parent.verticalCenter - fontSize: 14 - fontBold: true - text: amount - fontColor: !isout ? "#00d304" : "red" - } + Layout.preferredWidth: 420 + Layout.fillHeight: true + color: "#406288" + + MyText { + anchors.right: parent.right + anchors.rightMargin: 10 + + anchors.verticalCenter: parent.verticalCenter + fontSize: 14 + fontBold: true + text: amount + fontColor: !isout ? "#00d304" : "red" + } } - } - } - } - - Item { - Layout.fillHeight: true - } - } - - Rectangle { - z: parent.z - 1 - color: "transparent" - anchors.fill: parent - } + } + } + } - function getTxData(x, y) { - var idx = modelx.index(x, y); - return modelx.data(idx, 0); + Item { + Layout.fillHeight: true + } } - function updateTransactionsFromModel() { - // This function copies the items of `appWindow.currentWallet.historyModel` to `root.txModelData`, as a list of javascript objects - if(appWindow.currentWallet == null || typeof appWindow.currentWallet.history === "undefined" ) return; + Rectangle { + z: parent.z - 1 + color: "transparent" + anchors.fill: parent + } - var _model = root.model; - var total = 0 - var count = _model.rowCount() - root.txModelData = []; + function getTxData(x, y) { + var idx = txModel.index(x, y); + return txModel.data(idx, 0); } function onPageCompleted() { if(currentWallet == null || typeof currentWallet.history === "undefined" ) return; - root.modelx = appWindow.currentWallet.historyModel; + root.txCount = 0; + root.txModel = appWindow.currentWallet.historyModel; //root.model.sortRole = TransactionHistoryModel.TransactionBlockHeightRole; //root.model.sort(0, Qt.DescendingOrder); } diff --git a/src/vr/qml/wallet/ReceivePage.qml b/src/vr/qml/wallet/ReceivePage.qml index 82ebdf6..e13308e 100755 --- a/src/vr/qml/wallet/ReceivePage.qml +++ b/src/vr/qml/wallet/ReceivePage.qml @@ -6,249 +6,134 @@ import "." import "../common" MyStackViewPage { + id: root headerText: "Receive" - MyDialogOkPopup { - id: chaperoneMessageDialog - function showMessage(title, text) { - dialogTitle = title - dialogText = text - open() - } - } - - MyDialogOkCancelPopup { - id: chaperoneDeleteProfileDialog - property int profileIndex: -1 - dialogTitle: "Delete Profile" - dialogText: "Do you really want to delete this profile?" - onClosed: { - if (okClicked) { - ChaperoneTabController.deleteChaperoneProfile(profileIndex) - } - } - } - - MyDialogOkCancelPopup { - id: chaperoneNewProfileDialog - dialogTitle: "Create New Profile" - dialogWidth: 800 - dialogHeight: 780 - dialogContentItem: ColumnLayout { - RowLayout { - Layout.topMargin: 16 - Layout.leftMargin: 16 - Layout.rightMargin: 16 - MyText { - text: "Name: " - } - MyTextField { - id: chaperoneNewProfileName - keyBoardUID: 390 - color: "#cccccc" - text: "" - Layout.fillWidth: true - font.pointSize: 20 - function onInputEvent(input) { - chaperoneNewProfileName.text = input - } - } - } - MyText { - Layout.topMargin: 24 - text: "What to include:" - } - MyToggleButton { - id: chaperoneNewProfileIncludeGeometry - Layout.leftMargin: 32 - text: "Chaperone Geometry" - } - MyToggleButton { - id: chaperoneNewProfileIncludeStyle - Layout.leftMargin: 32 - text: "Chaperone Style" - } - MyToggleButton { - id: chaperoneNewProfileIncludeBoundsColor - Layout.leftMargin: 32 - text: "Chaperone Color" - } - MyToggleButton { - id: chaperoneNewProfileIncludeVisibility - Layout.leftMargin: 32 - text: "Visibility Setting" - } - MyToggleButton { - id: chaperoneNewProfileIncludeFadeDistance - Layout.leftMargin: 32 - text: "Fade Distance Setting" - } - MyToggleButton { - id: chaperoneNewProfileIncludeCenterMarker - Layout.leftMargin: 32 - text: "Center Marker Setting" - } - MyToggleButton { - id: chaperoneNewProfileIncludePlaySpaceMarker - Layout.leftMargin: 32 - text: "Play Space Marker Setting" - } - MyToggleButton { - id: chaperoneNewProfileIncludeFloorBoundsMarker - Layout.leftMargin: 32 - text: "Floor Bounds Always On Setting" - } - MyToggleButton { - id: chaperoneNewProfileIncludeForceBounds - Layout.leftMargin: 32 - text: "Force Bounds Setting" - } - MyToggleButton { - id: chaperoneNewProfileIncludeProximityWarnings - Layout.leftMargin: 32 - text: "Proximity Warning Settings" - } - } - onClosed: { - if (okClicked) { - if (chaperoneNewProfileName.text == "") { - chaperoneMessageDialog.showMessage("Create New Profile", "ERROR: Empty profile name.") - } else if (!chaperoneNewProfileIncludeGeometry.checked - && !chaperoneNewProfileIncludeVisibility.checked - && !chaperoneNewProfileIncludeFadeDistance.checked - && !chaperoneNewProfileIncludeCenterMarker.checked - && !chaperoneNewProfileIncludePlaySpaceMarker.checked - && !chaperoneNewProfileIncludeFloorBoundsMarker.checked - && !chaperoneNewProfileIncludeBoundsColor.checked - && !chaperoneNewProfileIncludeStyle.checked - && !chaperoneNewProfileIncludeForceBounds.checked - && !chaperoneNewProfileIncludeProximityWarnings.checked) { - chaperoneMessageDialog.showMessage("Create New Profile", "ERROR: Nothing included.") - } else if ( Math.abs(MoveCenterTabController.offsetX) > 0.00000000001 - || Math.abs(MoveCenterTabController.offsetY) > 0.00000000001 - || Math.abs(MoveCenterTabController.offsetZ) > 0.00000000001 - || MoveCenterTabController.rotation !== 0) { - chaperoneMessageDialog.showMessage("Create New Profile", "ERROR: Offsets not reset.") - } else { - ChaperoneTabController.addChaperoneProfile(chaperoneNewProfileName.text, - chaperoneNewProfileIncludeGeometry.checked, - chaperoneNewProfileIncludeVisibility.checked, - chaperoneNewProfileIncludeFadeDistance.checked, - chaperoneNewProfileIncludeCenterMarker.checked, - chaperoneNewProfileIncludePlaySpaceMarker.checked, - chaperoneNewProfileIncludeFloorBoundsMarker.checked, - chaperoneNewProfileIncludeBoundsColor.checked, - chaperoneNewProfileIncludeStyle.checked, - chaperoneNewProfileIncludeForceBounds.checked, - chaperoneNewProfileIncludeProximityWarnings.checked) - } - - } - } - function openPopup() { - chaperoneNewProfileName.text = "" - chaperoneNewProfileIncludeGeometry.checked = false - chaperoneNewProfileIncludeVisibility.checked = false - chaperoneNewProfileIncludeFadeDistance.checked = false - chaperoneNewProfileIncludeCenterMarker.checked = false - chaperoneNewProfileIncludePlaySpaceMarker.checked = false - chaperoneNewProfileIncludeFloorBoundsMarker.checked = false - chaperoneNewProfileIncludeBoundsColor.checked = false - chaperoneNewProfileIncludeStyle.checked = false - chaperoneNewProfileIncludeForceBounds.checked = false - chaperoneNewProfileIncludeProximityWarnings.checked = false - open() - } - } - - content: ColumnLayout { + Layout.fillWidth: true spacing: 30 - MyText { + RowLayout { + spacing: 30 Layout.fillWidth: true - wrap: true - text: "Give the following 4 digit PIN to the person that is sending you Wownero. PIN's are valid for 5 minutes and automatically renew." - } - ColumnLayout { - MyText { - visible: false - fontSize: 14 - text: "Currently generating PIN." - } + ColumnLayout { + spacing: 20 + Layout.fillWidth: true + + Rectangle { + color: "transparent" + Layout.fillWidth: true + Layout.preferredHeight: 120 - Text { - visible: true - text: "0 0 0 0" - color: "#ffffff" - font.bold: true - font.pointSize: 40 - leftPadding: 20 - rightPadding: 20 + MyText { + width: parent.width + wrap: true + fontSize: 14 + text: "Give the following 4 digit PIN to the person that is sending you Wownero. PIN's are valid for 10 minutes and automatically renew." + } + } Rectangle { - z: parent.z - 1 - anchors.fill: parent - color: "black" + color: "transparent" + Layout.fillWidth: true + Layout.preferredHeight: 220 + + ColumnLayout { + spacing: 20 + MyText { + id: statusText + width: parent.width + visible: true + fontSize: 14 + text: "Generating PIN..." + } + + Text { + id: pinText + visible: false + text: "- - - -" + color: "#ffffff" + font.bold: true + font.pointSize: 40 + leftPadding: 20 + rightPadding: 20 + + Rectangle { + z: parent.z - 1 + anchors.fill: parent + color: "black" + } + } + } } - } - MyText { - id: expireText - visible: true - fontSize: 14 - text: "Expires in 40 seconds." + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } } + Rectangle { + color: "#cccccc" + width: 1 + Layout.fillHeight: true + } - } + ColumnLayout { + Layout.fillWidth: true - Rectangle { - color: "#cccccc" - height: 1 - Layout.topMargin: 10 - Layout.fillWidth: true - } + Rectangle { + color: "transparent" + Layout.fillWidth: true + Layout.preferredHeight: 80 + Layout.bottomMargin: 20 + + MyText { + width: parent.width + fontSize: 14 + wrap: true + text: "Alternatively, you may use one of the following methods to retreive your address." + } + } - MyText { - Layout.fillWidth: true - wrap: true - text: "Alternatively, you may use one of the following methods." - } + MyPushButton { + id: viewAddress + text: "View address" + Layout.preferredHeight: 70 + Layout.fillWidth: true - RowLayout { - Layout.topMargin: 10 + onClicked: { + //walletView.push(chaperoneAdditionalPage) + } + } - MyPushButton { - id: viewAddress - text: "View address" - Layout.preferredWidth: 360 + MyPushButton { + id: copyToClipboard + text: "Copy address to clipboard" + Layout.preferredHeight: 70 + Layout.fillWidth: true - onClicked: { - MyResources.playFocusChangedSound() - walletView.push(chaperoneAdditionalPage) + onClicked: { + MyResources.playFocusChangedSound() + walletView.push(chaperoneAdditionalPage) + } } - } - MyPushButton { - id: copyToClipboard - text: "Copy address to clipboard" - Layout.preferredWidth: 540 + MyPushButton { + id: writeQRcode + text: "Save QR image" + Layout.preferredHeight: 70 + Layout.fillWidth: true - onClicked: { - MyResources.playFocusChangedSound() - walletView.push(chaperoneAdditionalPage) + onClicked: { + chaperoneNewProfileDialog.open(); + } } - } - - MyPushButton { - id: writeQRcode - text: "QR image" - Layout.preferredWidth: 340 - onClicked: { - chaperoneNewProfileDialog.open(); + Item { + Layout.fillHeight: true + Layout.fillWidth: true } } } @@ -262,5 +147,58 @@ MyStackViewPage { function onPageCompleted() { console.log("onPageCompleted() ReceivePage") + pinAskTimer.start(); + askReceivingPIN(); + } + + function resetPage() { + pinAskTimer.stop(); + statusText.visible = true; + statusText.text = "Generating PIN..."; + pinText.visible = false; + pinText.text = "- - - -"; + } + + onBackClicked: { + resetPage(); + } + + Timer { + id: pinAskTimer + interval: 1000 * 5; + running: false; + repeat: true + onTriggered: askReceivingPIN() + triggeredOnStart: false + } + + function askReceivingPIN() { + ctx.onAskReceivingPIN(); + } + + Connections { + target: ctx + + function onPinReceived(pin) { + console.log("onPINReceived", pin); + statusText.visible = false; + pinText.visible = true; + pinText.text = pin[0] + " " + pin[1] + " " + pin[2] + " " + pin[3]; + } + } + + Connections { + target: OverlayController + + function onDashboardDeactivated() { + console.log("onDashboardDeactivated()") + pinAskTimer.stop(); + } + + function onDashboardActivated() { + console.log("onDashboardActivated()") + if(walletView.currentItem == root) + pinAskTimer.start(); + } } } diff --git a/src/vr/qml/wallet/WalletDashBoardPage.qml b/src/vr/qml/wallet/WalletDashBoardPage.qml index 35b4730..86a6b4c 100644 --- a/src/vr/qml/wallet/WalletDashBoardPage.qml +++ b/src/vr/qml/wallet/WalletDashBoardPage.qml @@ -6,8 +6,6 @@ import QtQuick.Window 2.0 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.2 -// import ovrwow.wowletvr 1.0 - import "../common" import "." @@ -63,6 +61,7 @@ MyStackViewPage { } walletView.push(receivePage) + receivePage.onPageCompleted(); } } @@ -74,7 +73,7 @@ MyStackViewPage { Layout.fillWidth: true onClicked: { //MyResources.playFocusChangedSound() - ctx.closeWallet(true, true); + ctx.onCloseWallet(true, true); mainView.pop(); } } diff --git a/src/vr/qml/wallet/send/SendPage.qml b/src/vr/qml/wallet/send/SendPage.qml index 06679a0..4b1000b 100755 --- a/src/vr/qml/wallet/send/SendPage.qml +++ b/src/vr/qml/wallet/send/SendPage.qml @@ -11,7 +11,7 @@ MyStackViewPage { width: 1600 headerText: "Send" - property string destinationAddress: "cool_addy_here" + property string destinationAddress: "" property string enteredColor: "#365473" property string exitedColor: "#2c435d" @@ -102,14 +102,6 @@ MyStackViewPage { } } - // Connections { - // target: sendStateView.dashPage - // function onTest() { - // sendStack.push(pinPage) - // pinPage.onPageCompleted(); - // } - // } - function onPageCompleted(previousView){ sendStateView.state = "dashPage" } diff --git a/src/vr/qml/wallet/send/SendPagePIN.qml b/src/vr/qml/wallet/send/SendPagePIN.qml index 04dd83c..70934a2 100644 --- a/src/vr/qml/wallet/send/SendPagePIN.qml +++ b/src/vr/qml/wallet/send/SendPagePIN.qml @@ -10,24 +10,6 @@ ColumnLayout { Layout.fillWidth: true property string _PINLookup: "" - property int lookupTimeoutSecs: 5; - property int lookupTimeoutCounter: 2; - - Timer { - id: lookupTimer - interval: 1000; - running: false; - repeat: true; - - onTriggered: { - lookupTimeoutCounter -= 1; - - if(lookupTimeoutCounter === 0) { - stop(); - root.onLookupTimeout(); - } - } - } MyText { Layout.fillWidth: true @@ -153,20 +135,6 @@ ColumnLayout { text: _PINLookup } } - - RowLayout { - spacing: 30 - Layout.fillWidth: true - - MyText { - fontBold: true - text: "Timeout:" - } - - MyText { - text: lookupTimeoutCounter + " seconds" - } - } } // Image { @@ -227,35 +195,18 @@ ColumnLayout { numPad.enabled = false; - lookupTimer.start(); - } - - function onLookupTimeout() { - reset(); - messagePopup.showMessage("Lookup failed", "Error getting address.") - sendStateView.state = "transferPage"; + ctx.onLookupReceivingPIN(code); } function onPageCompleted(previousView) { reset(); } - function onWSPINAdressReceived(pin_code, address) { - // address received from websockets - if(pin_code === _PINLookup) { - sendStateController.destinationAddress = address; - sendStateView.state = "transferPage"; - } else { - console.log("PIN lookup received but we timed out already, disregard.") - } - } function reset() { // reset state _PINLookup = ""; - lookupTimer.stop(); - lookupTimeoutCounter = lookupTimeoutSecs; idleContainer.visible = true; foundContainer.visible = false; loadingContainer.visible = false; @@ -266,4 +217,25 @@ ColumnLayout { codeDisplay.text = "0 0 0 0"; } + + Connections { + target: ctx + + function onPinLookupReceived(address, pin) { + console.log("onPinLookupReceived", address); + + if(pin === _PINLookup) { + sendStateController.destinationAddress = address; + sendStateView.state = "transferPage"; + } else { + console.log("PIN lookup received but we timed out already, disregard.") // undefined behavior + } + } + + function onPinLookupErrorReceived() { + console.log("onPinLookupErrorReceived"); + messagePopup.showMessage("Lookup failed", "Error getting address.") + reset(); + } + } } \ No newline at end of file diff --git a/src/vr/qml/wallet/send/SendPageTransfer.qml b/src/vr/qml/wallet/send/SendPageTransfer.qml index ede8a69..c0ee2ff 100644 --- a/src/vr/qml/wallet/send/SendPageTransfer.qml +++ b/src/vr/qml/wallet/send/SendPageTransfer.qml @@ -133,7 +133,7 @@ ColumnLayout { Layout.preferredHeight: 48 MyText { - text: "Wo3ige...YegEia2" + text: destinationAddress anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right } @@ -171,7 +171,7 @@ ColumnLayout { text: "Enter amount via virtual keyboard" onClicked: { - OverlayController.showKeyboard(text, "1337") + OverlayController.showKeyboard(text, 1337) } } @@ -193,8 +193,9 @@ ColumnLayout { Connections { target: OverlayController + function onKeyBoardInputSignal(input, userValue) { - if (userValue == "1337") { + if (userValue == 1337) { let val = parseFloat(input); myNumPadSendAmount.onAmountUpdated(val); } diff --git a/src/widgets/suchwowwidget.cpp b/src/widgets/suchwowwidget.cpp index c3792a7..bb46257 100644 --- a/src/widgets/suchwowwidget.cpp +++ b/src/widgets/suchwowwidget.cpp @@ -19,6 +19,7 @@ SuchWowPost::SuchWowPost(AppContext *ctx, QObject *parent) : m_ctx(ctx) { m_networkImg = new UtilsNetworking(m_ctx->network, this); m_networkThumb = new UtilsNetworking(m_ctx->network, this); + m_weburl = QString("http://%1/suchwow").arg(this->m_ctx->wsUrl); } void SuchWowPost::onThumbReceived(QByteArray data) { diff --git a/src/widgets/suchwowwidget.h b/src/widgets/suchwowwidget.h index 802a845..543936e 100644 --- a/src/widgets/suchwowwidget.h +++ b/src/widgets/suchwowwidget.h @@ -57,8 +57,7 @@ signals: void thumbReceived(SuchWowPost *test); private: - // @TODO: Replace url - QString m_weburl = "http://feathercitimllbmdktu6cmjo3fizgmyfrntntqzu6xguqa2rlq5cgid.onion/suchwow"; + QString m_weburl; AppContext *m_ctx = nullptr; UtilsNetworking *m_networkThumb = nullptr; UtilsNetworking *m_networkImg = nullptr; diff --git a/src/wizard/walletwizard.cpp b/src/wizard/walletwizard.cpp index 7613bcc..8cf9b8e 100644 --- a/src/wizard/walletwizard.cpp +++ b/src/wizard/walletwizard.cpp @@ -42,7 +42,7 @@ WalletWizard::WalletWizard(AppContext *ctx, WalletWizard::Page startPage, QWidge setStartId(Page_Menu); setButtonText(QWizard::CancelButton, "Close"); - setPixmap(QWizard::WatermarkPixmap, QPixmap(":/assets/images/photos/wow20.png")); + setPixmap(QWizard::WatermarkPixmap, QPixmap(":/assets/images/photos/wow40.png")); setWizardStyle(WizardStyle::ModernStyle); setOption(QWizard::NoBackButtonOnStartPage);