diff --git a/README.md b/README.md index dffac98..d5cc1ea 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # bytecoin-gui -[![Build Status](https://dev.azure.com/bcndev/bytecoin/_apis/build/status/bytecoin-desktop?branchName=releases/3.5.0)](https://dev.azure.com/bcndev/bytecoin/_build/latest?definitionId=2&branchName=releases/3.5.0) +[![Build Status](https://dev.azure.com/bcndev/bytecoin/_apis/build/status/bytecoin-desktop?branchName=releases/3.5.1)](https://dev.azure.com/bcndev/bytecoin/_build/latest?definitionId=2&branchName=releases/3.5.1) ## How to build binaries from source code diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 1382ec7..7999e4a 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,5 +1,10 @@ ## Release Notes +### v3.5.1 (Beryl) +- Brought back El Capitan support. +- Fixed minor UI bugs. +- Updated the Bytecoin daemons. + ### v3.5.0 (Beryl) - Made many visual improvements to the graphical elements of the app. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f21e978..52a5796 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -156,8 +156,11 @@ jobs: displayName: Clone desktop code - script: | - brew install qt - displayName: Install qt + curl -L -O https://raw.githubusercontent.com/Homebrew/homebrew-core/8d4d48f0bb552b7b107119aeef59f141ce1f72c3/Formula/qt.rb + depends_on :macos => :mountain_lion + sed -i '' 's/depends_on :macos => :mountain_lion/#depends_on :macos => :mountain_lion/g' qt.rb + brew install qt.rb + displayName: Install qt 5.10.1 - script: | mkdir bytecoin-gui/build && cd bytecoin-gui/build diff --git a/src/addressbookmanager.cpp b/src/addressbookmanager.cpp index 2649110..a4e6fa0 100644 --- a/src/addressbookmanager.cpp +++ b/src/addressbookmanager.cpp @@ -201,7 +201,7 @@ void MyAddressesManager::walletRecordsReceived(const RpcApi::WalletRecords& reco addressBook_ << AddressItem{rec.label, rec.address}; const AddressIndex index = addressBook_.size() - 1; addressIndexes_[rec.address] = index; - WalletLogger::debug(tr("[WalletAddressBook] Wallet record indexed.")); +// WalletLogger::debug(tr("[WalletAddressBook] Wallet record indexed.")); if (!firstTime_) emit addressAddedSignal(index); } diff --git a/src/application.cpp b/src/application.cpp index d55b94e..03c4d72 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -370,7 +370,6 @@ void WalletApplication::daemonFinished(int exitCode, QProcess::ExitStatus /*exit restartDaemon(); return; } - tryToOpenWithEmptyPassword_ = false; const QString walletdMsg = BuiltinWalletd::errorMessage(returnCode); const QString msg = !walletdMsg.isEmpty() ? @@ -632,7 +631,7 @@ void WalletApplication::checkProof() void WalletApplication::showWalletdParams() { WalletdParamsDialog dlg(Settings::instance().getWalletdConnectionMethod() == ConnectionMethod::BUILTIN && !Settings::instance().getWalletFile().isEmpty(), m_mainWindow); - connect(&dlg, &WalletdParamsDialog::restartWalletd, this, &WalletApplication::restartDaemon); + connect(&dlg, &WalletdParamsDialog::restartWalletd, [this](){ this->tryToOpenWithEmptyPassword_ = true; this->restartDaemon();} ); BuiltinWalletd* walletd = static_cast(walletd_); if (walletd) connect(walletd, &BuiltinWalletd::daemonErrorOccurredSignal, &dlg, &WalletdParamsDialog::reject); diff --git a/src/bytecoin-gui.pro b/src/bytecoin-gui.pro index 6e94c15..d8994c3 100644 --- a/src/bytecoin-gui.pro +++ b/src/bytecoin-gui.pro @@ -15,7 +15,7 @@ TEMPLATE = app macx: QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.11 macx: ICON = images/bytecoin.icns win32: RC_ICONS = images/bytecoin.ico -win32: VERSION = 3.19.7.4 +win32: VERSION = 3.19.7.18 #QMAKE_CXXFLAGS += -fno-omit-frame-pointer -fsanitize=address,undefined #LIBS += -lasan -lubsan diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index bf60cec..da75a9a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -137,6 +137,7 @@ MainWindow::MainWindow( // m_ui->m_miningButton->setStyleSheet(QString{BUTTON_STYLE_SHEET}.arg(MAIN_NET_COLOR)); // m_ui->m_logButton->setStyleSheet(QString{BUTTON_STYLE_SHEET}.arg(MAIN_NET_COLOR)); + m_ui->m_walletViewOnlyLabel->hide(); m_addressBookModel = new AddressBookModel(addressBookManager_, this); m_sortedAddressBookModel = new SortedAddressBookModel(m_addressBookModel, this); m_myAddressesModel = new AddressBookModel(myAddressesManager_, this); @@ -300,6 +301,8 @@ QString MainWindow::getAddress() const void MainWindow::addRecipient(const QString& address, const QString& label) { + if (walletModel_->isViewOnly()) + return; m_ui->m_sendFrame->addRecipient(address, label); m_ui->m_sendButton->click(); } @@ -528,7 +531,11 @@ void MainWindow::clearTitle() void MainWindow::setConnectedState() { - m_ui->m_sendButton->setEnabled(true); + const bool viewOnly = walletModel_->isViewOnly(); + m_ui->m_walletViewOnlyLabel->setVisible(viewOnly); + + if (!viewOnly) + m_ui->m_sendButton->setEnabled(true); m_ui->m_miningButton->setEnabled(true); m_ui->m_overviewButton->setEnabled(true); m_ui->m_addressBookButton->setEnabled(true); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 962d4b2..690f1a9 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -167,6 +167,19 @@ 0 + + + + Qt::Vertical + + + + 20 + 0 + + + + @@ -188,6 +201,9 @@ New version %1 of Bytecoin wallet is available! + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + @@ -203,24 +219,24 @@ + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 20 - - - - @@ -436,17 +452,76 @@ - - - Qt::Vertical - - - - 20 - 20 - + + + 0 - + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 75 + true + + + + View-only wallet + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + diff --git a/src/overviewframe.cpp b/src/overviewframe.cpp index fd106fc..c4a4e3e 100644 --- a/src/overviewframe.cpp +++ b/src/overviewframe.cpp @@ -22,9 +22,12 @@ namespace WalletGUI { namespace { -const char TX_HASH_URL[] = "https://explorer.bytecoin.org/tx?hash=%1"; -const char BLOCK_HASH_URL[] = "https://explorer.bytecoin.org/block?hash=%1"; -const char BLOCK_HEIGHT_URL[] = "https://explorer.bytecoin.org/block?height=%1"; +const char MAIN_TX_HASH_URL[] = "https://explorer.bytecoin.org/tx?hash=%1"; +const char MAIN_BLOCK_HASH_URL[] = "https://explorer.bytecoin.org/block?hash=%1"; +const char MAIN_BLOCK_HEIGHT_URL[] = "https://explorer.bytecoin.org/block?height=%1"; +const char STAGE_TX_HASH_URL[] = "https://stage.explorer.bytecoin.org/tx?hash=%1"; +const char STAGE_BLOCK_HASH_URL[] = "https://stage.explorer.bytecoin.org/block?hash=%1"; +const char STAGE_BLOCK_HEIGHT_URL[] = "https://stage.explorer.bytecoin.org/block?height=%1"; //const char OVERVIEW_STYLE_SHEET_TEMPLATE[] = @@ -167,13 +170,15 @@ bool OverviewFrame::eventFilter(QObject* object, QEvent* event) { QMouseEvent* e = (QMouseEvent*)event; QModelIndex modelIndex = view->indexAt(e->pos()); - if (!modelIndex.isValid()) return false; + const QString net = m_transactionsModel->data(modelIndex, WalletModel::ROLE_NET).toString(); + const bool isTestnet = (net == RpcApi::TEST_NET_NAME); const bool explorableColumns = - (modelIndex.column() == WalletModel::COLUMN_HASH && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_HASH).toString().isEmpty()) || + !isTestnet && + ((modelIndex.column() == WalletModel::COLUMN_HASH && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_HASH).toString().isEmpty()) || (modelIndex.column() == WalletModel::COLUMN_BLOCK_HASH && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HASH).toString().isEmpty()) || - (modelIndex.column() == WalletModel::COLUMN_BLOCK_HEIGHT && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HEIGHT).toString().isEmpty()); + (modelIndex.column() == WalletModel::COLUMN_BLOCK_HEIGHT && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HEIGHT).toString().isEmpty())); const bool proof = m_transactionsModel->data(modelIndex, WalletModel::ROLE_PROOF).toBool(); const bool proofColumn = (modelIndex.column() == WalletModel::COLUMN_PROOF && proof); const bool valid = explorableColumns || proofColumn; @@ -182,16 +187,17 @@ bool OverviewFrame::eventFilter(QObject* object, QEvent* event) if (explorableColumns) { + const bool mainnet = (net == RpcApi::MAIN_NET_NAME); switch(modelIndex.column()) { case WalletModel::COLUMN_HASH: - QDesktopServices::openUrl(QUrl::fromUserInput(QString{TX_HASH_URL}.arg(m_transactionsModel->data(modelIndex, WalletModel::ROLE_HASH).toString()))); + QDesktopServices::openUrl(QUrl::fromUserInput(QString{mainnet ? MAIN_TX_HASH_URL : STAGE_TX_HASH_URL}.arg(m_transactionsModel->data(modelIndex, WalletModel::ROLE_HASH).toString()))); break; case WalletModel::COLUMN_BLOCK_HASH: - QDesktopServices::openUrl(QUrl::fromUserInput(QString{BLOCK_HASH_URL}.arg(m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HASH).toString()))); + QDesktopServices::openUrl(QUrl::fromUserInput(QString{mainnet ? MAIN_BLOCK_HASH_URL : STAGE_BLOCK_HASH_URL}.arg(m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HASH).toString()))); break; case WalletModel::COLUMN_BLOCK_HEIGHT: - QDesktopServices::openUrl(QUrl::fromUserInput(QString{BLOCK_HEIGHT_URL}.arg(m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HEIGHT).toString()))); + QDesktopServices::openUrl(QUrl::fromUserInput(QString{mainnet ? MAIN_BLOCK_HEIGHT_URL : STAGE_BLOCK_HEIGHT_URL}.arg(m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HEIGHT).toString()))); break; } } @@ -207,10 +213,13 @@ bool OverviewFrame::eventFilter(QObject* object, QEvent* event) QMouseEvent* e = (QMouseEvent*)event; QModelIndex modelIndex = view->indexAt(e->pos()); + const QString net = m_transactionsModel->data(modelIndex, WalletModel::ROLE_NET).toString(); + const bool isTestnet = (net == RpcApi::TEST_NET_NAME); const bool explorableColumns = - (modelIndex.column() == WalletModel::COLUMN_HASH && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_HASH).toString().isEmpty()) || + !isTestnet && + ((modelIndex.column() == WalletModel::COLUMN_HASH && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_HASH).toString().isEmpty()) || (modelIndex.column() == WalletModel::COLUMN_BLOCK_HASH && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HASH).toString().isEmpty()) || - (modelIndex.column() == WalletModel::COLUMN_BLOCK_HEIGHT && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HEIGHT).toString().isEmpty()); + (modelIndex.column() == WalletModel::COLUMN_BLOCK_HEIGHT && !m_transactionsModel->data(modelIndex, WalletModel::ROLE_BLOCK_HEIGHT).toString().isEmpty())); const bool proof = m_transactionsModel->data(modelIndex, WalletModel::ROLE_PROOF).toBool(); const bool proofColumn = (modelIndex.column() == WalletModel::COLUMN_PROOF && proof); diff --git a/src/rpcapi.cpp b/src/rpcapi.cpp index ee593c4..63deab1 100644 --- a/src/rpcapi.cpp +++ b/src/rpcapi.cpp @@ -264,6 +264,7 @@ GetTransfers::Request::toJson() const RPCAPI_SERIALIZE_FIELD(value, json, to_height); RPCAPI_SERIALIZE_FIELD(value, json, forward); RPCAPI_SERIALIZE_FIELD(value, json, desired_transactions_count); + RPCAPI_SERIALIZE_FIELD(value, json, need_outputs); return json; } @@ -380,7 +381,7 @@ Transfer::fromJson(const QVariantMap& json) RPCAPI_DESERIALIZE_FIELD(value, json, locked); RPCAPI_DESERIALIZE_FIELD(value, json, transaction_hash); - RPCAPI_DESERIALIZE_LIST(value, json, outputs); +// RPCAPI_DESERIALIZE_LIST(value, json, outputs); return value; } @@ -397,7 +398,7 @@ Transfer::toJson() const RPCAPI_SERIALIZE_FIELD(value, json, locked); RPCAPI_SERIALIZE_FIELD(value, json, transaction_hash); - RPCAPI_SERIALIZE_LIST(value, json, outputs); +// RPCAPI_SERIALIZE_LIST(value, json, outputs); return json; } @@ -457,8 +458,8 @@ WalletRecord::fromJson(const QVariantMap& json) RPCAPI_DESERIALIZE_FIELD(value, json, address); RPCAPI_DESERIALIZE_FIELD(value, json, label); RPCAPI_DESERIALIZE_FIELD(value, json, index); - RPCAPI_DESERIALIZE_FIELD(value, json, secret_spend_key); - RPCAPI_DESERIALIZE_FIELD(value, json, public_spend_key); +// RPCAPI_DESERIALIZE_FIELD(value, json, secret_spend_key); +// RPCAPI_DESERIALIZE_FIELD(value, json, public_spend_key); return value; } diff --git a/src/rpcapi.h b/src/rpcapi.h index 1d56f8a..a119031 100644 --- a/src/rpcapi.h +++ b/src/rpcapi.h @@ -107,7 +107,8 @@ struct Transfer SignedAmount amount = 0; bool ours = true; bool locked = false; - QList outputs; + // we do not request outputs +// QList outputs; QString transaction_hash; static Transfer fromJson(const QVariantMap& json); @@ -120,7 +121,7 @@ struct Transfer amount, ours, locked, - outputs, +// outputs, transaction_hash); } }; @@ -250,8 +251,9 @@ struct WalletRecord QString address; QString label; quint64 index = 0; - QString secret_spend_key; - QString public_spend_key; + // we do not ask keys +// QString secret_spend_key; +// QString public_spend_key; static WalletRecord fromJson(const QVariantMap& json); @@ -260,33 +262,12 @@ struct WalletRecord return std::tie( address, label, - index, + index/*, secret_spend_key, - public_spend_key); + public_spend_key*/); } }; -//struct Proof -//{ -// QString message; -// QString address; -// Amount amount = 0; -// QString transaction_hash; -// QString proof; - -// static Proof fromJson(const QVariantMap& json); - -// auto tie() const -// { -// return std::tie( -// message, -// address, -// amount, -// transaction_hash, -// proof); -// } -//}; - struct GetStatus { static constexpr char METHOD[] = "get_status"; @@ -541,6 +522,7 @@ struct GetTransfers Height to_height = std::numeric_limits::max(); bool forward = false; quint64 desired_transactions_count = 300; + bool need_outputs = false; QVariantMap toJson() const; }; diff --git a/src/settings.cpp b/src/settings.cpp index 1bc8900..ac353b2 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -199,7 +199,7 @@ QString Settings::getBytecoindHost() const quint16 Settings::getBytecoindPort() const { - return static_cast(settings_->value(OPTION_BYTECOIND_PORT).toUInt()); + return static_cast(settings_->value(OPTION_BYTECOIND_PORT, getDefaultBytecoindPort()).toUInt()); } NetworkType Settings::getNetworkType() const diff --git a/src/version.h b/src/version.h index 9919084..34ab5fe 100644 --- a/src/version.h +++ b/src/version.h @@ -5,10 +5,10 @@ namespace WalletGUI { -constexpr char VERSION[] = "3.5.0"; +constexpr char VERSION[] = "3.5.1"; constexpr char CODENAME[] = "Beryl"; constexpr char VERSION_SUFFIX[] = "stable"; -constexpr char REVISION[] = "20190704"; +constexpr char REVISION[] = "20190718"; // returns <0, if newVersion is worse than currentVersion, returns >0, if newVersion is better, and returns 0, if versions are equal int compareVersion(const QString& newVersion, const QString& currentVersion); diff --git a/src/walletdparamsdialog.cpp b/src/walletdparamsdialog.cpp index cf4d5e4..c739806 100644 --- a/src/walletdparamsdialog.cpp +++ b/src/walletdparamsdialog.cpp @@ -33,8 +33,9 @@ WalletdParamsDialog::WalletdParamsDialog(bool allowToRestart, QWidget *parent) default: ui->radioBuiltinBytecoind->setChecked(true); break; } - ui->editHost->setText(Settings::instance().getBytecoindHost()); - ui->spinPort->setValue(Settings::instance().getBytecoindPort()); + QUrl url{Settings::instance().getBytecoindHost()}; + url.setPort(Settings::instance().getBytecoindPort()); + ui->editHost->setText(url.toString()); } WalletdParamsDialog::~WalletdParamsDialog() @@ -59,7 +60,9 @@ void WalletdParamsDialog::saveParams() ui->radioExternalBytecoind->isChecked() ? ConnectionMethod::REMOTE : ConnectionMethod::BUILTIN); - Settings::instance().setBytecoindEndPoint(ui->editHost->text(), static_cast(ui->spinPort->value())); + + const QUrl url{ui->editHost->text()}; + Settings::instance().setBytecoindEndPoint(url.toString(QUrl::RemovePort), url.port(Settings::instance().getDefaultBytecoindPort())); } void WalletdParamsDialog::applyParams() diff --git a/src/walletdparamsdialog.ui b/src/walletdparamsdialog.ui index 92c67f2..607f27a 100644 --- a/src/walletdparamsdialog.ui +++ b/src/walletdparamsdialog.ui @@ -7,7 +7,7 @@ 0 0 652 - 314 + 322 @@ -51,7 +51,7 @@ - + QLayout::SetDefaultConstraint @@ -61,53 +61,28 @@ 0 - - + + false - + 0 0 + + 127.0.0.1:8081 + true - - QAbstractSpinBox::NoButtons - - - Default - - - QAbstractSpinBox::CorrectToNearestValue - - - false - - - 0 - - - 65535 - - - 0 - - - - - - - - 0 - 0 - + + 127.0.0.1:8081 - - Port: + + true @@ -124,31 +99,6 @@ - - - - false - - - - 0 - 0 - - - - 127.0.0.1 - - - true - - - 127.0.0.1 - - - true - - - @@ -328,22 +278,6 @@ - - radioExternalBytecoind - toggled(bool) - spinPort - setEnabled(bool) - - - 242 - 85 - - - 425 - 136 - - - editHost textChanged(QString) diff --git a/src/walletmodel.cpp b/src/walletmodel.cpp index e61cf9c..f7f6fc5 100644 --- a/src/walletmodel.cpp +++ b/src/walletmodel.cpp @@ -1072,6 +1072,11 @@ bool WalletModel::isAmethyst() const return pimpl_->walletType == "amethyst" || pimpl_->walletType == "hardware"; } +bool WalletModel::isViewOnly() const +{ + return pimpl_->viewOnly; +} + void WalletModel::reset() { beginResetModel(); diff --git a/src/walletmodel.h b/src/walletmodel.h index a7a8717..c12e881 100644 --- a/src/walletmodel.h +++ b/src/walletmodel.h @@ -162,6 +162,7 @@ class WalletModel : public QAbstractItemModel QString getAddress() const; bool isConnected() const; bool isAmethyst() const; + bool isViewOnly() const; quint32 getLastBlockHeight() const; QString getLastBlockHash() const;