Browse Source

WIP: create namespace, delete key.

kevaview
Just Wonder 4 years ago
parent
commit
0c71cd4835
  1. 11
      src/qt/forms/kevadialog.ui
  2. 62
      src/qt/kevadialog.cpp
  3. 7
      src/qt/kevadialog.h
  4. 8
      src/qt/kevanamespacemodel.cpp
  5. 3
      src/qt/kevanamespacemodel.h
  6. 26
      src/qt/kevanewnamespacedialog.cpp
  7. 2
      src/qt/kevanewnamespacedialog.h
  8. 142
      src/qt/walletmodel.cpp
  9. 2
      src/qt/walletmodel.h

11
src/qt/forms/kevadialog.ui

@ -227,7 +227,7 @@ @@ -227,7 +227,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="showRequestButton">
<widget class="QPushButton" name="showValueButton">
<property name="enabled">
<bool>false</bool>
</property>
@ -247,7 +247,7 @@ @@ -247,7 +247,7 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="removeRequestButton">
<widget class="QPushButton" name="removeButton">
<property name="enabled">
<bool>false</bool>
</property>
@ -295,15 +295,12 @@ @@ -295,15 +295,12 @@
</customwidget>
</customwidgets>
<tabstops>
<tabstop>reqLabel</tabstop>
<tabstop>reqAmount</tabstop>
<tabstop>useBech32</tabstop>
<tabstop>reqMessage</tabstop>
<tabstop>receiveButton</tabstop>
<tabstop>clearButton</tabstop>
<tabstop>recentRequestsView</tabstop>
<tabstop>showRequestButton</tabstop>
<tabstop>removeRequestButton</tabstop>
<tabstop>showValueButton</tabstop>
<tabstop>removeButton</tabstop>
</tabstops>
<resources>
<include location="../bitcoin.qrc"/>

62
src/qt/kevadialog.cpp

@ -38,12 +38,12 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) : @@ -38,12 +38,12 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
if (!_platformStyle->getImagesOnButtons()) {
ui->receiveButton->setIcon(QIcon());
ui->showRequestButton->setIcon(QIcon());
ui->removeRequestButton->setIcon(QIcon());
ui->showValueButton->setIcon(QIcon());
ui->removeButton->setIcon(QIcon());
} else {
ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/address-book"));
ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit"));
ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
ui->showValueButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit"));
ui->removeButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
}
// context menu actions
@ -65,7 +65,6 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) : @@ -65,7 +65,6 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
}
void KevaDialog::setModel(WalletModel *_model)
@ -87,9 +86,9 @@ void KevaDialog::setModel(WalletModel *_model) @@ -87,9 +86,9 @@ void KevaDialog::setModel(WalletModel *_model)
tableView->setColumnWidth(KevaTableModel::Key, KEY_COLUMN_WIDTH);
tableView->setColumnWidth(KevaTableModel::Block, BLOCK_MINIMUM_COLUMN_WIDTH);
connect(tableView->selectionModel(),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this,
SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
connect(ui->kevaView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(kevaView_selectionChanged()));
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready.
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(tableView, BLOCK_MINIMUM_COLUMN_WIDTH, DATE_COLUMN_WIDTH, this);
}
@ -182,15 +181,15 @@ void KevaDialog::on_kevaView_doubleClicked(const QModelIndex &index) @@ -182,15 +181,15 @@ void KevaDialog::on_kevaView_doubleClicked(const QModelIndex &index)
dialog->show();
}
void KevaDialog::kevaView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void KevaDialog::kevaView_selectionChanged()
{
// Enable Show/Remove buttons only if anything is selected.
bool enable = !ui->kevaView->selectionModel()->selectedRows().isEmpty();
ui->showRequestButton->setEnabled(enable);
ui->removeRequestButton->setEnabled(enable);
ui->showValueButton->setEnabled(enable);
ui->removeButton->setEnabled(enable);
}
void KevaDialog::on_showRequestButton_clicked()
void KevaDialog::on_showValueButton_clicked()
{
if(!model || !model->getKevaTableModel() || !ui->kevaView->selectionModel())
return;
@ -201,16 +200,33 @@ void KevaDialog::on_showRequestButton_clicked() @@ -201,16 +200,33 @@ void KevaDialog::on_showRequestButton_clicked()
}
}
void KevaDialog::on_removeRequestButton_clicked()
void KevaDialog::on_removeButton_clicked()
{
if(!model || !model->getKevaTableModel() || !ui->kevaView->selectionModel())
return;
QModelIndexList selection = ui->kevaView->selectionModel()->selectedRows();
if(selection.empty())
return;
// correct for selection mode ContiguousSelection
QModelIndex firstIndex = selection.at(0);
model->getKevaTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
QMessageBox::StandardButton reply;
QModelIndex index = selection.at(0);
QModelIndex keyIdx = index.sibling(index.row(), KevaTableModel::Key);
QString keyStr = keyIdx.data(Qt::DisplayRole).toString();
reply = QMessageBox::warning(this, tr("Warning"), tr("Delete the key \"%1\"?").arg(keyStr),
QMessageBox::Cancel|QMessageBox::Ok);
if (reply == QMessageBox::Cancel) {
return;
}
std::string nameSpace = ui->nameSpace->text().toStdString();
std::string key = keyStr.toStdString();
if (this->model->deleteKevaEntry(nameSpace, key)) {
// correct for selection mode ContiguousSelection
QModelIndex firstIndex = selection.at(0);
model->getKevaTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
}
}
// We override the virtual resizeEvent of the QWidget to adjust tables column
@ -300,3 +316,17 @@ void KevaDialog::copyAmount() @@ -300,3 +316,17 @@ void KevaDialog::copyAmount()
{
copyColumnToClipboard(KevaTableModel::Block);
}
int KevaDialog::createNamespace(std::string displayName, std::string& namespaceId)
{
if (!this->model) {
return 0;
}
if (!this->model->createNamespace(displayName, namespaceId)) {
// TODO: show error message.
return 1;
}
return 1;
}

