Browse Source

Plugin infrastructure.

Initial separation of accounts into plugin.
cl-refactor
Gav Wood 10 years ago
parent
commit
a59eab65c9
  1. 115
      alethzero/AllAccounts.cpp
  2. 56
      alethzero/AllAccounts.h
  3. 134
      alethzero/AllAccounts.ui
  4. 5
      alethzero/CMakeLists.txt
  5. 92
      alethzero/Main.ui
  6. 60
      alethzero/MainFace.cpp
  7. 86
      alethzero/MainFace.h
  8. 78
      alethzero/MainWin.cpp
  9. 11
      alethzero/MainWin.h

115
alethzero/AllAccounts.cpp

@ -0,0 +1,115 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AllAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "AllAccounts.h"
#include <sstream>
#include <libdevcore/Log.h>
#include <libdevcore/SHA3.h>
#include <libevmcore/Instruction.h>
#include <libethereum/Client.h>
#include "ui_AllAccounts.h"
using namespace std;
using namespace dev;
using namespace az;
using namespace eth;
AllAccounts::AllAccounts(MainFace* _m):
Plugin(_m, "AllAccounts"),
m_ui(new Ui::AllAccounts)
{
m_ui->setupUi(dock());
refresh();
}
AllAccounts::~AllAccounts()
{
}
// TODO: Introduce interface for MainWin's refreshAccounts() and have it call refresh().
void AllAccounts::refresh()
{
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
m_ui->accounts->clear();
bool showContract = m_ui->showContracts->isChecked();
bool showBasic = m_ui->showBasic->isChecked();
bool onlyNamed = m_ui->onlyNamed->isChecked();
for (auto const& i: ethereum()->addresses())
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
#endif
m_refreshAccounts->setEnabled(false);
}
void AllAccounts::on_accounts_currentItemChanged()
{
m_ui->accountInfo->clear();
if (auto item = m_ui->accounts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto address = h160((byte const*)hba.data(), h160::ConstructFromPointer);
stringstream s;
try
{
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << main()->prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << main()->prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << ETH_HTML_DIV(ETH_HTML_MONO) << toHex(ethereum()->codeAt(address)) << "</div>";
m_ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::InvalidTrie)
{
m_ui->accountInfo->appendHtml("Corrupted trie.");
}
ui->accountInfo->moveCursor(QTextCursor::Start);
}
}
void AllAccounts::on_accounts_doubleClicked()
{
if (ui->accounts->count())
{
auto hba = ui->accounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}
void AllAccounts::on_refreshAccounts_clicked()
{
refreshAccounts();
}

56
alethzero/AllAccounts.h

@ -0,0 +1,56 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AllAccounts.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <QListWidget>
#include <QPlainTextEdit>
#include "MainFace.h"
namespace Ui {
class AllAccounts;
}
namespace dev
{
namespace az
{
class AllAccounts: public Plugin
{
public:
AllAccounts(MainFace* _m): Plugin(_m, "AllAccounts") {}
~AllAccounts();
void refresh();
public slots:
void on_accounts_currentItemChanged();
void on_accounts_doubleClicked();
void on_refreshAccounts_clicked();
private:
Ui::AllAccounts* m_ui;
QAction* m_refreshAccounts;
};
}
}

134
alethzero/AllAccounts.ui

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AllAccounts</class>
<widget class="QWidget" name="AllAccounts">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="accounts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

5
alethzero/CMakeLists.txt

@ -31,6 +31,9 @@ qt5_wrap_ui(ui_ExportState.h ExportState.ui)
qt5_wrap_ui(ui_GetPassword.h GetPassword.ui)
qt5_wrap_ui(ui_GasPricing.h GasPricing.ui)
# Extensions
qt5_wrap_ui(ui_AllAccounts.h AllAccounts.ui)
file(GLOB HEADERS "*.h")
if (APPLE)
@ -42,7 +45,7 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui
UI_RESOURCES alethzero.icns Main.ui Connect.ui Debugger.ui Transact.ui ExportState.ui GetPassword.ui GasPricing.ui AllAccounts.ui
WIN_RESOURCES alethzero.rc
)

92
alethzero/Main.ui

@ -615,98 +615,6 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLineEdit" name="accountsFilter">
<property name="placeholderText">
<string>Filter...</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showBasic">
<property name="text">
<string>Basic</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="showContracts">
<property name="text">
<string>Contracts</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="onlyNamed">
<property name="text">
<string>Only Named</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="refreshAccounts">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QListWidget" name="accounts">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QPlainTextEdit" name="accountInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::WheelFocus</enum>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>

