diff --git a/CMakeLists.txt b/CMakeLists.txt index d1ceda3..5fcfd9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,6 @@ set(VERSION_REVISION "0") set(VERSION "beta-4") option(FETCH_DEPS "Download dependencies if they are not found" ON) -option(XMRIG "Include XMRig module") option(OPENVR "Include OpenVR support") option(QML "Include QtQuick (QML)") option(ANDROID "Android deployment") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e899ba7..3bd5ac4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -172,10 +172,6 @@ if(TOR_BIN) target_compile_definitions(wowlet PRIVATE HAS_TOR_BIN=1) endif() -if(XMRIG) - target_compile_definitions(wowlet PRIVATE HAS_XMRIG=1) -endif() - if(ANDROID) target_compile_definitions(wowlet PRIVATE HAS_ANDROID=1) endif() @@ -389,7 +385,6 @@ message(STATUS "VERSION_REVISION: ${VERSION_REVISION}") message(STATUS "STATIC: ${STATIC}") message(STATUS "Include QtQuick (QML): ${QML}") message(STATUS "VERSION: ${VERSION}") -message(STATUS "Include the XMRIG tab: ${XMRIG}") message(STATUS "Include Valve's OpenVR library: ${OPENVR}") message(STATUS "This build is for Android: ${ANDROID}") message(STATUS "This build is for testing the Android app on desktop: ${ANDROID_DEBUG}") diff --git a/src/appcontext.cpp b/src/appcontext.cpp index 4b23c0a..244234e 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -163,10 +163,8 @@ AppContext::AppContext(QCommandLineParser *cmdargs) { AppContext::prices = new Prices(); // XMRig -#ifdef HAS_XMRIG this->XMRig = new XmRig(this->configDirectory, this); this->XMRig->prepare(); -#endif this->walletManager = WalletManager::instance(); QString logPath = QString("%1/daemon.log").arg(configDirectory); @@ -447,11 +445,12 @@ void AppContext::onWSMessage(const QJsonObject &msg) { else if(cmd == "rpc_nodes") { this->onWSNodes(msg.value("data").toArray()); } -#if defined(HAS_XMRIG) else if(cmd == "xmrig") { this->XMRigDownloads(msg.value("data").toObject()); } -#endif + else if(cmd == "wownerod_releases") { + emit WownerodDownloads(msg.value("data").toObject()); + } else if(cmd == "crypto_rates") { QJsonArray crypto_rates = msg.value("data").toArray(); AppContext::prices->cryptoPricesReceived(crypto_rates); diff --git a/src/appcontext.h b/src/appcontext.h index 9e9f99c..6d12de8 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -215,6 +215,7 @@ signals: void yellowUpdated(); void nodeSourceChanged(NodeSource nodeSource); void XMRigDownloads(const QJsonObject &data); + void WownerodDownloads(const QJsonObject &data); void pinLookupReceived(QString address, QString pin); void pinLookupErrorReceived(); void pinReceived(QString pin); diff --git a/src/assets.qrc b/src/assets.qrc index da545e3..9969331 100644 --- a/src/assets.qrc +++ b/src/assets.qrc @@ -37,6 +37,7 @@ assets/images/eye_blind.png assets/images/wowlet.png assets/images/file.png + assets/images/fire.png assets/images/gnome-calc.png assets/images/history.png assets/images/info.png diff --git a/src/assets/images/fire.png b/src/assets/images/fire.png new file mode 100644 index 0000000..6f5d037 Binary files /dev/null and b/src/assets/images/fire.png differ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1b5050b..aab4b84 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -171,22 +171,21 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : connect(m_ctx->nodes, &Nodes::WSNodeExhausted, this, &MainWindow::showWSNodeExhaustedMessage); // XMRig -#ifdef HAS_XMRIG m_xmrig = new XMRigWidget(m_ctx, this); ui->xmrRigLayout->addWidget(m_xmrig); connect(m_ctx->XMRig, &XmRig::output, m_xmrig, &XMRigWidget::onProcessOutput); connect(m_ctx->XMRig, &XmRig::error, m_xmrig, &XMRigWidget::onProcessError); + connect(m_ctx->XMRig, &XmRig::stopped, m_xmrig, &XMRigWidget::onStopped); + connect(m_ctx->XMRig, &XmRig::blockReward, m_xmrig, &XMRigWidget::onBlockReward); connect(m_ctx->XMRig, &XmRig::hashrate, m_xmrig, &XMRigWidget::onHashrate); connect(m_ctx, &AppContext::walletClosed, m_xmrig, &XMRigWidget::onWalletClosed); connect(m_ctx, &AppContext::walletOpened, m_xmrig, &XMRigWidget::onWalletOpened); - connect(m_ctx, &AppContext::XMRigDownloads, m_xmrig, &XMRigWidget::onDownloads); + connect(m_ctx, &AppContext::XMRigDownloads, m_xmrig, &XMRigWidget::onRigDownloads); + connect(m_ctx, &AppContext::WownerodDownloads, m_xmrig, &XMRigWidget::onWownerodDownloads); connect(m_xmrig, &XMRigWidget::miningStarted, [=]{ m_ctx->setWindowTitle(true); }); connect(m_xmrig, &XMRigWidget::miningEnded, [=]{ m_ctx->setWindowTitle(false); }); -#else - ui->tabWidget->setTabVisible(Tabs::XMRIG, false); -#endif connect(ui->ccsWidget, &CCSWidget::selected, this, &MainWindow::showSendScreen); connect(m_ctx, &AppContext::ccsUpdated, ui->ccsWidget->model(), &CCSModel::updateEntries); @@ -421,13 +420,9 @@ void MainWindow::initMenu() { m_tabShowHideMapper["Calc"] = new ToggleTab(ui->tabCalc, "Calc", "Calc", ui->actionShow_calc, Config::showTabCalc); m_tabShowHideSignalMapper->setMapping(ui->actionShow_calc, "Calc"); -#if defined(HAS_XMRIG) connect(ui->actionShow_XMRig, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); m_tabShowHideMapper["Mining"] = new ToggleTab(ui->tabXmrRig, "Mining", "Mining", ui->actionShow_XMRig, Config::showTabXMRig); m_tabShowHideSignalMapper->setMapping(ui->actionShow_XMRig, "Mining"); -#else - ui->actionShow_XMRig->setVisible(false); -#endif for (const auto &key: m_tabShowHideMapper.keys()) { const auto toggleTab = m_tabShowHideMapper.value(key); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 574c282..a7de9cf 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -207,6 +207,20 @@ + + + + :/assets/images/mining.png:/assets/images/mining.png + + + Mining + + + + + + + @@ -330,20 +344,6 @@ - - - - :/assets/images/mining.png:/assets/images/mining.png - - - Mining - - - - - - - diff --git a/src/utils/config.cpp b/src/utils/config.cpp index 6cd65ba..7068595 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -33,14 +33,14 @@ static const QHash configStrings = { {Config::autoOpenWalletPath,{QS("autoOpenWalletPath"), ""}}, {Config::walletPath,{QS("walletPath"), ""}}, {Config::xmrigPath,{QS("xmrigPath"), ""}}, - {Config::xmrigPool,{QS("xmrigPool"), "cryptonote.social:2223"}}, + {Config::wownerodPath, {QS("wownerodPath"), ""}}, {Config::nodes,{QS("nodes"), "{}"}}, {Config::websocketEnabled,{QS("websocketEnabled"), true}}, {Config::nodeSource,{QS("nodeSource"), 0}}, {Config::useOnionNodes,{QS("useOnionNodes"), false}}, {Config::showTabHome,{QS("showTabHome"), true}}, {Config::showTabCoins,{QS("showTabCoins"), false}}, - {Config::showTabXMRig,{QS("showTabXMRig"), false}}, + {Config::showTabXMRig,{QS("showTabXMRig"), true}}, {Config::showTabCalc,{QS("showTabCalc"), false}}, {Config::geometry, {QS("geometry"), {}}}, {Config::windowState, {QS("windowState"), {}}}, diff --git a/src/utils/config.h b/src/utils/config.h index 98732fb..b4304f4 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -35,7 +35,7 @@ public: walletDirectory, walletPath, xmrigPath, - xmrigPool, + wownerodPath, nodes, websocketEnabled, nodeSource, diff --git a/src/utils/xmrig.cpp b/src/utils/xmrig.cpp index 4cdb709..69a9698 100644 --- a/src/utils/xmrig.cpp +++ b/src/utils/xmrig.cpp @@ -7,10 +7,17 @@ #include "utils/utils.h" #include "utils/xmrig.h" -#include "appcontext.h" +#include "mainwindow.h" -XmRig::XmRig(const QString &configDir, QObject *parent) : QObject(parent) { - this->rigDir = QDir(configDir).filePath("xmrig"); +XmRig::XmRig(const QString &configDir, QObject *parent) : + QObject(parent), + m_statusTimer(new QTimer(this)) +{ + m_statusTimer->setInterval(5000); + connect(m_statusTimer, &QTimer::timeout, [this]{ + if(mining_started && m_process.state() == QProcess::Running) + m_process.write("status\n"); + }); } void XmRig::prepare() { @@ -28,74 +35,82 @@ void XmRig::stop() { m_process.terminate(); #endif } + m_statusTimer->stop(); } -void XmRig::start(const QString &path, - int threads, - const QString &address, - const QString &username, - const QString &password, - bool tor, bool tls) { +bool XmRig::start(const QString &path, int threads) { + m_ctx = MainWindow::getContext(); + auto state = m_process.state(); if (state == QProcess::ProcessState::Running || state == QProcess::ProcessState::Starting) { - emit error("Can't start XMRig, already running or starting"); - return; + emit error("Can't start wownerod, already running or starting"); + return false; } if(path.isEmpty()) { - emit error("XmRig->Start path parameter missing."); - return; + emit error("wownerod path seems to be empty."); + return false; } if(!Utils::fileExists(path)) { - emit error(QString("Path to XMRig binary invalid; file does not exist: %1").arg(path)); - return; + emit error(QString("Path to wownerod binary is invalid; file does not exist: %1").arg(path)); + return false; } + auto privateSpendKey = m_ctx->currentWallet->getSecretSpendKey(); QStringList arguments; - arguments << "-o" << address; - arguments << "-a" << "rx/wow"; - arguments << "-u" << username; - if(!password.isEmpty()) - arguments << "-p" << password; - arguments << "--no-color"; - arguments << "-t" << QString::number(threads); - if(tor) - arguments << "-x" << QString("%1:%2").arg(Tor::torHost).arg(Tor::torPort); - if(tls) - arguments << "--tls"; - arguments << "--donate-level" << "1"; + arguments << "--mining-threads" << QString::number(threads); + arguments << "--start-mining" << m_ctx->currentWallet->address(0, 0); + arguments << "--spendkey" << privateSpendKey; + QString cmd = QString("%1 %2").arg(path, arguments.join(" ")); + cmd = cmd.replace(privateSpendKey, "[redacted]"); emit output(cmd.toUtf8()); + m_process.start(path, arguments); + m_statusTimer->start(); + return true; } void XmRig::stateChanged(QProcess::ProcessState state) { if(state == QProcess::ProcessState::Running) - emit output("XMRig started"); - else if (state == QProcess::ProcessState::NotRunning) - emit output("XMRig stopped"); + emit output("wownerod started"); + else if (state == QProcess::ProcessState::NotRunning) { + emit output("wownerod stopped"); + this->mining_started = false; + emit stopped(); + } } void XmRig::handleProcessOutput() { - QByteArray _output = m_process.readAllStandardOutput(); - if(_output.contains("miner") && _output.contains("speed")) { - // detect hashrate - auto str = Utils::barrayToString(_output); - auto spl = str.mid(str.indexOf("speed")).split(" "); - auto rate = spl.at(2) + "H/s"; - qDebug() << "mining hashrate: " << rate; - emit hashrate(rate); - } + QByteArray data = m_process.readAllStandardOutput(); + + for(auto &line: data.split('\n')) { + if(line.indexOf("\tI") >= 20) + line = line.remove(0, line.indexOf("\tI") + 2); + if(line.trimmed().isEmpty() || line.startsWith("status")) continue; + if(line.contains("Mining started. Good luck")) + this->mining_started = true; + else if(line.contains("you won a block reward")) + emit blockReward(); + else if(line.contains("mining at")) { + auto rate = line.remove(0, line.indexOf("mining at")); + rate = rate.remove(rate.indexOf(","), rate.length()); + rate = rate.remove(0, 9); + rate = rate.trimmed(); + emit hashrate(rate); + } - emit output(_output); + emit output(line); + } } void XmRig::handleProcessError(QProcess::ProcessError err) { if (err == QProcess::ProcessError::Crashed) - emit error("XMRig crashed or killed"); + emit error("wownerod crashed or killed"); else if (err == QProcess::ProcessError::FailedToStart) { - auto path = config()->get(Config::xmrigPath).toString(); - emit error(QString("XMRig binary failed to start: %1").arg(path)); + auto path = config()->get(Config::wownerodPath).toString(); + emit error(QString("wownerod binary failed to start: %1").arg(path)); } + this->mining_started = false; } diff --git a/src/utils/xmrig.h b/src/utils/xmrig.h index c25c52a..662de3c 100644 --- a/src/utils/xmrig.h +++ b/src/utils/xmrig.h @@ -14,6 +14,7 @@ #include "utils/childproc.h" +class AppContext; class XmRig : public QObject { Q_OBJECT @@ -22,15 +23,14 @@ public: explicit XmRig(const QString &configDir, QObject *parent = nullptr); void prepare(); - void start(const QString &path, int threads, const QString &address, const QString &username, const QString &password, bool tor = false, bool tls = true); + bool start(const QString &path, int threads); void stop(); - QString rigDir; - QString rigPath; - signals: void error(const QString &msg); void output(const QByteArray &data); + void stopped(); + void blockReward(); void hashrate(const QString &rate); private slots: @@ -40,6 +40,9 @@ private slots: private: ChildProcess m_process; + AppContext *m_ctx; + QTimer *m_statusTimer; + bool mining_started = false; }; #endif //WOWLET_XMRIG_H diff --git a/src/widgets/xmrigwidget.cpp b/src/widgets/xmrigwidget.cpp index c683c9e..74b634c 100644 --- a/src/widgets/xmrigwidget.cpp +++ b/src/widgets/xmrigwidget.cpp @@ -15,19 +15,28 @@ XMRigWidget::XMRigWidget(AppContext *ctx, QWidget *parent) : QWidget(parent), ui(new Ui::XMRigWidget), m_ctx(ctx), - m_model(new QStandardItemModel(this)), - m_contextMenu(new QMenu(this)) + m_modelRig(new QStandardItemModel(this)), + m_modelWownerod(new QStandardItemModel(this)), + m_contextMenuRig(new QMenu(this)), + m_contextMenuWownerod(new QMenu(this)) { ui->setupUi(this); - QPixmap p(":assets/images/mining.png"); - ui->lbl_logo->setPixmap(p.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + QPixmap p(":assets/images/fire.png"); + ui->lbl_logo->setPixmap(p.scaled(268, 271, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + ui->lbl_reward->hide(); - // table - ui->tableView->setModel(this->m_model); - m_contextMenu->addAction(QIcon(":/assets/images/network.png"), "Download file", this, &XMRigWidget::linkClicked); - connect(ui->tableView, &QHeaderView::customContextMenuRequested, this, &XMRigWidget::showContextMenu); - connect(ui->tableView, &QTableView::doubleClicked, this, &XMRigWidget::linkClicked); + // table XMRig + ui->tableRig->setModel(this->m_modelRig); + m_contextMenuRig->addAction(QIcon(":/assets/images/network.png"), "Download file", this, &XMRigWidget::rigLinkClicked); + connect(ui->tableRig, &QHeaderView::customContextMenuRequested, this, &XMRigWidget::showContextRigMenu); + connect(ui->tableRig, &QTableView::doubleClicked, this, &XMRigWidget::rigLinkClicked); + + // table wownerod + ui->tableWownerod->setModel(this->m_modelWownerod); + m_contextMenuWownerod->addAction(QIcon(":/assets/images/network.png"), "Download file", this, &XMRigWidget::wownerodLinkClicked); + connect(ui->tableWownerod, &QHeaderView::customContextMenuRequested, this, &XMRigWidget::showContextWownerodMenu); + connect(ui->tableWownerod, &QTableView::doubleClicked, this, &XMRigWidget::wownerodLinkClicked); // threads ui->threadSlider->setMinimum(1); @@ -47,75 +56,49 @@ XMRigWidget::XMRigWidget(AppContext *ctx, QWidget *parent) : // defaults ui->btn_stop->setEnabled(false); ui->check_autoscroll->setChecked(true); - ui->relayTor->setChecked(false); - ui->check_tls->setChecked(true); +#ifdef Q_OS_WIN + ui->label_path->setText("Path to wownerod.exe"); +#endif ui->label_status->setTextInteractionFlags(Qt::TextSelectableByMouse); ui->label_status->hide(); - ui->soloFrame->hide(); - ui->poolFrame->hide(); - // XMRig binary - auto path = config()->get(Config::xmrigPath).toString(); - if(!path.isEmpty()) { + // wownerod binary + auto path = config()->get(Config::wownerodPath).toString(); + if(!path.isEmpty()) ui->lineEdit_path->setText(path); - } - // pools - ui->poolFrame->show(); - ui->combo_pools->insertItems(0, m_pools); - auto preferredPool = config()->get(Config::xmrigPool).toString(); - if (m_pools.contains(preferredPool)) - ui->combo_pools->setCurrentIndex(m_pools.indexOf(preferredPool)); - else { - preferredPool = m_pools.at(0); - config()->set(Config::xmrigPool, preferredPool); - } - connect(ui->combo_pools, QOverload::of(&QComboBox::currentIndexChanged), this, &XMRigWidget::onPoolChanged); + connect(ui->lineEdit_path, &QLineEdit::textChanged, [=] { + config()->set(Config::wownerodPath, ui->lineEdit_path->text().trimmed()); + }); // info - ui->console->appendPlainText(QString("Detected %1 CPU threads.").arg(threads)); - if(!path.isEmpty() && !Utils::fileExists(path)) - ui->console->appendPlainText("Invalid path to XMRig binary detected. Please reconfigure on the Settings tab."); - else - ui->console->appendPlainText(QString("XMRig path set to %1").arg(path)); - - ui->console->appendPlainText("Ready to mine."); - - // username/password - connect(ui->lineEdit_password, &QLineEdit::editingFinished, [=]() { - m_ctx->currentWallet->setCacheAttribute("wowlet.xmrig_password", ui->lineEdit_password->text()); - m_ctx->storeWallet(); - }); - connect(ui->lineEdit_address, &QLineEdit::editingFinished, [=]() { - m_ctx->currentWallet->setCacheAttribute("wowlet.xmrig_username", ui->lineEdit_address->text()); - m_ctx->storeWallet(); - }); + this->appendText(QString("Detected %1 CPU threads.").arg(threads)); + if(path.isEmpty()) + this->appendText(QString("wownerod path is empty - please point towards the wownerod executable.").arg(path)); + else if(!Utils::fileExists(path)) + this->appendText("Invalid path to the wownerod executable detected. Please set the correct path."); + else { + this->appendText(QString("wownerod path set to '%1'").arg(path)); + this->appendText("Ready to mine."); + } +} - // checkbox connects - connect(ui->check_solo, &QCheckBox::stateChanged, this, &XMRigWidget::onSoloChecked); +void XMRigWidget::appendText(const QString &line) { + ui->console->appendPlainText(line); + m_consoleBuffer += 1; + if(m_consoleBuffer >= m_consoleBufferMax) { + ui->console->clear(); + m_consoleBuffer = 0; + } } void XMRigWidget::onWalletClosed() { this->onStopClicked(); this->onClearClicked(); - ui->lineEdit_password->setText(""); - ui->lineEdit_address->setText(""); } void XMRigWidget::onWalletOpened(Wallet *wallet){ - // Xmrig username - auto username = m_ctx->currentWallet->getCacheAttribute("wowlet.xmrig_username"); - if(!username.isEmpty()) - ui->lineEdit_address->setText(username); - - // Xmrig passwd - auto password = m_ctx->currentWallet->getCacheAttribute("wowlet.xmrig_password"); - if(!password.isEmpty()) { - ui->lineEdit_password->setText(password); - } else { - ui->lineEdit_password->setText("wowlet"); - m_ctx->currentWallet->setCacheAttribute("wowlet.xmrig_password", ui->lineEdit_password->text()); - } + int egiwoge = 1; } void XMRigWidget::onThreadsValueChanged(int threads) { @@ -123,50 +106,28 @@ void XMRigWidget::onThreadsValueChanged(int threads) { ui->label_threads->setText(QString("CPU threads: %1").arg(m_threads)); } -void XMRigWidget::onPoolChanged(int pos) { - config()->set(Config::xmrigPool, m_pools.at(pos)); -} - void XMRigWidget::onBrowseClicked() { QString fileName = QFileDialog::getOpenFileName( - this, "Path to XMRig executable", QDir::homePath()); + this, "Path to wownerod executable", QDir::homePath()); if (fileName.isEmpty()) return; - config()->set(Config::xmrigPath, fileName); + config()->set(Config::wownerodPath, fileName); ui->lineEdit_path->setText(fileName); } +void XMRigWidget::onBlockReward() { + QDateTime date = QDateTime::currentDateTime(); + QString formattedTime = date.toString("yyyy/MM/dd hh:mm"); + ui->lbl_reward->setText(QString("Congrats: new block found at %1").arg(formattedTime)); + ui->lbl_reward->show(); +} + void XMRigWidget::onClearClicked() { ui->console->clear(); } void XMRigWidget::onStartClicked() { - QString xmrigPath; - bool solo = ui->check_solo->isChecked(); - xmrigPath = config()->get(Config::xmrigPath).toString(); - - // username is receiving address usually - auto username = m_ctx->currentWallet->getCacheAttribute("wowlet.xmrig_username"); - auto password = m_ctx->currentWallet->getCacheAttribute("wowlet.xmrig_password"); - - if(username.isEmpty()) { - QString err = "Please specify a receiving address on the Settings screen"; - ui->console->appendPlainText(err); - QMessageBox::warning(this, "Error", err); - return; - } - - QString address; - if(solo) - address = ui->lineEdit_solo->text().trimmed(); - else - address = config()->get(Config::xmrigPool).toString(); - - if(address.contains("cryptonote.social") && !username.contains(".")) { - // cryptonote social requires ., we'll just grab a few chars from primary addy - username = QString("%1.%2").arg(username, m_ctx->currentWallet->address(0, 0).mid(0, 6)); - } - - m_ctx->XMRig->start(xmrigPath, m_threads, address, username, password, ui->relayTor->isChecked(), ui->check_tls->isChecked()); + auto binPath = config()->get(Config::wownerodPath).toString(); + if(!m_ctx->XMRig->start(binPath, m_threads)) return; ui->btn_start->setEnabled(false); ui->btn_stop->setEnabled(true); @@ -175,10 +136,6 @@ void XMRigWidget::onStartClicked() { void XMRigWidget::onStopClicked() { m_ctx->XMRig->stop(); - ui->btn_start->setEnabled(true); - ui->btn_stop->setEnabled(false); - ui->label_status->hide(); - emit miningEnded(); } void XMRigWidget::onProcessOutput(const QByteArray &data) { @@ -186,14 +143,21 @@ void XMRigWidget::onProcessOutput(const QByteArray &data) { if(output.endsWith("\n")) output = output.trimmed(); - ui->console->appendPlainText(output); + this->appendText(output); if(ui->check_autoscroll->isChecked()) ui->console->verticalScrollBar()->setValue(ui->console->verticalScrollBar()->maximum()); } +void XMRigWidget::onStopped() { + ui->btn_start->setEnabled(true); + ui->btn_stop->setEnabled(false); + ui->label_status->hide(); + emit miningEnded(); +} + void XMRigWidget::onProcessError(const QString &msg) { - ui->console->appendPlainText("\n" + msg); + this->appendText(msg); ui->btn_start->setEnabled(true); ui->btn_stop->setEnabled(false); ui->label_status->hide(); @@ -205,17 +169,62 @@ void XMRigWidget::onHashrate(const QString &hashrate) { ui->label_status->setText(QString("Mining at %1").arg(hashrate)); } -void XMRigWidget::onDownloads(const QJsonObject &data) { - // For the downloads table we'll manually update the table - // with items once, as opposed to creating a class in - // src/models/. Saves effort; full-blown model - // is unnecessary in this case. +void XMRigWidget::onWownerodDownloads(const QJsonObject &data) { + m_modelWownerod->clear(); + m_urlsWownerod.clear(); + + auto version = data.value("version").toString(); + ui->label_latest_version_wownerod->setText(QString("Latest version: %1").arg(version)); + QJsonObject assets = data.value("assets").toObject(); + + const auto _linux = assets.value("linux").toArray(); + const auto macos = assets.value("macos").toArray(); + const auto windows = assets.value("windows").toArray(); - m_model->clear(); - m_urls.clear(); + auto info = QSysInfo::productType(); + QJsonArray *os_assets; + if(info == "osx") { + os_assets = const_cast(&macos); + } else if (info == "windows") { + os_assets = const_cast(&windows); + } else { + // assume linux + os_assets = const_cast(&_linux); + } + + int i = 0; + for(const auto &entry: *os_assets) { + auto _obj = entry.toObject(); + auto _name = _obj.value("name").toString(); + auto _url = _obj.value("url").toString(); + auto _created_at = _obj.value("created_at").toString(); + + m_urlsWownerod.append(_url); + auto download_count = _obj.value("download_count").toInt(); + + m_modelWownerod->setItem(i, 0, Utils::qStandardItem(_name)); + m_modelWownerod->setItem(i, 1, Utils::qStandardItem(_created_at)); + m_modelWownerod->setItem(i, 2, Utils::qStandardItem(QString::number(download_count))); + i++; + } + + m_modelWownerod->setHeaderData(0, Qt::Horizontal, tr("Filename"), Qt::DisplayRole); + m_modelWownerod->setHeaderData(1, Qt::Horizontal, tr("Date"), Qt::DisplayRole); + m_modelWownerod->setHeaderData(2, Qt::Horizontal, tr("Downloads"), Qt::DisplayRole); + + ui->tableWownerod->verticalHeader()->setVisible(false); + ui->tableWownerod->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->tableWownerod->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + ui->tableWownerod->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->tableWownerod->setColumnWidth(2, 100); +} + +void XMRigWidget::onRigDownloads(const QJsonObject &data) { + m_modelRig->clear(); + m_urlsRig.clear(); auto version = data.value("version").toString(); - ui->label_latest_version->setText(QString("Latest version: %1").arg(version)); + ui->label_latest_version_rig->setText(QString("Latest version: %1").arg(version)); QJsonObject assets = data.value("assets").toObject(); const auto _linux = assets.value("linux").toArray(); @@ -240,54 +249,54 @@ void XMRigWidget::onDownloads(const QJsonObject &data) { auto _url = _obj.value("url").toString(); auto _created_at = _obj.value("created_at").toString(); - m_urls.append(_url); + m_urlsRig.append(_url); auto download_count = _obj.value("download_count").toInt(); - m_model->setItem(i, 0, Utils::qStandardItem(_name)); - m_model->setItem(i, 1, Utils::qStandardItem(_created_at)); - m_model->setItem(i, 2, Utils::qStandardItem(QString::number(download_count))); + m_modelRig->setItem(i, 0, Utils::qStandardItem(_name)); + m_modelRig->setItem(i, 1, Utils::qStandardItem(_created_at)); + m_modelRig->setItem(i, 2, Utils::qStandardItem(QString::number(download_count))); i++; } - m_model->setHeaderData(0, Qt::Horizontal, tr("Filename"), Qt::DisplayRole); - m_model->setHeaderData(1, Qt::Horizontal, tr("Date"), Qt::DisplayRole); - m_model->setHeaderData(2, Qt::Horizontal, tr("Downloads"), Qt::DisplayRole); + m_modelRig->setHeaderData(0, Qt::Horizontal, tr("Filename"), Qt::DisplayRole); + m_modelRig->setHeaderData(1, Qt::Horizontal, tr("Date"), Qt::DisplayRole); + m_modelRig->setHeaderData(2, Qt::Horizontal, tr("Downloads"), Qt::DisplayRole); - ui->tableView->verticalHeader()->setVisible(false); - ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); - ui->tableView->setColumnWidth(2, 100); + ui->tableRig->verticalHeader()->setVisible(false); + ui->tableRig->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->tableRig->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + ui->tableRig->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + ui->tableRig->setColumnWidth(2, 100); } -void XMRigWidget::showContextMenu(const QPoint &pos) { - QModelIndex index = ui->tableView->indexAt(pos); - if (!index.isValid()) { +void XMRigWidget::showContextRigMenu(const QPoint &pos) { + QModelIndex index = ui->tableRig->indexAt(pos); + if (!index.isValid()) return; - } - m_contextMenu->exec(ui->tableView->viewport()->mapToGlobal(pos)); + m_contextMenuRig->exec(ui->tableRig->viewport()->mapToGlobal(pos)); } -void XMRigWidget::onSoloChecked(int state) { - if(state == 2) { - ui->poolFrame->hide(); - ui->soloFrame->show(); - ui->check_tls->setChecked(false); - } - else { - ui->poolFrame->show(); - ui->soloFrame->hide(); - } +void XMRigWidget::showContextWownerodMenu(const QPoint &pos) { + QModelIndex index = ui->tableWownerod->indexAt(pos); + if (!index.isValid()) + return; + m_contextMenuRig->exec(ui->tableWownerod->viewport()->mapToGlobal(pos)); +} + +void XMRigWidget::wownerodLinkClicked() { + QModelIndex index = ui->tableRig->currentIndex(); + auto download_link = m_urlsRig.at(index.row()); + Utils::externalLinkWarning(this, download_link); } -void XMRigWidget::linkClicked() { - QModelIndex index = ui->tableView->currentIndex(); - auto download_link = m_urls.at(index.row()); +void XMRigWidget::rigLinkClicked() { + QModelIndex index = ui->tableRig->currentIndex(); + auto download_link = m_urlsRig.at(index.row()); Utils::externalLinkWarning(this, download_link); } QStandardItemModel *XMRigWidget::model() { - return m_model; + return m_modelRig; } XMRigWidget::~XMRigWidget() { diff --git a/src/widgets/xmrigwidget.h b/src/widgets/xmrigwidget.h index d146204..465aaf2 100644 --- a/src/widgets/xmrigwidget.h +++ b/src/widgets/xmrigwidget.h @@ -30,33 +30,41 @@ public slots: void onWalletOpened(Wallet *wallet); void onStartClicked(); void onStopClicked(); + void onStopped(); void onClearClicked(); - void onDownloads(const QJsonObject &data); - void linkClicked(); + void onBlockReward(); + void onRigDownloads(const QJsonObject &data); + void onWownerodDownloads(const QJsonObject &data); + void rigLinkClicked(); + void wownerodLinkClicked(); void onProcessError(const QString &msg); void onProcessOutput(const QByteArray &msg); void onHashrate(const QString &hashrate); - void onSoloChecked(int state); private slots: void onBrowseClicked(); void onThreadsValueChanged(int date); - void onPoolChanged(int pos); signals: void miningStarted(); void miningEnded(); private: - void showContextMenu(const QPoint &pos); + void showContextRigMenu(const QPoint &pos); + void showContextWownerodMenu(const QPoint &pos); + void appendText(const QString &line); AppContext *m_ctx; Ui::XMRigWidget *ui; - QStandardItemModel *m_model; - QMenu *m_contextMenu; + QStandardItemModel *m_modelRig; + QStandardItemModel *m_modelWownerod; + QMenu *m_contextMenuRig; + QMenu *m_contextMenuWownerod; int m_threads; - QStringList m_urls; - QStringList m_pools{"cryptonote.social:2223", "pool.hashvault.pro:8888"}; + QStringList m_urlsRig; + QStringList m_urlsWownerod; + unsigned int m_consoleBuffer = 0; + unsigned int m_consoleBufferMax = 2000; }; #endif // REDDITWIDGET_H diff --git a/src/widgets/xmrigwidget.ui b/src/widgets/xmrigwidget.ui index 5fc6db9..1fdeb50 100644 --- a/src/widgets/xmrigwidget.ui +++ b/src/widgets/xmrigwidget.ui @@ -6,8 +6,8 @@ 0 0 - 1329 - 540 + 959 + 534 @@ -29,14 +29,66 @@ - 1 + 0 Mining - - + + + + + + + Clear + + + + + + + auto-scroll + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Mining at + + + + + + + Stop + + + + + + + Start mining + + + + + + QFrame::NoFrame @@ -44,7 +96,7 @@ QFrame::Plain - + 0 @@ -57,378 +109,189 @@ 0 - + true - - - - - - Clear - - - - - - - auto-scroll - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Mining at - - - - - - - Stop - - - - - - - Start mining - - - - - + + + + + + Executable + + + + + + + + + Path to wownerod... + + + + + + + Browse + + + + + + + + + CPU threads + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Horizontal + + + + + + + rewardtxt + + + - Settings + How-To - - - + + + + + 12 + - + - - - - - - - Threads: - - - - - - - - - Qt::Horizontal - - - - - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - + + + img + + - - - QFrame::NoFrame + + + Qt::Vertical - - QFrame::Plain + + + 20 + 40 + + + + + + + + + + + + + 16 + + + + How to solo mine - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - TLS - - - - - - - Tor - - - - - - - Solo mine - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + 1. Go to the 'wownerod' tab + + - - - - - QFrame::NoFrame - - - QFrame::Plain - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - Pool - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Plain - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - Node address - - - - - - - 127.0.0.1:18081 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - + + + 2. Download the latest wownerod archive (right-click) + + - - - - - Receiving address - - - - - - - - - - Password (optional) - - - - - - - - - - XMRig executable - - - - - - - - - /path/to/xmrig - - - - - - - Browse - - - - - - + + + 3. Unpack/extract the archive + + - - - - - - Qt::Horizontal - - - QSizePolicy::Maximum - - - - 24 - 20 - - - - - - - + - logoimg + 4. Go to the 'Mining' tab + + + + + + + 5. Click 'browse' and select the previously extracted wownerod executable + + + + + + + 6. Click 'Start mining' to start solo-mining. Goodluck! + + + + + + + P.S: Do not start multiple wownerod instances, i.e if you already have one running on your machine, things will (probably) crash and burn. + + + true @@ -447,32 +310,85 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + - - - - Qt::Vertical + + + + + wownerod + + + + + + + + Latest version: + + + + + + + false + + + (right-click to download) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::CustomContextMenu - - - 20 - 0 - + + QAbstractItemView::NoEditTriggers - + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + false + + - Downloads + XMRig - + Latest version: @@ -494,7 +410,7 @@ - + Qt::CustomContextMenu