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

62
src/qt/kevadialog.cpp

@ -38,12 +38,12 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
if (!_platformStyle->getImagesOnButtons()) { if (!_platformStyle->getImagesOnButtons()) {
ui->receiveButton->setIcon(QIcon()); ui->receiveButton->setIcon(QIcon());
ui->showRequestButton->setIcon(QIcon()); ui->showValueButton->setIcon(QIcon());
ui->removeRequestButton->setIcon(QIcon()); ui->removeButton->setIcon(QIcon());
} else { } else {
ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/address-book")); ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/address-book"));
ui->showRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit")); ui->showValueButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit"));
ui->removeRequestButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); ui->removeButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
} }
// context menu actions // context menu actions
@ -65,7 +65,6 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel())); connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage())); connect(copyMessageAction, SIGNAL(triggered()), this, SLOT(copyMessage()));
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount())); connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
} }
void KevaDialog::setModel(WalletModel *_model) void KevaDialog::setModel(WalletModel *_model)
@ -87,9 +86,9 @@ void KevaDialog::setModel(WalletModel *_model)
tableView->setColumnWidth(KevaTableModel::Key, KEY_COLUMN_WIDTH); tableView->setColumnWidth(KevaTableModel::Key, KEY_COLUMN_WIDTH);
tableView->setColumnWidth(KevaTableModel::Block, BLOCK_MINIMUM_COLUMN_WIDTH); tableView->setColumnWidth(KevaTableModel::Block, BLOCK_MINIMUM_COLUMN_WIDTH);
connect(tableView->selectionModel(), connect(ui->kevaView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, this, SLOT(kevaView_selectionChanged()));
SLOT(recentRequestsView_selectionChanged(QItemSelection, QItemSelection)));
// Last 2 columns are set by the columnResizingFixer, when the table geometry is ready. // 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); 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)
dialog->show(); 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. // Enable Show/Remove buttons only if anything is selected.
bool enable = !ui->kevaView->selectionModel()->selectedRows().isEmpty(); bool enable = !ui->kevaView->selectionModel()->selectedRows().isEmpty();
ui->showRequestButton->setEnabled(enable); ui->showValueButton->setEnabled(enable);
ui->removeRequestButton->setEnabled(enable); ui->removeButton->setEnabled(enable);
} }
void KevaDialog::on_showRequestButton_clicked() void KevaDialog::on_showValueButton_clicked()
{ {
if(!model || !model->getKevaTableModel() || !ui->kevaView->selectionModel()) if(!model || !model->getKevaTableModel() || !ui->kevaView->selectionModel())
return; return;
@ -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()) if(!model || !model->getKevaTableModel() || !ui->kevaView->selectionModel())
return; return;
QModelIndexList selection = ui->kevaView->selectionModel()->selectedRows(); QModelIndexList selection = ui->kevaView->selectionModel()->selectedRows();
if(selection.empty()) if(selection.empty())
return; return;
// correct for selection mode ContiguousSelection
QModelIndex firstIndex = selection.at(0); QMessageBox::StandardButton reply;
model->getKevaTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent()); 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 // We override the virtual resizeEvent of the QWidget to adjust tables column
@ -300,3 +316,17 @@ void KevaDialog::copyAmount()
{ {
copyColumnToClipboard(KevaTableModel::Block); 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:
void setModel(WalletModel *model); void setModel(WalletModel *model);
void showNamespace(QString ns); void showNamespace(QString ns);
int createNamespace(std::string displayName, std::string& namespaceId);
public Q_SLOTS: public Q_SLOTS:
void clear(); void clear();
@ -68,10 +69,10 @@ private Q_SLOTS:
void on_showContent_clicked(); void on_showContent_clicked();
void on_createNamespace_clicked(); void on_createNamespace_clicked();
void on_listNamespaces_clicked(); void on_listNamespaces_clicked();
void on_showRequestButton_clicked(); void on_showValueButton_clicked();
void on_removeRequestButton_clicked(); void on_removeButton_clicked();
void on_kevaView_doubleClicked(const QModelIndex &index); void on_kevaView_doubleClicked(const QModelIndex &index);
void kevaView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void kevaView_selectionChanged();
void updateDisplayUnit(); void updateDisplayUnit();
void showMenu(const QPoint &point); void showMenu(const QPoint &point);
void copyURI(); void copyURI();

8
src/qt/kevanamespacemodel.cpp

@ -105,10 +105,14 @@ bool KevaNamespaceModel::removeRows(int row, int count, const QModelIndex &paren
Qt::ItemFlags KevaNamespaceModel::flags(const QModelIndex &index) const 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 // actually add to table in GUI
void KevaNamespaceModel::setNamespace(std::vector<NamespaceEntry> vNamespaceEntries) void KevaNamespaceModel::setNamespace(std::vector<NamespaceEntry> vNamespaceEntries)
{ {

3
src/qt/kevanamespacemodel.h

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

26
src/qt/kevanewnamespacedialog.cpp

@ -6,7 +6,9 @@
#include <qt/forms/ui_kevanewnamespacedialog.h> #include <qt/forms/ui_kevanewnamespacedialog.h>
#include <qt/kevatablemodel.h> #include <qt/kevatablemodel.h>
#include <qt/kevadialog.h>
#include <QPushButton>
#include <QModelIndex> #include <QModelIndex>
KevaNewNamespaceDialog::KevaNewNamespaceDialog(QWidget *parent) : KevaNewNamespaceDialog::KevaNewNamespaceDialog(QWidget *parent) :
@ -14,14 +16,36 @@ KevaNewNamespaceDialog::KevaNewNamespaceDialog(QWidget *parent) :
ui(new Ui::KevaNewNamespaceDialog) ui(new Ui::KevaNewNamespaceDialog)
{ {
ui->setupUi(this); 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() 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(); QDialog::accept();
} }
void KevaNewNamespaceDialog::reject()
{
}
KevaNewNamespaceDialog::~KevaNewNamespaceDialog() KevaNewNamespaceDialog::~KevaNewNamespaceDialog()
{ {
delete ui; delete ui;

2
src/qt/kevanewnamespacedialog.h

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

142
src/qt/walletmodel.cpp

@ -40,6 +40,8 @@
#include <QSet> #include <QSet>
#include <QTimer> #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) : WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) :
QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0), QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0),
@ -764,9 +766,27 @@ int WalletModel::getDefaultConfirmTarget() const
void WalletModel::getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::string nameSpace) 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); LOCK(cs_main);
valtype nameSpaceVal = ValtypeFromString(nameSpace);
valtype key; valtype key;
CKevaData data; CKevaData data;
std::unique_ptr<CKevaIterator> iter(pcoinsTip->IterateKeys(nameSpaceVal)); std::unique_ptr<CKevaIterator> iter(pcoinsTip->IterateKeys(nameSpaceVal));
@ -783,6 +803,7 @@ void WalletModel::getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::stri
} }
vKevaEntries.push_back(std::move(entry)); vKevaEntries.push_back(std::move(entry));
} }
} }
void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEntries) void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEntries)
@ -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(); std::map<std::string, std::string>::iterator it = mapObjects.begin();
while (it != mapObjects.end()) { while (it != mapObjects.end()) {
NamespaceEntry entry; NamespaceEntry entry;
@ -842,3 +880,105 @@ void WalletModel::getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEnt
it++; 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:
// Keva // Keva
void getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::string nameSpace); void getKevaEntries(std::vector<KevaEntry>& vKevaEntries, std::string nameSpace);
void getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEntries); void getNamespaceEntries(std::vector<NamespaceEntry>& vNamespaceEntries);
int createNamespace(std::string displayName, std::string& namespaceId);
int deleteKevaEntry(std::string nameSpace, std::string key);
private: private:
CWallet *wallet; CWallet *wallet;

Loading…
Cancel
Save