60
alethzero/MainFace.cpp

@ -0,0 +1,60 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MainFace.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "MainFace.h"
using namespace dev;
using namespace az;
Plugin::Plugin(MainFace* _f, std::string const& _name):
m_main(_f),
m_name(_name)
{
_f->adoptPlugin(this);
}
QDockWidget* Plugin::dock(Qt::DockWidgetArea _area, QString _title)
{
if (_title.isEmpty())
_title = QString::fromStdString(m_name);
if (!m_dock)
{
m_dock = new QDockWidget(_title, m_main);
m_main->addDockWidget(_area, m_dock);
}
return m_dock;
}
void Plugin::addToDock(Qt::DockWidgetArea _area, QDockWidget* _dockwidget, Qt::Orientation _orientation)
{
m_main->addDockWidget(_area, m_dock, _orientation);
}
void Plugin::addAction(QAction* _a)
{
m_main->addAction(_a);
}
void MainFace::killPlugins()
{
m_plugins.clear();
}

86
alethzero/MainFace.h

@ -0,0 +1,86 @@
/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MainFace.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <memory>
#include <map>
#include <string>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QAction>
#include <QtWidgets/QDockWidget>
#include "Context.h"
namespace dev
{
namespace web3 { class WebThreeDirect; }
namespace eth { class Client; }
namespace shh { class WhisperHost; }
namespace az
{
class Plugin;
class MainFace: public QMainWindow, public Context
{
public:
explicit MainFace(QWidget* _parent = nullptr): QMainWindow(_parent) {}
void adoptPlugin(Plugin* _p) { m_plugins.insert(_p->name(), std::shared_ptr<Plugin>(_p)); }
void killPlugins();
// TODO: tidy - all should be references that throw if module unavailable.
// TODO: provide a set of available web3 modules.
virtual dev::web3::WebThreeDirect* web3() const = 0;
virtual dev::eth::Client* ethereum() const = 0;
virtual std::shared_ptr<dev::shh::WhisperHost> whisper() const = 0;
private:
std::unordered_map<std::string, std::shared_ptr<Plugin>> m_plugins;
};
class Plugin
{
public:
Plugin(MainFace* _f, std::string const& _name);
virtual ~Plugin() {}
std::string const& name() const { return m_name; }
dev::web3::WebThreeDirect* web3() const { return m_main->web3(); }
dev::eth::Client* ethereum() const { return m_main->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_main->whisper(); }
MainFace* main() { return m_main; }
QDockWidget* dock(Qt::DockWidgetArea _area = Qt::RightDockWidgetArea, QString _title = QString());
void addToDock(Qt::DockWidgetArea _area, QDockWidget* _dockwidget, Qt::Orientation _orientation);
void addAction(QAction* _a);
private:
MainFace* m_main;
std::string m_name;
QDockWidget* m_dock;
};
}
}

78
alethzero/MainWin.cpp