7
src/qt/kevadialog.h

@ -44,6 +44,7 @@ public: @@ -44,6 +44,7 @@ public:
void setModel(WalletModel *model);
void showNamespace(QString ns);
int createNamespace(std::string displayName, std::string& namespaceId);
public Q_SLOTS:
void clear();
@ -68,10 +69,10 @@ private Q_SLOTS: @@ -68,10 +69,10 @@ private Q_SLOTS:
void on_showContent_clicked();
void on_createNamespace_clicked();
void on_listNamespaces_clicked();
void on_showRequestButton_clicked();
void on_removeRequestButton_clicked();
void on_showValueButton_clicked();
void on_removeButton_clicked();
void on_kevaView_doubleClicked(const QModelIndex &index);
void kevaView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void kevaView_selectionChanged();
void updateDisplayUnit();
void showMenu(const QPoint &point);
void copyURI();

8
src/qt/kevanamespacemodel.cpp

@ -105,10 +105,14 @@ bool KevaNamespaceModel::removeRows(int row, int count, const QModelIndex &paren @@ -105,10 +105,14 @@ bool KevaNamespaceModel::removeRows(int row, int count, const QModelIndex &paren
Qt::ItemFlags KevaNamespaceModel::flags(const QModelIndex &index) const
{
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
const NamespaceEntry *rec = &list[index.row()];
if (rec->confirmed) {
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
} else {
return Qt::ItemIsSelectable;
}
}
// actually add to table in GUI
void KevaNamespaceModel::setNamespace(std::vector<NamespaceEntry> vNamespaceEntries)
{

3
src/qt/kevanamespacemodel.h

@ -16,10 +16,11 @@ class CWallet; @@ -16,10 +16,11 @@ class CWallet;
class NamespaceEntry
{
public:
NamespaceEntry() { }
NamespaceEntry():confirmed(true) { }
std::string id;
std::string name;
bool confirmed;
};
class NamespaceEntryLessThan

26
src/qt/kevanewnamespacedialog.cpp

@ -6,7 +6,9 @@ @@ -6,7 +6,9 @@
#include <qt/forms/ui_kevanewnamespacedialog.h>
#include <qt/kevatablemodel.h>
#include <qt/kevadialog.h>
#include <QPushButton>
#include <QModelIndex>
KevaNewNamespaceDialog::KevaNewNamespaceDialog(QWidget *parent) :
@ -14,14 +16,36 @@ KevaNewNamespaceDialog::KevaNewNamespaceDialog(QWidget *parent) : @@ -14,14 +16,36 @@ KevaNewNamespaceDialog::KevaNewNamespaceDialog(QWidget *parent) :
ui(new Ui::KevaNewNamespaceDialog)
{
ui->setupUi(this);
connect(ui->buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
connect(ui->buttonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(accept()));
connect(ui->namespaceText, SIGNAL(textChanged(const QString &)), this, SLOT(onNamespaceChanged(const QString &)));
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
}
void KevaNewNamespaceDialog::onNamespaceChanged(const QString & ns)
{
int length = ns.length();
bool enabled = length > 0;
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(enabled);
}
void KevaNewNamespaceDialog::accept()
{
// Create the namespace here.
KevaDialog* dialog = (KevaDialog*)this->parentWidget();
QString nsText = ui->namespaceText->text();
std::string namespaceId;
if (!dialog->createNamespace(nsText.toStdString(), namespaceId)) {
//TODO: error message.
return;
}
dialog->showNamespace(QString::fromStdString(namespaceId));
QDialog::accept();
}
void KevaNewNamespaceDialog::reject()
{
}
KevaNewNamespaceDialog::~KevaNewNamespaceDialog()
{
delete ui;

2
src/qt/kevanewnamespacedialog.h

@ -26,6 +26,8 @@ public: @@ -26,6 +26,8 @@ public:
public Q_SLOTS:
void accept();
void reject();
void onNamespaceChanged(const QString & ns);
private:
Ui::KevaNewNamespaceDialog *ui;

142
src/qt/walletmodel.cpp

@ -40,6 +40,8 @@ @@ -40,6 +40,8 @@
#include <QSet>
#include <QTimer>
const int NAMESPACE_LENGTH = 21;
const std::string DUMMY_NAMESPACE = "___DUMMY_NAMESPACE___";
WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) :
QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
@ -764,9 +766,27 @@ int WalletModel::getDefaultConfirmTarget() const @@ -764,9 +766,27 @@ int WalletModel::getDefaultConfirmTarget() const
void WalletModel::getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::string nameSpace)
{
valtype nameSpaceVal = ValtypeFromString(nameSpace);
{
// Get the unconfirmed namespaces and list them at the beginning.
LOCK (mempool.cs);
std::vector<std::tuple<valtype, valtype, valtype, uint256>> unconfirmedKeyValueList;
mempool.getUnconfirmedKeyValueList(unconfirmedKeyValueList, nameSpaceVal);
for (auto e : unconfirmedKeyValueList) {
KevaEntry entry;
entry.key = ValtypeToString(std::get<1>(e));
entry.value = ValtypeToString(std::get<2>(e));
entry.block = -1; // Unconfirmed.
entry.date = QDateTime();
vKevaEntries.push_back(std::move(entry));
}
}
LOCK(cs_main);
valtype nameSpaceVal = ValtypeFromString(nameSpace);
valtype key;
CKevaData data;
std::unique_ptr<CKevaIterator> iter(pcoinsTip->IterateKeys(nameSpaceVal));
@ -783,6 +803,7 @@ void WalletModel::getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::stri @@ -783,6 +803,7 @@ void WalletModel::getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::stri
}
vKevaEntries.push_back(std::move(entry));
}
}
void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEntries)
@ -833,6 +854,23 @@ void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEnt @@ -833,6 +854,23 @@ void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEnt
}
}
{
// Also get the unconfirmed namespaces and list them at the beginning.
LOCK (mempool.cs);
std::vector<std::tuple<valtype, valtype, uint256>> unconfirmedNamespaces;
mempool.getUnconfirmedNamespaceList(unconfirmedNamespaces);
for (auto ns: unconfirmedNamespaces) {
NamespaceEntry entry;
entry.id = ValtypeToString(std::get<0>(ns));
entry.name = ValtypeToString(std::get<1>(ns));
entry.confirmed = false;
vNamespaceEntries.push_back(std::move(entry));
}
}
// The confirmed namespaces.
std::map<std::string, std::string>::iterator it = mapObjects.begin();
while (it != mapObjects.end()) {
NamespaceEntry entry;
@ -842,3 +880,105 @@ void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEnt @@ -842,3 +880,105 @@ void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEnt
it++;
}
}
int WalletModel::createNamespace(std::string displayNameStr, std::string& namespaceId)
{
const valtype displayName = ValtypeFromString (displayNameStr);
if (displayName.size() > MAX_NAMESPACE_LENGTH) {
return 0;
}
CReserveKey keyName(wallet);
CPubKey pubKey;
const bool ok = keyName.GetReservedKey(pubKey, true);
assert(ok);
CKeyID keyId = pubKey.GetID();
// The namespace name is: Hash160("first txin")
// For now we don't know the first txin, so use dummy name here.
// It will be replaced later in CreateTransaction.
valtype namespaceDummy = ToByteVector(std::string(DUMMY_NAMESPACE));
assert(namespaceDummy.size() == NAMESPACE_LENGTH);
CScript redeemScript = GetScriptForDestination(WitnessV0KeyHash(keyId));
CScriptID scriptHash = CScriptID(redeemScript);
CScript addrName = GetScriptForDestination(scriptHash);
const CScript newScript = CKevaScript::buildKevaNamespace(addrName, namespaceDummy, displayName);
CCoinControl coinControl;
CWalletTx wtx;
valtype kevaNamespace;
SendMoneyToScript(wallet, newScript, nullptr, kevaNamespace,
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
keyName.KeepKey();
namespaceId = EncodeBase58Check(kevaNamespace);
return 1;
}
int WalletModel::deleteKevaEntry(std::string namespaceStr, std::string keyStr)
{
valtype nameSpace;
if (!DecodeKevaNamespace(namespaceStr, Params(), nameSpace)) {
//TODO: show error message.
return 0;
}
const valtype key = ValtypeFromString(keyStr);
if (key.size() > MAX_KEY_LENGTH) {
//TODO: show error message.
return 0;
}
bool hasKey = false;
CKevaData data;
{
LOCK2(cs_main, mempool.cs);
std::vector<std::tuple<valtype, valtype, valtype, uint256>> unconfirmedKeyValueList;
valtype val;
if (mempool.getUnconfirmedKeyValue(nameSpace, key, val)) {
if (val.size() > 0) {
hasKey = true;
}
} else if (pcoinsTip->GetName(nameSpace, key, data)) {
hasKey = true;
}
}
if (!hasKey) {
//TODO: show error message.
return 0;
}
COutput output;
std::string kevaNamespce = namespaceStr;
if (!wallet->FindKevaCoin(output, kevaNamespce)) {
// TODO: This namespace can not be updated
return 0;
}
const COutPoint outp(output.tx->GetHash(), output.i);
const CTxIn txIn(outp);
CReserveKey keyName(wallet);
CPubKey pubKeyReserve;
const bool ok = keyName.GetReservedKey(pubKeyReserve, true);
assert(ok);
CScript redeemScript = GetScriptForDestination(WitnessV0KeyHash(pubKeyReserve.GetID()));
CScriptID scriptHash = CScriptID(redeemScript);
CScript addrName = GetScriptForDestination(scriptHash);
const CScript kevaScript = CKevaScript::buildKevaDelete(addrName, nameSpace, key);
CCoinControl coinControl;
CWalletTx wtx;
valtype empty;
SendMoneyToScript(wallet, kevaScript, &txIn, empty,
KEVA_LOCKED_AMOUNT, false, wtx, coinControl);
keyName.KeepKey();
return 1;
}

2
src/qt/walletmodel.h

@ -229,6 +229,8 @@ public: @@ -229,6 +229,8 @@ public:
// Keva
void getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::string nameSpace);
void getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEntries);
int createNamespace(std::string displayName, std::string& namespaceId);
int deleteKevaEntry(std::string nameSpace, std::string key);
private:
CWallet *wallet;

Loading…
Cancel
Save