From 493e290956453ad068aa43b9a2fbefacd3550192 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 3 Jun 2016 17:30:19 +0300 Subject: libwallet integration --- src/libwalletqt/WalletManager.cpp | 116 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/libwalletqt/WalletManager.cpp (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp new file mode 100644 index 00000000..cb0ffbac --- /dev/null +++ b/src/libwalletqt/WalletManager.cpp @@ -0,0 +1,116 @@ +#include "WalletManager.h" +#include "Wallet.h" +#include "wallet/wallet2_api.h" +#include +#include +#include +#include +#include + +WalletManager * WalletManager::m_instance = nullptr; + + + + + +WalletManager *WalletManager::instance() +{ + if (!m_instance) { + m_instance = new WalletManager; + } + // Checking linkage (doesn't work, TODO: have every dependencies linked statically into libwallet) + Bitmonero::WalletManager * wallet_manager_impl = Bitmonero::WalletManagerFactory::getWalletManager(); + + return m_instance; +} + +Wallet *WalletManager::createWallet(const QString &path, const QString &password, + const QString &language) +{ + QFileInfo fi(path); + if (fi.exists()) { + qCritical("%s: already exists", __FUNCTION__); + // TODO: set error and error string + // return nullptr; + } + Wallet * wallet = new Wallet(path, password, language); + return wallet; +} + +Wallet *WalletManager::openWallet(const QString &path, const QString &language, const QString &password) +{ + QFileInfo fi(path); + if (fi.exists()) { + qCritical("%s: not exists", __FUNCTION__); + // TODO: set error and error string + // return nullptr; + } + // TODO: call the libwallet api here; + Wallet * wallet = new Wallet(path, password, language); + + return wallet; +} + +Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, const QString &language) +{ + // TODO: call the libwallet api here; + + return nullptr; +} + +bool WalletManager::moveWallet(const QString &src, const QString &dst_) +{ + // TODO: move this to libwallet; + QFile walletFile(src); + if (!walletFile.exists()) { + qWarning("%s: source file [%s] doesn't exits", __FUNCTION__, + qPrintable(src)); + return false; + } + QString dst = QUrl(dst_).toLocalFile(); + QString walletKeysFile = src + ".keys"; + QString walletAddressFile = src + ".address.txt"; + + QString dstWalletKeysFile = dst + ".keys"; + QString dstWalletAddressFile = dst + ".address.txt"; + + if (!walletFile.rename(dst)) { + qWarning("Error renaming file: '%s' to '%s' : (%s)", + qPrintable(src), + qPrintable(dst), + qPrintable(walletFile.errorString())); + return false; + } + QFile::rename(walletKeysFile, dstWalletKeysFile); + QFile::rename(walletAddressFile, dstWalletAddressFile); + + return QFile::exists(dst) && QFile::exists(dstWalletKeysFile) + && QFile::exists(dstWalletAddressFile); +} + +void WalletManager::closeWallet(Wallet *wallet) +{ + delete wallet; +} + +QString WalletManager::walletLanguage(const QString &locale) +{ + return "English"; +} + +int WalletManager::error() const +{ + return 0; +} + +QString WalletManager::errorString() const +{ + return tr("Unknown error"); +} + +WalletManager::WalletManager(QObject *parent) : QObject(parent) +{ + +} + + -- cgit v1.2.3 From da1b74a707da4e21a1c749c372ab9c8b1df1e5e1 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Tue, 7 Jun 2016 16:26:25 +0300 Subject: Start in normal mode if wallet exists. Resolves #9 --- main.cpp | 4 +- main.qml | 11 +++ src/libwalletqt/Wallet.cpp | 173 +++++--------------------------------- src/libwalletqt/Wallet.h | 34 +++++--- src/libwalletqt/WalletManager.cpp | 92 ++++++++------------ src/libwalletqt/WalletManager.h | 33 +++++--- 6 files changed, 111 insertions(+), 236 deletions(-) (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/main.cpp b/main.cpp index b486c5f0..6c529ed0 100644 --- a/main.cpp +++ b/main.cpp @@ -44,8 +44,8 @@ int main(int argc, char *argv[]) app.installEventFilter(eventFilter); qmlRegisterType("moneroComponents", 1, 0, "Clipboard"); - //qmlRegisterType("moneroWallet", 1, 0, "Wallet"); - qmlRegisterType(); + qmlRegisterInterface("Wallet"); + QQmlApplicationEngine engine; diff --git a/main.qml b/main.qml index c1a1d5ec..a36a3755 100644 --- a/main.qml +++ b/main.qml @@ -110,6 +110,15 @@ ApplicationWindow { } + function walletsFound() { + var wallets = walletManager.findWallets(moneroAccountsDir); + if (wallets.length === 0) { + wallets = walletManager.findWallets(applicationDirectory); + } + print(wallets); + return wallets.length > 0; + } + visible: true width: rightPanelExpanded ? 1269 : 1269 - 300 height: 800 @@ -120,6 +129,8 @@ ApplicationWindow { Component.onCompleted: { x = (Screen.width - width) / 2 y = (Screen.height - height) / 2 + // + rootItem.state = walletsFound() ? "normal" : "wizard"; } Item { diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 61998ab5..2ede062c 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -1,194 +1,61 @@ #include "Wallet.h" +#include "wallet/wallet2_api.h" + #include #include #include #include namespace { - QString TEST_SEED = "bound class paint gasp task soul forgot past pleasure physical circle " - " appear shore bathroom glove women crap busy beauty bliss idea give needle burden"; - - namespace { - bool createFileWrapper(const QString &filename) - { - QFile file(filename); - // qDebug("%s: about to create file: %s", __FUNCTION__, qPrintable(filename)); - bool result = file.open(QIODevice::WriteOnly); - if (!result ){ - qWarning("%s: error creating file '%s' : '%s'", - __FUNCTION__, - qPrintable(filename), - qPrintable(file.errorString())); - } - return result; - } - } - -} - -struct WalletImpl -{ - - QString basename() const; - void setBasename(const QString &name); - - QString keysName() const; - QString addressName() const; -// Bitmonero::Wallet * m_walletImpl; - QString m_basename; - QString m_seed; - QString m_password; - QString m_language; - static QString keysName(const QString &basename); - static QString addressName(const QString &basename); - -}; - - -QString WalletImpl::basename() const -{ - return m_basename; } -void WalletImpl::setBasename(const QString &name) -{ - m_basename = name; -} -QString WalletImpl::keysName() const -{ - return keysName(m_basename); -} - -QString WalletImpl::addressName() const -{ - return addressName(m_basename); -} - -QString WalletImpl::keysName(const QString &basename) +QString Wallet::getSeed() const { - return basename + ".keys"; + return QString::fromStdString(m_walletImpl->seed()); } -QString WalletImpl::addressName(const QString &basename) +QString Wallet::getSeedLanguage() const { - return basename + ".address.txt"; + return QString::fromStdString(m_walletImpl->getSeedLanguage()); } - -Wallet::Wallet(QObject *parent) - : QObject(parent) +int Wallet::status() const { - + return m_walletImpl->status(); } -QString Wallet::getSeed() const -{ - return m_pimpl->m_seed; -} - -QString Wallet::getSeedLanguage() const +QString Wallet::errorString() const { - return "English"; + return QString::fromStdString(m_walletImpl->errorString()); } -//void Wallet::setSeedLaguage(const QString &lang) -//{ -// // TODO: call libwallet's appropriate method -//} - bool Wallet::setPassword(const QString &password) { - // set/change password implies: - // recovery wallet with existing path, seed and lang - qDebug("%s: recovering wallet with path=%s, seed=%s, lang=%s and new password=%s", - __FUNCTION__, - qPrintable(this->getBasename()), - qPrintable(this->getSeed()), - qPrintable(this->getSeedLanguage()), - qPrintable(password)); - return true; + return m_walletImpl->setPassword(password.toStdString()); } -QString Wallet::getPassword() const +QString Wallet::address() const { - return m_pimpl->m_password; + return QString::fromStdString(m_walletImpl->address()); } -bool Wallet::rename(const QString &name) +bool Wallet::store(const QString &path) { - - QString dst = QUrl(name).toLocalFile(); - - if (dst.isEmpty()) - dst = name; - - qDebug("%s: renaming '%s' to '%s'", - __FUNCTION__, - qPrintable(m_pimpl->basename()), - qPrintable(dst)); - - QString walletKeysFile = m_pimpl->keysName(); - QString walletAddressFile = m_pimpl->addressName(); - - QString dstWalletKeysFile = WalletImpl::keysName(dst); - QString dstWalletAddressFile = WalletImpl::addressName(dst); - - QFile walletFile(this->getBasename()); - - if (!walletFile.rename(dst)) { - qWarning("Error renaming file: '%s' to '%s' : (%s)", - qPrintable(m_pimpl->basename()), - qPrintable(dst), - qPrintable(walletFile.errorString())); - return false; - } - QFile::rename(walletKeysFile, dstWalletKeysFile); - QFile::rename(walletAddressFile, dstWalletAddressFile); - - bool result = QFile::exists(dst) && QFile::exists(dstWalletKeysFile) - && QFile::exists(dstWalletAddressFile); - - if (result) { - m_pimpl->m_basename = dst; - } - - return result; + return m_walletImpl->store(path.toStdString()); } -QString Wallet::getBasename() const -{ - return m_pimpl->basename(); -} -int Wallet::error() const -{ - return 0; -} -QString Wallet::errorString() const +Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent) + : QObject(parent), m_walletImpl(w) { - return m_pimpl->m_seed; + } -Wallet::Wallet(const QString &path, const QString &password, const QString &language) +Wallet::~Wallet() { - m_pimpl = new WalletImpl; - m_pimpl->m_basename = path; - m_pimpl->m_password = password; - m_pimpl->m_language = language; - m_pimpl->m_seed = TEST_SEED; - - // Create dummy files for testing - QFileInfo fi(path); - QDir tempDir; - tempDir.mkpath(fi.absolutePath()); - createFileWrapper(m_pimpl->basename()); - createFileWrapper(m_pimpl->keysName()); - createFileWrapper(m_pimpl->addressName()); + Bitmonero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl); } - - - diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 221d3d43..79655cb4 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -3,13 +3,18 @@ #include -struct WalletImpl; +namespace Bitmonero { + class Wallet; // forward declaration +} class Wallet : public QObject { Q_OBJECT Q_PROPERTY(QString seed READ getSeed) public: - explicit Wallet(QObject *parent = 0); + enum Status { + Status_Ok = 0, + Status_Error = 1 + }; //! returns mnemonic seed Q_INVOKABLE QString getSeed() const; @@ -17,28 +22,31 @@ public: //! returns seed language Q_INVOKABLE QString getSeedLanguage() const; + //! returns last operation's status + Q_INVOKABLE int status() const; + + //! returns last operation's error message + Q_INVOKABLE QString errorString() const; //! changes the password using existing parameters (path, seed, seed lang) Q_INVOKABLE bool setPassword(const QString &password); - //! returns curret wallet password - Q_INVOKABLE QString getPassword() const; - //! renames/moves wallet files - Q_INVOKABLE bool rename(const QString &name); + //! returns wallet's public address + Q_INVOKABLE QString address() const; + + //! saves wallet to the file by given path + Q_INVOKABLE bool store(const QString &path); - //! returns current wallet name (basename, as wallet consists of several files) - Q_INVOKABLE QString getBasename() const; - Q_INVOKABLE int error() const; - Q_INVOKABLE QString errorString() const; private: - Wallet(const QString &path, const QString &password, const QString &language); + Wallet(Bitmonero::Wallet *w, QObject * parent = 0); + ~Wallet(); private: friend class WalletManager; - //! pimpl wrapper for libwallet; - WalletImpl * m_pimpl; + //! libwallet's + Bitmonero::Wallet * m_walletImpl; }; #endif // WALLET_H diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index cb0ffbac..646e47f5 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -7,6 +7,8 @@ #include #include + + WalletManager * WalletManager::m_instance = nullptr; @@ -18,89 +20,55 @@ WalletManager *WalletManager::instance() if (!m_instance) { m_instance = new WalletManager; } - // Checking linkage (doesn't work, TODO: have every dependencies linked statically into libwallet) - Bitmonero::WalletManager * wallet_manager_impl = Bitmonero::WalletManagerFactory::getWalletManager(); return m_instance; } Wallet *WalletManager::createWallet(const QString &path, const QString &password, - const QString &language) + const QString &language, bool testnet) { - QFileInfo fi(path); - if (fi.exists()) { - qCritical("%s: already exists", __FUNCTION__); - // TODO: set error and error string - // return nullptr; - } - Wallet * wallet = new Wallet(path, password, language); + Bitmonero::Wallet * w = m_pimpl->createWallet(path.toStdString(), password.toStdString(), + language.toStdString(), testnet); + Wallet * wallet = new Wallet(w); return wallet; } -Wallet *WalletManager::openWallet(const QString &path, const QString &language, const QString &password) +Wallet *WalletManager::openWallet(const QString &path, const QString &password, bool testnet) { - QFileInfo fi(path); - if (fi.exists()) { - qCritical("%s: not exists", __FUNCTION__); - // TODO: set error and error string - // return nullptr; - } // TODO: call the libwallet api here; - Wallet * wallet = new Wallet(path, password, language); + Bitmonero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet); + Wallet * wallet = new Wallet(w); return wallet; } -Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, const QString &language) -{ - // TODO: call the libwallet api here; - - return nullptr; -} -bool WalletManager::moveWallet(const QString &src, const QString &dst_) +Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, bool testnet) { - // TODO: move this to libwallet; - QFile walletFile(src); - if (!walletFile.exists()) { - qWarning("%s: source file [%s] doesn't exits", __FUNCTION__, - qPrintable(src)); - return false; - } - QString dst = QUrl(dst_).toLocalFile(); - QString walletKeysFile = src + ".keys"; - QString walletAddressFile = src + ".address.txt"; - - QString dstWalletKeysFile = dst + ".keys"; - QString dstWalletAddressFile = dst + ".address.txt"; - - if (!walletFile.rename(dst)) { - qWarning("Error renaming file: '%s' to '%s' : (%s)", - qPrintable(src), - qPrintable(dst), - qPrintable(walletFile.errorString())); - return false; - } - QFile::rename(walletKeysFile, dstWalletKeysFile); - QFile::rename(walletAddressFile, dstWalletAddressFile); - - return QFile::exists(dst) && QFile::exists(dstWalletKeysFile) - && QFile::exists(dstWalletAddressFile); + Bitmonero::Wallet * w = m_pimpl->recoveryWallet(path.toStdString(), memo.toStdString(), testnet); + Wallet * wallet = new Wallet(w); + return wallet; } + void WalletManager::closeWallet(Wallet *wallet) { delete wallet; } -QString WalletManager::walletLanguage(const QString &locale) +bool WalletManager::walletExists(const QString &path) const { - return "English"; + return m_pimpl->walletExists(path.toStdString()); } -int WalletManager::error() const +QStringList WalletManager::findWallets(const QString &path) { - return 0; + std::vector found_wallets = m_pimpl->findWallets(path.toStdString()); + QStringList result; + for (const auto &w : found_wallets) { + result.append(QString::fromStdString(w)); + } + return result; } QString WalletManager::errorString() const @@ -108,9 +76,21 @@ QString WalletManager::errorString() const return tr("Unknown error"); } -WalletManager::WalletManager(QObject *parent) : QObject(parent) +bool WalletManager::moveWallet(const QString &src, const QString &dst) { + return true; +} + +QString WalletManager::walletLanguage(const QString &locale) +{ + return "English"; +} + + +WalletManager::WalletManager(QObject *parent) : QObject(parent) +{ + m_pimpl = Bitmonero::WalletManagerFactory::getWalletManager(); } diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index 231f104c..c40fec54 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -4,6 +4,9 @@ #include class Wallet; +namespace Bitmonero { + class WalletManager; +} class WalletManager : public QObject { @@ -12,37 +15,43 @@ public: static WalletManager * instance(); // wizard: createWallet path; Q_INVOKABLE Wallet * createWallet(const QString &path, const QString &password, - const QString &language); + const QString &language, bool testnet = false); // just for future use - Q_INVOKABLE Wallet * openWallet(const QString &path, const QString &language, - const QString &password); + Q_INVOKABLE Wallet * openWallet(const QString &path, const QString &password, bool testnet = false); // wizard: recoveryWallet path; hint: internally it recorvers wallet and set password = "" Q_INVOKABLE Wallet * recoveryWallet(const QString &path, const QString &memo, - const QString &language); - - // wizard: both "create" and "recovery" paths. - // TODO: probably move it to "Wallet" interface - Q_INVOKABLE bool moveWallet(const QString &src, const QString &dst); + bool testnet = false); //! utils: close wallet to free memory Q_INVOKABLE void closeWallet(Wallet * wallet); - //! returns libwallet language name for given locale - Q_INVOKABLE QString walletLanguage(const QString &locale); + //! checks is given filename is a wallet; + Q_INVOKABLE bool walletExists(const QString &path) const; - //! returns last error happened in WalletManager - Q_INVOKABLE int error() const; + //! returns list with wallet's filenames, if found by given path + Q_INVOKABLE QStringList findWallets(const QString &path); //! returns error description in human language Q_INVOKABLE QString errorString() const; + + + // wizard: both "create" and "recovery" paths. + // TODO: probably move it to "Wallet" interface + Q_INVOKABLE bool moveWallet(const QString &src, const QString &dst); + //! returns libwallet language name for given locale + Q_INVOKABLE QString walletLanguage(const QString &locale); + signals: public slots: private: + explicit WalletManager(QObject *parent = 0); static WalletManager * m_instance; + Bitmonero::WalletManager * m_pimpl; + }; #endif // WALLETMANAGER_H -- cgit v1.2.3 From 5c10be325103d668884fc5e463aaa59c726d4f8e Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Wed, 8 Jun 2016 13:53:24 +0300 Subject: Qt wrappers for libwallet API classes --- monero-core.pro | 10 ++++-- src/libwalletqt/PendingTransaction.cpp | 37 +++++++++++++++++++ src/libwalletqt/PendingTransaction.h | 41 +++++++++++++++++++++ src/libwalletqt/TransactionHistory.cpp | 50 ++++++++++++++++++++++++++ src/libwalletqt/TransactionHistory.h | 42 ++++++++++++++++++++++ src/libwalletqt/TransactionInfo.cpp | 55 ++++++++++++++++++++++++++++ src/libwalletqt/TransactionInfo.h | 54 ++++++++++++++++++++++++++++ src/libwalletqt/Wallet.cpp | 66 ++++++++++++++++++++++++++++++++-- src/libwalletqt/Wallet.h | 63 ++++++++++++++++++++++++++++---- src/libwalletqt/WalletManager.cpp | 5 +++ src/libwalletqt/WalletManager.h | 3 ++ 11 files changed, 414 insertions(+), 12 deletions(-) create mode 100644 src/libwalletqt/PendingTransaction.cpp create mode 100644 src/libwalletqt/PendingTransaction.h create mode 100644 src/libwalletqt/TransactionHistory.cpp create mode 100644 src/libwalletqt/TransactionHistory.h create mode 100644 src/libwalletqt/TransactionInfo.cpp create mode 100644 src/libwalletqt/TransactionInfo.h (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/monero-core.pro b/monero-core.pro index 7b05829f..f521c9ec 100644 --- a/monero-core.pro +++ b/monero-core.pro @@ -15,7 +15,10 @@ HEADERS += \ clipboardAdapter.h \ oscursor.h \ src/libwalletqt/WalletManager.h \ - src/libwalletqt/Wallet.h + src/libwalletqt/Wallet.h \ + src/libwalletqt/PendingTransaction.h \ + src/libwalletqt/TransactionHistory.h \ + src/libwalletqt/TransactionInfo.h SOURCES += main.cpp \ @@ -23,7 +26,10 @@ SOURCES += main.cpp \ clipboardAdapter.cpp \ oscursor.cpp \ src/libwalletqt/WalletManager.cpp \ - src/libwalletqt/Wallet.cpp + src/libwalletqt/Wallet.cpp \ + src/libwalletqt/PendingTransaction.cpp \ + src/libwalletqt/TransactionHistory.cpp \ + src/libwalletqt/TransactionInfo.cpp lupdate_only { SOURCES = *.qml \ diff --git a/src/libwalletqt/PendingTransaction.cpp b/src/libwalletqt/PendingTransaction.cpp new file mode 100644 index 00000000..a5dc458d --- /dev/null +++ b/src/libwalletqt/PendingTransaction.cpp @@ -0,0 +1,37 @@ +#include "PendingTransaction.h" + +PendingTransaction::Status PendingTransaction::status() const +{ + return static_cast(m_pimpl->status()); +} + +QString PendingTransaction::errorString() const +{ + return QString::fromStdString(m_pimpl->errorString()); +} + +bool PendingTransaction::commit() +{ + return m_pimpl->commit(); +} + +quint64 PendingTransaction::amount() const +{ + return m_pimpl->amount(); +} + +quint64 PendingTransaction::dust() const +{ + return m_pimpl->dust(); +} + +quint64 PendingTransaction::fee() const +{ + return m_pimpl->fee(); +} + +PendingTransaction::PendingTransaction(Bitmonero::PendingTransaction *pt, QObject *parent) + : QObject(parent), m_pimpl(pt) +{ + +} diff --git a/src/libwalletqt/PendingTransaction.h b/src/libwalletqt/PendingTransaction.h new file mode 100644 index 00000000..29fa7cb4 --- /dev/null +++ b/src/libwalletqt/PendingTransaction.h @@ -0,0 +1,41 @@ +#ifndef PENDINGTRANSACTION_H +#define PENDINGTRANSACTION_H + +#include + +#include + +//namespace Bitmonero { +//class PendingTransaction; +//} + +class PendingTransaction : public QObject +{ + Q_OBJECT + Q_PROPERTY(Status status READ status) + Q_PROPERTY(QString errorString READ errorString) + Q_PROPERTY(quint64 amount READ amount) + Q_PROPERTY(quint64 dust READ dust) + Q_PROPERTY(quint64 fee READ fee) + +public: + enum Status { + Status_Ok = Bitmonero::PendingTransaction::Status_Ok, + Status_Error = Bitmonero::PendingTransaction::Status_Error + }; + + Status status() const; + QString errorString() const; + Q_INVOKABLE bool commit(); + quint64 amount() const; + quint64 dust() const; + quint64 fee() const; +private: + explicit PendingTransaction(Bitmonero::PendingTransaction * pt, QObject *parent = 0); + +private: + friend class Wallet; + Bitmonero::PendingTransaction * m_pimpl; +}; + +#endif // PENDINGTRANSACTION_H diff --git a/src/libwalletqt/TransactionHistory.cpp b/src/libwalletqt/TransactionHistory.cpp new file mode 100644 index 00000000..2c2c9f73 --- /dev/null +++ b/src/libwalletqt/TransactionHistory.cpp @@ -0,0 +1,50 @@ +#include "TransactionHistory.h" +#include "TransactionInfo.h" +#include + + +int TransactionHistory::count() const +{ + return m_pimpl->count(); +} + +TransactionInfo *TransactionHistory::transaction(int index) +{ + // box up Bitmonero::TransactionInfo + Bitmonero::TransactionInfo * impl = m_pimpl->transaction(index); + TransactionInfo * result = new TransactionInfo(impl, this); + return result; +} + +TransactionInfo *TransactionHistory::transaction(const QString &id) +{ + // box up Bitmonero::TransactionInfo + Bitmonero::TransactionInfo * impl = m_pimpl->transaction(id.toStdString()); + TransactionInfo * result = new TransactionInfo(impl, this); + return result; +} + +QList TransactionHistory::getAll() const +{ + qDeleteAll(m_tinfo); + m_tinfo.clear(); + TransactionHistory * parent = const_cast(this); + for (const auto i : m_pimpl->getAll()) { + TransactionInfo * ti = new TransactionInfo(i, parent); + m_tinfo.append(ti); + } + return m_tinfo; +} + +void TransactionHistory::refresh() +{ + // XXX this invalidates previously saved history that might be used by clients + m_pimpl->refresh(); + emit invalidated(); +} + +TransactionHistory::TransactionHistory(Bitmonero::TransactionHistory *pimpl, QObject *parent) + : QObject(parent), m_pimpl(pimpl) +{ + +} diff --git a/src/libwalletqt/TransactionHistory.h b/src/libwalletqt/TransactionHistory.h new file mode 100644 index 00000000..a6287506 --- /dev/null +++ b/src/libwalletqt/TransactionHistory.h @@ -0,0 +1,42 @@ +#ifndef TRANSACTIONHISTORY_H +#define TRANSACTIONHISTORY_H + +#include +#include + +namespace Bitmonero { +class TransactionHistory; +} + +class TransactionInfo; + +class TransactionHistory : public QObject +{ + Q_OBJECT + Q_PROPERTY(int count READ count) + +public: + int count() const; + Q_INVOKABLE TransactionInfo *transaction(int index); + Q_INVOKABLE TransactionInfo * transaction(const QString &id); + Q_INVOKABLE QList getAll() const; + Q_INVOKABLE void refresh(); + +signals: + void invalidated(); + +public slots: + + +private: + explicit TransactionHistory(Bitmonero::TransactionHistory * pimpl, QObject *parent = 0); + +private: + friend class Wallet; + + Bitmonero::TransactionHistory * m_pimpl; + mutable QList m_tinfo; + +}; + +#endif // TRANSACTIONHISTORY_H diff --git a/src/libwalletqt/TransactionInfo.cpp b/src/libwalletqt/TransactionInfo.cpp new file mode 100644 index 00000000..192e85e5 --- /dev/null +++ b/src/libwalletqt/TransactionInfo.cpp @@ -0,0 +1,55 @@ +#include "TransactionInfo.h" +#include + +TransactionInfo::Direction TransactionInfo::direction() const +{ + return static_cast(m_pimpl->direction()); +} + +bool TransactionInfo::isPending() const +{ + return m_pimpl->isPending(); +} + +bool TransactionInfo::isFailed() const +{ + return m_pimpl->isFailed(); +} + +quint64 TransactionInfo::amount() const +{ + return m_pimpl->amount(); +} + +quint64 TransactionInfo::fee() const +{ + return m_pimpl->fee(); + +} + +quint64 TransactionInfo::blockHeight() const +{ + return m_pimpl->blockHeight(); +} + +QString TransactionInfo::hash() const +{ + return QString::fromStdString(m_pimpl->hash()); +} + +QString TransactionInfo::timestamp() +{ + QString result = QDateTime::fromTime_t(m_pimpl->timestamp()).toString(Qt::ISODate); + return result; +} + +QString TransactionInfo::paymentId() +{ + return QString::fromStdString(m_pimpl->paymentId()); +} + +TransactionInfo::TransactionInfo(Bitmonero::TransactionInfo *pimpl, QObject *parent) + : QObject(parent), m_pimpl(pimpl) +{ + +} diff --git a/src/libwalletqt/TransactionInfo.h b/src/libwalletqt/TransactionInfo.h new file mode 100644 index 00000000..62c26e2f --- /dev/null +++ b/src/libwalletqt/TransactionInfo.h @@ -0,0 +1,54 @@ +#ifndef TRANSACTIONINFO_H +#define TRANSACTIONINFO_H + +#include +#include + +class TransactionInfo : public QObject +{ + Q_OBJECT + Q_PROPERTY(Direction direction READ direction) + Q_PROPERTY(bool isPending READ isPending) + Q_PROPERTY(bool isFailed READ isFailed) + Q_PROPERTY(quint64 amount READ amount) + Q_PROPERTY(quint64 fee READ fee) + Q_PROPERTY(quint64 blockHeight READ blockHeight) + Q_PROPERTY(QString hash READ hash) + Q_PROPERTY(QString timestamp READ timestamp) + Q_PROPERTY(QString paymentId READ paymentId) + +public: + enum Direction { + Direction_In = Bitmonero::TransactionInfo::Direction_In, + Direction_Out = Bitmonero::TransactionInfo::Direction_Out + }; + +// TODO: implement as separate class; + +// struct Transfer { +// Transfer(uint64_t _amount, const std::string &address); +// const uint64_t amount; +// const std::string address; +// }; + Direction direction() const; + bool isPending() const; + bool isFailed() const; + quint64 amount() const; + quint64 fee() const; + quint64 blockHeight() const; + //! transaction_id + QString hash() const; + QString timestamp(); + QString paymentId(); + + // TODO: implement it + //! only applicable for output transactions + // virtual const std::vector & transfers() const = 0; +private: + explicit TransactionInfo(Bitmonero::TransactionInfo * pimpl, QObject *parent = 0); +private: + friend class TransactionHistory; + Bitmonero::TransactionInfo * m_pimpl; +}; + +#endif // TRANSACTIONINFO_H diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 2ede062c..77901b0c 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -1,4 +1,6 @@ #include "Wallet.h" +#include "PendingTransaction.h" +#include "TransactionHistory.h" #include "wallet/wallet2_api.h" #include @@ -22,9 +24,14 @@ QString Wallet::getSeedLanguage() const return QString::fromStdString(m_walletImpl->getSeedLanguage()); } -int Wallet::status() const +void Wallet::setSeedLanguage(const QString &lang) { - return m_walletImpl->status(); + m_walletImpl->setSeedLanguage(lang.toStdString()); +} + +Wallet::Status Wallet::status() const +{ + return static_cast(m_walletImpl->status()); } QString Wallet::errorString() const @@ -47,10 +54,63 @@ bool Wallet::store(const QString &path) return m_walletImpl->store(path.toStdString()); } +bool Wallet::init(const QString &daemonAddress, quint64 upperTransactionLimit) +{ + return m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit); +} + +bool Wallet::connectToDaemon() +{ + return m_walletImpl->connectToDaemon(); +} + +void Wallet::setTrustedDaemon(bool arg) +{ + m_walletImpl->setTrustedDaemon(arg); +} + +quint64 Wallet::balance() const +{ + return m_walletImpl->balance(); +} + +quint64 Wallet::unlockedBalance() const +{ + return m_walletImpl->unlockedBalance(); +} + +bool Wallet::refresh() +{ + return m_walletImpl->refresh(); +} + +PendingTransaction *Wallet::createTransaction(const QString &dst_addr, quint64 amount) +{ + Bitmonero::PendingTransaction * ptImpl = m_walletImpl->createTransaction( + dst_addr.toStdString(), amount); + PendingTransaction * result = new PendingTransaction(ptImpl, this); + return result; +} + +void Wallet::disposeTransaction(PendingTransaction *t) +{ + m_walletImpl->disposeTransaction(t->m_pimpl); + delete t; +} + +TransactionHistory *Wallet::history() +{ + if (!m_history) { + Bitmonero::TransactionHistory * impl = m_walletImpl->history(); + m_history = new TransactionHistory(impl, this); + } + return m_history; +} + Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent) - : QObject(parent), m_walletImpl(w) + : QObject(parent), m_walletImpl(w), m_history(nullptr) { } diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 79655cb4..7d391429 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -3,41 +3,88 @@ #include +#include "wallet/wallet2_api.h" // we need to access Status enum here; + namespace Bitmonero { class Wallet; // forward declaration } + +class PendingTransaction; +class TransactionHistory; + class Wallet : public QObject { Q_OBJECT Q_PROPERTY(QString seed READ getSeed) + Q_PROPERTY(QString seedLanguage READ getSeedLanguage) + Q_PROPERTY(Status status READ status) + Q_PROPERTY(QString errorString READ errorString) + Q_PROPERTY(QString address READ address) + Q_PROPERTY(quint64 balance READ balance) + Q_PROPERTY(quint64 unlockedBalance READ unlockedBalance) + Q_PROPERTY(TransactionHistory * history READ history) + public: enum Status { - Status_Ok = 0, - Status_Error = 1 + Status_Ok = Bitmonero::Wallet::Status_Ok, + Status_Error = Bitmonero::Wallet::Status_Error }; + Q_ENUM(Status) + //! returns mnemonic seed - Q_INVOKABLE QString getSeed() const; + QString getSeed() const; //! returns seed language - Q_INVOKABLE QString getSeedLanguage() const; + QString getSeedLanguage() const; + + //! set seed language + Q_INVOKABLE void setSeedLanguage(const QString &lang); //! returns last operation's status - Q_INVOKABLE int status() const; + Status status() const; //! returns last operation's error message - Q_INVOKABLE QString errorString() const; + QString errorString() const; //! changes the password using existing parameters (path, seed, seed lang) Q_INVOKABLE bool setPassword(const QString &password); //! returns wallet's public address - Q_INVOKABLE QString address() const; + QString address() const; //! saves wallet to the file by given path Q_INVOKABLE bool store(const QString &path); + //! initializes wallet + Q_INVOKABLE bool init(const QString &daemonAddress, quint64 upperTransactionLimit); + + //! connects to daemon + Q_INVOKABLE bool connectToDaemon(); + + //! indicates id daemon is trusted + Q_INVOKABLE void setTrustedDaemon(bool arg); + + //! returns balance + quint64 balance() const; + + //! returns unlocked balance + quint64 unlockedBalance() const; + + //! refreshes the wallet + Q_INVOKABLE bool refresh(); + + //! creates transaction + Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, + quint64 amount); + + //! deletes transaction and frees memory + Q_INVOKABLE void disposeTransaction(PendingTransaction * t); + + //! returns transaction history + TransactionHistory * history(); + // TODO: setListenter() when it implemented in API private: Wallet(Bitmonero::Wallet *w, QObject * parent = 0); @@ -47,6 +94,8 @@ private: friend class WalletManager; //! libwallet's Bitmonero::Wallet * m_walletImpl; + // history lifetime managed by wallet; + TransactionHistory * m_history; }; #endif // WALLET_H diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index 646e47f5..6ad81e2a 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -87,6 +87,11 @@ QString WalletManager::walletLanguage(const QString &locale) return "English"; } +QString WalletManager::displayAmount(quint64 amount) +{ + return QString::fromStdString(Bitmonero::Wallet::displayAmount(amount)); +} + WalletManager::WalletManager(QObject *parent) : QObject(parent) { diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index c40fec54..30e6b02a 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -42,6 +42,9 @@ public: //! returns libwallet language name for given locale Q_INVOKABLE QString walletLanguage(const QString &locale); + + //! since we can't call static method from QML, move it to this class + Q_INVOKABLE QString displayAmount(quint64 amount); signals: public slots: -- cgit v1.2.3 From eaf59243b2cbe3d7ea6de1d8dcd18493df9f365d Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Thu, 16 Jun 2016 17:13:46 +0300 Subject: basic "send money" functionality implemented in GUI --- LeftPanel.qml | 2 ++ MiddlePanel.qml | 14 ++++++++++++++ components/LineEdit.qml | 3 +++ main.cpp | 3 +++ main.qml | 25 +++++++++++++++++++++++++ pages/Transfer.qml | 27 +++++++++++++++++++++------ src/libwalletqt/PendingTransaction.h | 2 ++ src/libwalletqt/WalletManager.cpp | 9 +++++++++ src/libwalletqt/WalletManager.h | 3 +++ 9 files changed, 82 insertions(+), 6 deletions(-) (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/LeftPanel.qml b/LeftPanel.qml index 1eddf019..95b5aa6f 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -56,6 +56,7 @@ Rectangle { width: 260 color: "#FFFFFF" + // Item with monero logo Item { id: logoItem anchors.left: parent.left @@ -85,6 +86,7 @@ Rectangle { } } + Column { id: column1 anchors.left: parent.left diff --git a/MiddlePanel.qml b/MiddlePanel.qml index 62072af9..28d6f137 100644 --- a/MiddlePanel.qml +++ b/MiddlePanel.qml @@ -30,6 +30,7 @@ import QtQuick 2.2 Rectangle { color: "#F0EEEE" + signal paymentClicked(string address, string paymentId, double amount, double fee, int privacyLevel) states: [ State { @@ -72,6 +73,19 @@ Rectangle { anchors.right: parent.right anchors.top: styledRow.bottom anchors.bottom: parent.bottom + onLoaded: { + console.log("Loaded " + item); + } + + } + + Connections { + ignoreUnknownSignals: false + target: loader.item + onPaymentClicked : { + console.log("MiddlePanel: paymentClicked") + paymentClicked(address, paymentId, amount, fee, privacyLevel) + } } Rectangle { diff --git a/components/LineEdit.qml b/components/LineEdit.qml index 6994b75f..37c2390d 100644 --- a/components/LineEdit.qml +++ b/components/LineEdit.qml @@ -31,7 +31,9 @@ import QtQuick 2.0 Item { property alias placeholderText: input.placeholderText property alias text: input.text + property alias validator: input.validator property int fontSize: 18 + height: 37 Rectangle { @@ -54,5 +56,6 @@ Item { anchors.leftMargin: 4 anchors.rightMargin: 4 font.pixelSize: parent.fontSize + } } diff --git a/main.cpp b/main.cpp index 7331a4e4..70390a80 100644 --- a/main.cpp +++ b/main.cpp @@ -36,6 +36,7 @@ #include "oshelper.h" #include "WalletManager.h" #include "Wallet.h" +#include "PendingTransaction.h" @@ -53,6 +54,8 @@ int main(int argc, char *argv[]) qmlRegisterType("moneroComponents", 1, 0, "Clipboard"); qmlRegisterUncreatableType("Bitmonero.Wallet", 1, 0, "Wallet", "Wallet can't be instantiated directly"); + qmlRegisterUncreatableType("Bitmonero.PendingTransaction", 1, 0, "PendingTransaction", + "PendingTransaction can't be instantiated directly"); QQmlApplicationEngine engine; diff --git a/main.qml b/main.qml index 3b79d1ec..d6109339 100644 --- a/main.qml +++ b/main.qml @@ -32,6 +32,7 @@ import QtQuick.Controls 1.1 import QtQuick.Controls.Styles 1.1 import Qt.labs.settings 1.0 import Bitmonero.Wallet 1.0 +import Bitmonero.PendingTransaction 1.0 import "components" import "wizard" @@ -120,6 +121,8 @@ ApplicationWindow { function initialize() { + middlePanel.paymentClicked.connect(handlePayment); + if (typeof wizard.settings['wallet'] !== 'undefined') { wallet = wizard.settings['wallet']; } else { @@ -157,6 +160,27 @@ ApplicationWindow { return wallets.length > 0; } + function handlePayment(address, paymentId, amount, fee, privacyLevel) { + console.log("Process payment here: ", address, paymentId, amount, fee, privacyLevel) + // TODO: handle payment id + // TODO: handle fee; + // TODO: handle mixins + var amountxmr = walletManager.amountFromString(amount); + + console.log("integer amount: ", amountxmr); + var pendingTransaction = wallet.createTransaction(address, amountxmr); + if (pendingTransaction.status !== PendingTransaction.Status_Ok) { + console.error("Can't create transaction: ", pendingTransaction.errorString); + } else { + console.log("Transaction created, amount: " + walletManager.displayAmount(pendingTransaction.amount) + + ", fee: " + walletManager.displayAmount(pendingTransaction.fee)); + if (!pendingTransaction.commit()) { + console.log("Error committing transaction: " + pendingTransaction.errorString); + } + } + wallet.disposeTransaction(pendingTransaction); + } + visible: true width: rightPanelExpanded ? 1269 : 1269 - 300 height: 800 @@ -423,6 +447,7 @@ ApplicationWindow { } property var previousPosition + onPressed: { previousPosition = globalCursor.getPosition() } diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 2535b8fe..df0a5b20 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -30,8 +30,11 @@ import QtQuick 2.0 import "../components" Rectangle { + signal paymentClicked(string address, string paymentId, double amount, double fee, int privacyLevel) + color: "#F0EEEE" + Label { id: amountLabel anchors.left: parent.left @@ -67,8 +70,9 @@ Rectangle { source: "../images/moneroIcon.png" } } - + // Amount input LineEdit { + id: amountLine placeholderText: qsTr("Amount...") width: parent.width - 37 - 17 } @@ -133,7 +137,7 @@ Rectangle { onLinkActivated: appWindow.showPageRequest("AddressBook") } - + // recipient address input LineEdit { id: addressLine anchors.left: parent.left @@ -142,10 +146,11 @@ Rectangle { anchors.leftMargin: 17 anchors.rightMargin: 17 anchors.topMargin: 5 + // validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g } } Label { - id: paymentLabel + id: paymentIdLabel anchors.left: parent.left anchors.right: parent.right anchors.top: addressLine.bottom @@ -156,21 +161,23 @@ Rectangle { text: qsTr("Payment ID ( Optional )") } + // payment id input LineEdit { - id: paymentLine + id: paymentIdLine anchors.left: parent.left anchors.right: parent.right - anchors.top: paymentLabel.bottom + anchors.top: paymentIdLabel.bottom anchors.leftMargin: 17 anchors.rightMargin: 17 anchors.topMargin: 5 + // validator: DoubleValidator { top: 0.0 } } Label { id: descriptionLabel anchors.left: parent.left anchors.right: parent.right - anchors.top: paymentLine.bottom + anchors.top: paymentIdLine.bottom anchors.leftMargin: 17 anchors.rightMargin: 17 anchors.topMargin: 17 @@ -200,5 +207,13 @@ Rectangle { shadowPressedColor: "#B32D00" releasedColor: "#FF6C3C" pressedColor: "#FF4304" + onClicked: { + // do more smart validation + + if (addressLine.text.length > 0 && amountLine.text.length > 0) { + console.log("paymentClicked") + paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, 0.0002, 1) + } + } } } diff --git a/src/libwalletqt/PendingTransaction.h b/src/libwalletqt/PendingTransaction.h index 29fa7cb4..d8c4ec1e 100644 --- a/src/libwalletqt/PendingTransaction.h +++ b/src/libwalletqt/PendingTransaction.h @@ -24,6 +24,8 @@ public: Status_Error = Bitmonero::PendingTransaction::Status_Error }; + Q_ENUM(Status) + Status status() const; QString errorString() const; Q_INVOKABLE bool commit(); diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index 6ad81e2a..a7742bca 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -92,6 +92,15 @@ QString WalletManager::displayAmount(quint64 amount) return QString::fromStdString(Bitmonero::Wallet::displayAmount(amount)); } +quint64 WalletManager::amountFromString(const QString &amount) +{ + return Bitmonero::Wallet::amountFromString(amount.toStdString()); +} + +quint64 WalletManager::amountFromDouble(double amount) +{ + return Bitmonero::Wallet::amountFromDouble(amount); +} WalletManager::WalletManager(QObject *parent) : QObject(parent) { diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index 30e6b02a..29df9048 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -45,6 +45,9 @@ public: //! since we can't call static method from QML, move it to this class Q_INVOKABLE QString displayAmount(quint64 amount); + Q_INVOKABLE quint64 amountFromString(const QString &amount); + Q_INVOKABLE quint64 amountFromDouble(double amount); + signals: public slots: -- cgit v1.2.3 From d3234bb91564ee8327b111e0acf2a83153929c25 Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Thu, 18 Aug 2016 21:55:34 +0300 Subject: WalletManager::openWalletAsync in progress --- main.qml | 81 +++++++++++++++++++++++++-------------- src/libwalletqt/WalletManager.cpp | 34 +++++++++++++++- src/libwalletqt/WalletManager.h | 33 ++++++++++++++-- 3 files changed, 114 insertions(+), 34 deletions(-) (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/main.qml b/main.qml index faeaf123..bf30266d 100644 --- a/main.qml +++ b/main.qml @@ -49,9 +49,10 @@ ApplicationWindow { property bool rightPanelExpanded: false property bool osx: false property alias persistentSettings : persistentSettings - property var wallet; + property var currentWallet; property var transaction; property alias password : passwordDialog.password + property bool walletOpeningWithPassword: false @@ -145,26 +146,9 @@ ApplicationWindow { var wallet_path = walletPath(); console.log("opening wallet at: ", wallet_path); - wallet = walletManager.openWallet(wallet_path, appWindow.password, + walletManager.openWalletAsync(wallet_path, appWindow.password, persistentSettings.testnet); - if (wallet.status !== Wallet.Status_Ok) { - console.error("Error opening wallet with empty password: ", wallet.errorString); - console.log("closing wallet...") - walletManager.closeWallet(wallet) - console.log("wallet closed") - // try to open wallet with password; - passwordDialog.open(); - return; - } - - console.log("Wallet opened successfully: ", wallet.errorString); } - // subscribing for wallet updates - wallet.updated.connect(onWalletUpdate); - wallet.refreshed.connect(onWalletRefresh); - - console.log("initializing with daemon address..") - wallet.initAsync(persistentSettings.daemon_address, 0); } @@ -174,6 +158,50 @@ ApplicationWindow { return wallet_path; } + function onWalletOpened(wallet) { + console.log(">>> wallet opened: " + wallet) + + if (wallet.status !== Wallet.Status_Ok) { + if (!appWindow.walletOpeningWithPassword) { + console.error("Error opening wallet with empty password: ", wallet.errorString); + console.log("closing wallet async...") + walletManager.closeWalletAsync(wallet) + // try to open wallet with password; + appWindow.walletOpeningWithPassword = true + passwordDialog.open(); + } else { + // opening with password but password doesn't match + console.error("Error opening wallet with password: ", wallet.errorString); + informationPopup.title = qsTr("Error") + translationManager.emptyString; + informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString; + informationPopup.icon = StandardIcon.Critical + informationPopup.open() + informationPopup.onCloseCallback = appWindow.initialize + walletManager.closeWallet(wallet); + } + return; + } + + // wallet opened successfully, subscribing for wallet updates + currentWallet = wallet +// wallet.updated.connect(appWindow.onWalletUpdate) +// wallet.refreshed.connect(appWindow.onWalletRefresh) + // currentWallet.refreshed.connect(onWalletRefresh) + var connectResult = currentWallet.refreshed.connect(function() { + console.log("QML: refreshed") + }) + + console.log("connected to refreshed: " + connectResult); + currentWallet.updated.connect(onWalletUpdate) + console.log("initializing with daemon address: ", persistentSettings.daemon_address) + currentWallet.initAsync(persistentSettings.daemon_address, 0); + + } + + + function onWalletClosed(walletAddress) { + console.log(">>> wallet closed: " + walletAddress) + } function onWalletUpdate() { console.log(">>> wallet updated") @@ -283,6 +311,9 @@ ApplicationWindow { x = (Screen.width - width) / 2 y = (Screen.height - height) / 2 // + walletManager.walletOpened.connect(onWalletOpened); + walletManager.walletClosed.connect(onWalletClosed); + rootItem.state = walletsFound() ? "normal" : "wizard"; if (rootItem.state === "normal") { initialize(persistentSettings) @@ -342,16 +373,8 @@ ApplicationWindow { var wallet_path = walletPath(); console.log("opening wallet with password: ", wallet_path); - wallet = walletManager.openWallet(wallet_path, password, persistentSettings.testnet); - if (wallet.status !== Wallet.Status_Ok) { - console.error("Error opening wallet with password: ", wallet.errorString); - informationPopup.title = qsTr("Error") + translationManager.emptyString; - informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString; - informationPopup.icon = StandardIcon.Critical - informationPopup.open() - informationPopup.onCloseCallback = appWindow.initialize - walletManager.closeWallet(wallet); - } + walletManager.openWalletAsync(wallet_path, password, persistentSettings.testnet); + } onRejected: { appWindow.enableUI(false) diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index a7742bca..50a61553 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -6,6 +6,7 @@ #include #include #include +#include @@ -42,6 +43,20 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password, return wallet; } +void WalletManager::openWalletAsync(const QString &path, const QString &password, bool testnet) +{ + QFuture future = QtConcurrent::run(this, &WalletManager::openWallet, + path, password, testnet); + QFutureWatcher * watcher = new QFutureWatcher(); + watcher->setFuture(future); + connect(watcher, &QFutureWatcher::finished, + this, [this, watcher]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + emit walletOpened(future.result()); + }); +} + Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, bool testnet) { @@ -51,9 +66,26 @@ Wallet *WalletManager::recoveryWallet(const QString &path, const QString &memo, } -void WalletManager::closeWallet(Wallet *wallet) +QString WalletManager::closeWallet(Wallet *wallet) { + QString result = wallet->address(); delete wallet; + return result; +} + +void WalletManager::closeWalletAsync(Wallet *wallet) +{ + QFuture future = QtConcurrent::run(this, &WalletManager::closeWallet, + wallet); + QFutureWatcher * watcher = new QFutureWatcher(); + watcher->setFuture(future); + + connect(watcher, &QFutureWatcher::finished, + this, [this, watcher]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + emit future.result(); + }); } bool WalletManager::walletExists(const QString &path) const diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index 29df9048..27224b5f 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -16,15 +16,38 @@ public: // wizard: createWallet path; Q_INVOKABLE Wallet * createWallet(const QString &path, const QString &password, const QString &language, bool testnet = false); - // just for future use + + /*! + * \brief openWallet - opens wallet by given path + * \param path - wallet filename + * \param password - wallet password. Empty string in wallet isn't password protected + * \param testnet - determines if we running testnet + * \return wallet object pointer + */ Q_INVOKABLE Wallet * openWallet(const QString &path, const QString &password, bool testnet = false); + /*! + * \brief openWalletAsync - asynchronous version of "openWallet". Returns immediately. "walletOpened" signal + * emitted when wallet opened; + */ + Q_INVOKABLE void openWalletAsync(const QString &path, const QString &password, bool testnet = false); + // wizard: recoveryWallet path; hint: internally it recorvers wallet and set password = "" Q_INVOKABLE Wallet * recoveryWallet(const QString &path, const QString &memo, bool testnet = false); - //! utils: close wallet to free memory - Q_INVOKABLE void closeWallet(Wallet * wallet); + /*! + * \brief closeWallet - closes wallet and frees memory + * \param wallet + * \return wallet address + */ + Q_INVOKABLE QString closeWallet(Wallet * wallet); + + /*! + * \brief closeWalletAsync - asynchronous version of "closeWallet" + * \param wallet - wallet pointer; + */ + Q_INVOKABLE void closeWalletAsync(Wallet * wallet); //! checks is given filename is a wallet; Q_INVOKABLE bool walletExists(const QString &path) const; @@ -50,8 +73,10 @@ public: signals: -public slots: + void walletOpened(Wallet * wallet); + void walletClosed(const QString &walletAddress); +public slots: private: explicit WalletManager(QObject *parent = 0); -- cgit v1.2.3 From 8d93f01db434ffd873e095d55abeeae7d8021f6f Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Fri, 19 Aug 2016 14:44:44 +0300 Subject: WalletManager::openWalletAsync integrating with UI --- main.qml | 62 +++++++++++++++++++-------------------- src/libwalletqt/WalletManager.cpp | 9 +++++- wizard/WizardCreateWallet.qml | 3 +- wizard/WizardRecoveryWallet.qml | 9 +++--- wizard/utils.js | 5 ++++ 5 files changed, 50 insertions(+), 38 deletions(-) (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/main.qml b/main.qml index bf30266d..f589c666 100644 --- a/main.qml +++ b/main.qml @@ -52,8 +52,6 @@ ApplicationWindow { property var currentWallet; property var transaction; property alias password : passwordDialog.password - property bool walletOpeningWithPassword: false - function altKeyReleased() { ctrlPressed = false; } @@ -140,18 +138,27 @@ ApplicationWindow { basicPanel.paymentClicked.connect(handlePayment); + // wallet already opened with wizard, we just need to initialize it if (typeof wizard.settings['wallet'] !== 'undefined') { - wallet = wizard.settings['wallet']; + connectWallet(wizard.settings['wallet']) } else { var wallet_path = walletPath(); - - console.log("opening wallet at: ", wallet_path); + console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.password); walletManager.openWalletAsync(wallet_path, appWindow.password, persistentSettings.testnet); } } + + function connectWallet(wallet) { + currentWallet = wallet + currentWallet.refreshed.connect(onWalletRefresh) + currentWallet.updated.connect(onWalletUpdate) + console.log("initializing with daemon address: ", persistentSettings.daemon_address) + currentWallet.initAsync(persistentSettings.daemon_address, 0); + } + function walletPath() { var wallet_path = persistentSettings.wallet_path + "/" + persistentSettings.account_name + "/" + persistentSettings.account_name; @@ -162,39 +169,32 @@ ApplicationWindow { console.log(">>> wallet opened: " + wallet) if (wallet.status !== Wallet.Status_Ok) { - if (!appWindow.walletOpeningWithPassword) { + if (appWindow.password === '') { console.error("Error opening wallet with empty password: ", wallet.errorString); - console.log("closing wallet async...") + console.log("closing wallet async : " + wallet.address) walletManager.closeWalletAsync(wallet) // try to open wallet with password; - appWindow.walletOpeningWithPassword = true passwordDialog.open(); } else { // opening with password but password doesn't match console.error("Error opening wallet with password: ", wallet.errorString); + informationPopup.title = qsTr("Error") + translationManager.emptyString; informationPopup.text = qsTr("Couldn't open wallet: ") + wallet.errorString; informationPopup.icon = StandardIcon.Critical + console.log("closing wallet async : " + wallet.address) + walletManager.closeWalletAsync(wallet); informationPopup.open() - informationPopup.onCloseCallback = appWindow.initialize - walletManager.closeWallet(wallet); + informationPopup.onCloseCallback = function() { + passwordDialog.open() + } + } return; } // wallet opened successfully, subscribing for wallet updates - currentWallet = wallet -// wallet.updated.connect(appWindow.onWalletUpdate) -// wallet.refreshed.connect(appWindow.onWalletRefresh) - // currentWallet.refreshed.connect(onWalletRefresh) - var connectResult = currentWallet.refreshed.connect(function() { - console.log("QML: refreshed") - }) - - console.log("connected to refreshed: " + connectResult); - currentWallet.updated.connect(onWalletUpdate) - console.log("initializing with daemon address: ", persistentSettings.daemon_address) - currentWallet.initAsync(persistentSettings.daemon_address, 0); + connectWallet(wallet) } @@ -205,14 +205,14 @@ ApplicationWindow { function onWalletUpdate() { console.log(">>> wallet updated") - basicPanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(wallet.unlockedBalance); - basicPanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(wallet.balance); - + basicPanel.unlockedBalanceText = leftPanel.unlockedBalanceText = + walletManager.displayAmount(currentWallet.unlockedBalance); + basicPanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance); } function onWalletRefresh() { console.log(">>> wallet refreshed") - leftPanel.networkStatus.connected = wallet.connected + leftPanel.networkStatus.connected = currentWallet.connected onWalletUpdate(); } @@ -369,12 +369,12 @@ ApplicationWindow { id: passwordDialog standardButtons: StandardButton.Ok + StandardButton.Cancel onAccepted: { + appWindow.currentWallet = null + appWindow.initialize(); - var wallet_path = walletPath(); - console.log("opening wallet with password: ", wallet_path); - - walletManager.openWalletAsync(wallet_path, password, persistentSettings.testnet); - +// var wallet_path = walletPath(); +// console.log("opening wallet with password: ", wallet_path); +// walletManager.openWalletAsync(wallet_path, password, persistentSettings.testnet); } onRejected: { appWindow.enableUI(false) diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index 50a61553..da5c4cd7 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -40,6 +40,13 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password, Bitmonero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet); Wallet * wallet = new Wallet(w); + + // move wallet to the GUI thread. Otherwise it wont be emitting signals + if (wallet->thread() != qApp->thread()) { + wallet->moveToThread(qApp->thread()); + } + + return wallet; } @@ -84,7 +91,7 @@ void WalletManager::closeWalletAsync(Wallet *wallet) this, [this, watcher]() { QFuture future = watcher->future(); watcher->deleteLater(); - emit future.result(); + emit walletClosed(future.result()); }); } diff --git a/wizard/WizardCreateWallet.qml b/wizard/WizardCreateWallet.qml index 771a13ec..43b8158f 100644 --- a/wizard/WizardCreateWallet.qml +++ b/wizard/WizardCreateWallet.qml @@ -29,6 +29,7 @@ import QtQuick 2.2 import moneroComponents 1.0 import QtQuick.Dialogs 1.2 +import 'utils.js' as Utils Item { opacity: 0 @@ -54,7 +55,7 @@ Item { } function checkNextButton() { - var wordsArray = cleanWordsInput(uiItem.wordsTextItem.memoText).split(" "); + var wordsArray = Utils.lineBreaksToSpaces(uiItem.wordsTextItem.memoText).split(" "); wizard.nextButton.enabled = wordsArray.length === 25; } diff --git a/wizard/WizardRecoveryWallet.qml b/wizard/WizardRecoveryWallet.qml index 2e6fe5f6..505bc239 100644 --- a/wizard/WizardRecoveryWallet.qml +++ b/wizard/WizardRecoveryWallet.qml @@ -30,6 +30,7 @@ import QtQuick 2.2 import moneroComponents 1.0 import QtQuick.Dialogs 1.2 import Bitmonero.Wallet 1.0 +import 'utils.js' as Utils Item { opacity: 0 @@ -46,13 +47,13 @@ Item { } function checkNextButton() { - var wordsArray = cleanWordsInput(uiItem.wordsTextItem.memoText).split(" "); + var wordsArray = Utils.lineBreaksToSpaces(uiItem.wordsTextItem.memoText).split(" "); wizard.nextButton.enabled = wordsArray.length === 25; } function onPageClosed(settingsObject) { settingsObject['account_name'] = uiItem.accountNameText - settingsObject['words'] = cleanWordsInput(uiItem.wordsTextItem.memoText) + settingsObject['words'] = Utils.lineBreaksToSpaces(uiItem.wordsTextItem.memoText) settingsObject['wallet_path'] = uiItem.walletPath return recoveryWallet(settingsObject) } @@ -69,9 +70,7 @@ Item { return success; } - function cleanWordsInput(text) { - return text.trim().replace(/(\r\n|\n|\r)/gm, " "); - } + WizardManageWalletUI { id: uiItem diff --git a/wizard/utils.js b/wizard/utils.js index 0cc910c6..be066598 100644 --- a/wizard/utils.js +++ b/wizard/utils.js @@ -42,3 +42,8 @@ function mapScope (inputScopeFrom, inputScopeTo, outputScopeFrom, outputScopeTo, function tr(text) { return qsTr(text) + translationManager.emptyString } + + +function lineBreaksToSpaces(text) { + return text.trim().replace(/(\r\n|\n|\r)/gm, " "); +} -- cgit v1.2.3 From 6b9afcf291cb5ab5db78f358a6213b1afc6081af Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Tue, 23 Aug 2016 10:32:01 +0300 Subject: extra debug logging --- main.cpp | 2 ++ src/libwalletqt/WalletManager.cpp | 17 ++++++++--------- src/libwalletqt/WalletManager.h | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 9 deletions(-) (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/main.cpp b/main.cpp index 9f109e01..d0e9e085 100644 --- a/main.cpp +++ b/main.cpp @@ -111,5 +111,7 @@ int main(int argc, char *argv[]) QObject::connect(eventFilter, SIGNAL(mousePressed(QVariant,QVariant,QVariant)), rootObject, SLOT(mousePressed(QVariant,QVariant,QVariant))); QObject::connect(eventFilter, SIGNAL(mouseReleased(QVariant,QVariant,QVariant)), rootObject, SLOT(mouseReleased(QVariant,QVariant,QVariant))); + WalletManager::instance()->setLogLevel(WalletManager::LogLevel_Max); + return app.exec(); } diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index da5c4cd7..947ccbfb 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -8,14 +8,9 @@ #include #include - - WalletManager * WalletManager::m_instance = nullptr; - - - WalletManager *WalletManager::instance() { if (!m_instance) { @@ -36,9 +31,11 @@ Wallet *WalletManager::createWallet(const QString &path, const QString &password Wallet *WalletManager::openWallet(const QString &path, const QString &password, bool testnet) { - // TODO: call the libwallet api here; + qDebug("%s: opening wallet at %s, testnet = %d ", + __PRETTY_FUNCTION__, qPrintable(path), testnet); Bitmonero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), testnet); + qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address().c_str(), w->status()); Wallet * wallet = new Wallet(w); // move wallet to the GUI thread. Otherwise it wont be emitting signals @@ -46,7 +43,6 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password, wallet->moveToThread(qApp->thread()); } - return wallet; } @@ -141,9 +137,12 @@ quint64 WalletManager::amountFromDouble(double amount) return Bitmonero::Wallet::amountFromDouble(amount); } +void WalletManager::setLogLevel(int logLevel) +{ + Bitmonero::WalletManagerFactory::setLogLevel(logLevel); +} + WalletManager::WalletManager(QObject *parent) : QObject(parent) { m_pimpl = Bitmonero::WalletManagerFactory::getWalletManager(); } - - diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index 27224b5f..1866b7cd 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -2,6 +2,7 @@ #define WALLETMANAGER_H #include +#include class Wallet; namespace Bitmonero { @@ -12,6 +13,17 @@ class WalletManager : public QObject { Q_OBJECT public: + enum LogLevel { + LogLevel_Silent = Bitmonero::WalletManagerFactory::LogLevel_Silent, + LogLevel_0 = Bitmonero::WalletManagerFactory::LogLevel_0, + LogLevel_1 = Bitmonero::WalletManagerFactory::LogLevel_1, + LogLevel_2 = Bitmonero::WalletManagerFactory::LogLevel_2, + LogLevel_3 = Bitmonero::WalletManagerFactory::LogLevel_3, + LogLevel_4 = Bitmonero::WalletManagerFactory::LogLevel_4, + LogLevel_Min = Bitmonero::WalletManagerFactory::LogLevel_Min, + LogLevel_Max = Bitmonero::WalletManagerFactory::LogLevel_Max, + }; + static WalletManager * instance(); // wizard: createWallet path; Q_INVOKABLE Wallet * createWallet(const QString &path, const QString &password, @@ -71,6 +83,8 @@ public: Q_INVOKABLE quint64 amountFromString(const QString &amount); Q_INVOKABLE quint64 amountFromDouble(double amount); + void setLogLevel(int logLevel); + signals: void walletOpened(Wallet * wallet); -- cgit v1.2.3 From 4fa8ad3b199483094cf9988f33da1ab6343d7c8a Mon Sep 17 00:00:00 2001 From: Ilya Kitaev Date: Tue, 23 Aug 2016 16:07:52 +0300 Subject: Transfer page: validate amount --- components/StandardButton.qml | 11 +++++++++-- main.cpp | 2 +- main.qml | 27 +++++++++++++++++++++------ pages/Transfer.qml | 27 ++++++++++++++++----------- src/libwalletqt/WalletManager.cpp | 16 +++++++++++++--- src/libwalletqt/WalletManager.h | 11 ++++++++--- 6 files changed, 68 insertions(+), 26 deletions(-) (limited to 'src/libwalletqt/WalletManager.cpp') diff --git a/components/StandardButton.qml b/components/StandardButton.qml index 208d90d3..5a088fbf 100644 --- a/components/StandardButton.qml +++ b/components/StandardButton.qml @@ -47,7 +47,10 @@ Item { height: parent.height - 1 y: buttonArea.pressed ? 0 : 1 //radius: 4 - color: buttonArea.pressed ? parent.shadowPressedColor : parent.shadowReleasedColor + color: { + parent.enabled ? (buttonArea.pressed ? parent.shadowPressedColor : parent.shadowReleasedColor) + : Qt.lighter(parent.shadowReleasedColor) + } } Rectangle { @@ -55,7 +58,11 @@ Item { anchors.right: parent.right height: parent.height - 1 y: buttonArea.pressed ? 1 : 0 - color: buttonArea.pressed ? parent.pressedColor : parent.releasedColor + color: { + parent.enabled ? (buttonArea.pressed ? parent.pressedColor : parent.releasedColor) + : Qt.lighter(parent.releasedColor) + + } //radius: 4 } diff --git a/main.cpp b/main.cpp index 387c4b13..e356659c 100644 --- a/main.cpp +++ b/main.cpp @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) QObject::connect(eventFilter, SIGNAL(mousePressed(QVariant,QVariant,QVariant)), rootObject, SLOT(mousePressed(QVariant,QVariant,QVariant))); QObject::connect(eventFilter, SIGNAL(mouseReleased(QVariant,QVariant,QVariant)), rootObject, SLOT(mouseReleased(QVariant,QVariant,QVariant))); - WalletManager::instance()->setLogLevel(WalletManager::LogLevel_Max); + WalletManager::instance()->setLogLevel(WalletManager::LogLevel_Silent); return app.exec(); } diff --git a/main.qml b/main.qml index 636945e8..6d57b634 100644 --- a/main.qml +++ b/main.qml @@ -135,7 +135,7 @@ ApplicationWindow { } middlePanel.paymentClicked.connect(handlePayment); - basicPanel.paymentClicked.connect(handlePayment); + // basicPanel.paymentClicked.connect(handlePayment); // wallet already opened with wizard, we just need to initialize it @@ -240,10 +240,25 @@ ApplicationWindow { ", mixins: ", mixinCount, ", priority: ", priority); - var amountxmr = walletManager.amountFromString(amount); + // validate amount; + var amountxmr = walletManager.amountFromString(amount); console.log("integer amount: ", amountxmr); - transaction = wallet.createTransaction(address, paymentId, amountxmr, mixinCount, priority); + if (amountxmr <= 0) { + informationPopup.title = qsTr("Error") + translationManager.emptyString; + informationPopup.text = qsTr("Amount is wrong: expected number from %1 to %2") + .arg(walletManager.displayAmount(0)) + .arg(walletManager.maximumAllowedAmountAsSting()) + + translationManager.emptyString + + informationPopup.icon = StandardIcon.Critical + informationPopup.onCloseCallback = null + informationPopup.open() + return; + } + + // validate address; + transaction = currentWallet.createTransaction(address, paymentId, amountxmr, mixinCount, priority); if (transaction.status !== PendingTransaction.Status_Ok) { console.error("Can't create transaction: ", transaction.errorString); informationPopup.title = qsTr("Error") + translationManager.emptyString; @@ -252,7 +267,7 @@ ApplicationWindow { informationPopup.onCloseCallback = null informationPopup.open(); // deleting transaction object, we don't want memleaks - wallet.disposeTransaction(transaction); + currentWallet.disposeTransaction(transaction); } else { console.log("Transaction created, amount: " + walletManager.displayAmount(transaction.amount) @@ -287,8 +302,8 @@ ApplicationWindow { } informationPopup.onCloseCallback = null informationPopup.open() - wallet.refresh() - wallet.disposeTransaction(transaction) + currentWallet.refresh() + currentWallet.disposeTransaction(transaction) } // blocks UI if wallet can't be opened or no connection to the daemon diff --git a/pages/Transfer.qml b/pages/Transfer.qml index 70fde050..508b32af 100644 --- a/pages/Transfer.qml +++ b/pages/Transfer.qml @@ -32,6 +32,7 @@ import "../components" Rectangle { + id: root signal paymentClicked(string address, string paymentId, double amount, int mixinCount, int priority) @@ -88,6 +89,11 @@ Rectangle { id: amountLine placeholderText: qsTr("Amount...") + translationManager.emptyString width: parent.width - 37 - 17 + validator: DoubleValidator { + bottom: 0.0 + notation: DoubleValidator.StandardNotation + locale: "C" + } } } @@ -170,7 +176,7 @@ Rectangle { textFormat: Text.RichText text: qsTr("\ Address ( Type in or select from Address book )") - + translationManager.emptyString + + translationManager.emptyString onLinkActivated: appWindow.showPageRequest("AddressBook") } @@ -220,7 +226,7 @@ Rectangle { anchors.topMargin: 17 fontSize: 14 text: qsTr("Description ( An optional description that will be saved to the local address book if entered )") - + translationManager.emptyString + + translationManager.emptyString } LineEdit { @@ -245,16 +251,15 @@ Rectangle { shadowPressedColor: "#B32D00" releasedColor: "#FF6C3C" pressedColor: "#FF4304" + enabled : addressLine.text.length > 0 && amountLine.text.length > 0 onClicked: { - // do more smart validation - - if (addressLine.text.length > 0 && amountLine.text.length > 0) { - console.log("paymentClicked") - var priority = priorityModel.get(priorityDropdown.currentIndex).priority - console.log("priority: " + priority) - paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, scaleValueToMixinCount(privacyLevelItem.fillLevel), - priority) - } + console.log("Transfer: paymentClicked") + var priority = priorityModel.get(priorityDropdown.currentIndex).priority + console.log("priority: " + priority) + console.log("amount: " + amountLine.text) + root.paymentClicked(addressLine.text, paymentIdLine.text, amountLine.text, scaleValueToMixinCount(privacyLevelItem.fillLevel), + priority) } } } + diff --git a/src/libwalletqt/WalletManager.cpp b/src/libwalletqt/WalletManager.cpp index 947ccbfb..a9f332a3 100644 --- a/src/libwalletqt/WalletManager.cpp +++ b/src/libwalletqt/WalletManager.cpp @@ -122,17 +122,27 @@ QString WalletManager::walletLanguage(const QString &locale) return "English"; } -QString WalletManager::displayAmount(quint64 amount) +quint64 WalletManager::maximumAllowedAmount() const +{ + return Bitmonero::Wallet::maximumAllowedAmount(); +} + +QString WalletManager::maximumAllowedAmountAsSting() const +{ + return WalletManager::displayAmount(WalletManager::maximumAllowedAmount()); +} + +QString WalletManager::displayAmount(quint64 amount) const { return QString::fromStdString(Bitmonero::Wallet::displayAmount(amount)); } -quint64 WalletManager::amountFromString(const QString &amount) +quint64 WalletManager::amountFromString(const QString &amount) const { return Bitmonero::Wallet::amountFromString(amount.toStdString()); } -quint64 WalletManager::amountFromDouble(double amount) +quint64 WalletManager::amountFromDouble(double amount) const { return Bitmonero::Wallet::amountFromDouble(amount); } diff --git a/src/libwalletqt/WalletManager.h b/src/libwalletqt/WalletManager.h index 1866b7cd..3629242a 100644 --- a/src/libwalletqt/WalletManager.h +++ b/src/libwalletqt/WalletManager.h @@ -12,6 +12,7 @@ namespace Bitmonero { class WalletManager : public QObject { Q_OBJECT + public: enum LogLevel { LogLevel_Silent = Bitmonero::WalletManagerFactory::LogLevel_Silent, @@ -79,9 +80,13 @@ public: //! since we can't call static method from QML, move it to this class - Q_INVOKABLE QString displayAmount(quint64 amount); - Q_INVOKABLE quint64 amountFromString(const QString &amount); - Q_INVOKABLE quint64 amountFromDouble(double amount); + Q_INVOKABLE QString displayAmount(quint64 amount) const; + Q_INVOKABLE quint64 amountFromString(const QString &amount) const; + Q_INVOKABLE quint64 amountFromDouble(double amount) const; + Q_INVOKABLE quint64 maximumAllowedAmount() const; + + // QML JS engine doesn't support unsigned integers + Q_INVOKABLE QString maximumAllowedAmountAsSting() const; void setLogLevel(int logLevel); -- cgit v1.2.3