@ -74,13 +74,15 @@
#include "DappHost.h"
#include "WebPage.h"
#include "ExportState.h"
#include "AllAccounts.h"
#include "ui_Main.h"
#include "ui_GetPassword.h"
#include "ui_GasPricing.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::eth;
using namespace az;
using namespace p2p;
using namespace eth;
namespace js = json_spirit;
string Main::fromRaw(h256 _n, unsigned* _inc)
@ -126,8 +128,8 @@ static QString filterOutTerminal(QString _s)
return _s.replace(QRegExp("\x1b\\[(\\d;)?\\d+m"), "");
}
Main::Main(QWidget *parent) :
QMainWindow(parent),
Main::Main(QWidget* _parent):
MainFace(_parent),
ui(new Ui::Main),
m_transact(nullptr),
m_dappLoader(nullptr),
@ -302,6 +304,8 @@ Main::Main(QWidget *parent) :
s.setValue("splashMessage", false);
}
}
new dev::az::AllAccounts(this);
}
Main::~Main()
@ -1283,35 +1287,6 @@ void Main::on_onlyNamed_toggled()
ui->refreshAccounts->setEnabled(true);
}
void Main::on_refreshAccounts_clicked()
{
refreshAccounts();
}
void Main::refreshAccounts()
{
DEV_TIMED_FUNCTION;
#if ETH_FATDB || !ETH_TRUE
cwatch << "refreshAccounts()";
ui->accounts->clear();
bool showContract = ui->showContracts->isChecked();
bool showBasic = ui->showBasic->isChecked();
bool onlyNamed = ui->onlyNamed->isChecked();
for (auto const& i: ethereum()->addresses())
{
bool isContract = (ethereum()->codeHashAt(i) != EmptySHA3);
if (!((showContract && isContract) || (showBasic && !isContract)))
continue;
string r = render(i);
if (onlyNamed && !(r.find('"') != string::npos || r.substr(0, 2) == "XE"))
continue;
(new QListWidgetItem(QString("%2: %1 [%3]").arg(formatBalance(ethereum()->balanceAt(i)).c_str()).arg(QString::fromStdString(r)).arg((unsigned)ethereum()->countAt(i)), ui->accounts))
->setData(Qt::UserRole, QByteArray((char const*)i.data(), Address::size));
}
#endif
ui->refreshAccounts->setEnabled(false);
}
void Main::refreshBlockCount()
{
auto d = ethereum()->blockChain().details();
@ -1919,33 +1894,6 @@ void Main::debugDumpState(int _add)
}
}
void Main::on_accounts_currentItemChanged()
{
ui->accountInfo->clear();
if (auto item = ui->accounts->currentItem())
{
auto hba = item->data(Qt::UserRole).toByteArray();
assert(hba.size() == 20);
auto address = h160((byte const*)hba.data(), h160::ConstructFromPointer);
stringstream s;
try
{
auto storage = ethereum()->storageAt(address);
for (auto const& i: storage)
s << "@" << showbase << hex << prettyU256(i.first) << "&nbsp;&nbsp;&nbsp;&nbsp;" << showbase << hex << prettyU256(i.second) << "<br/>";
s << "<h4>Body Code (" << sha3(ethereum()->codeAt(address)).abridged() << ")</h4>" << disassemble(ethereum()->codeAt(address));
s << ETH_HTML_DIV(ETH_HTML_MONO) << toHex(ethereum()->codeAt(address)) << "</div>";
ui->accountInfo->appendHtml(QString::fromStdString(s.str()));
}
catch (dev::InvalidTrie)
{
ui->accountInfo->appendHtml("Corrupted trie.");
}
ui->accountInfo->moveCursor(QTextCursor::Start);
}
}
void Main::on_idealPeers_valueChanged(int)
{
m_webThree->setIdealPeerCount(ui->idealPeers->value());
@ -1964,16 +1912,6 @@ void Main::on_ourAccounts_doubleClicked()
m_logHistory.clear();
}*/
void Main::on_accounts_doubleClicked()
{
if (ui->accounts->count())
{
auto hba = ui->accounts->currentItem()->data(Qt::UserRole).toByteArray();
auto h = Address((byte const*)hba.data(), Address::ConstructFromPointer);
qApp->clipboard()->setText(QString::fromStdString(toHex(h.asArray())));
}
}
static shh::Topics topicFromText(QString _s)
{
shh::BuildTopic ret;

11
alethzero/MainWin.h

@ -42,6 +42,7 @@
#include "Transact.h"
#include "NatspecHandler.h"
#include "Connect.h"
#include "MainFace.h"
class QListWidgetItem;
class QActionGroup;
@ -69,7 +70,7 @@ using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
QString contentsOfQResource(std::string const& res);
class Main: public QMainWindow, public Context
class Main: public dev::az::MainFace
{
Q_OBJECT
@ -77,9 +78,9 @@ public:
explicit Main(QWidget *parent = 0);
~Main();
dev::WebThreeDirect* web3() const { return m_webThree.get(); }
dev::eth::Client* ethereum() const { return m_webThree->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const { return m_webThree->whisper(); }
dev::WebThreeDirect* web3() const override { return m_webThree.get(); }
dev::eth::Client* ethereum() const override { return m_webThree->ethereum(); }
std::shared_ptr<dev::shh::WhisperHost> whisper() const override { return m_webThree->whisper(); }
bool confirm() const;
NatSpecFace* natSpec() { return &m_natSpecDB; }
@ -159,8 +160,6 @@ private slots:
// Stuff concerning the blocks/transactions/accounts panels
void on_ourAccounts_itemClicked(QListWidgetItem* _i);
void on_ourAccounts_doubleClicked();
void on_accounts_doubleClicked();
void on_accounts_currentItemChanged();
void on_transactionQueue_currentItemChanged();
void on_blockChainFilter_textChanged();
void on_blocks_currentItemChanged();

Loading…
Cancel
Save