mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-03-13 06:01:45 +00:00
WIP: create namespace, delete key.
This commit is contained in:
parent
16bab4654a
commit
0c71cd4835
@ -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 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeRequestButton">
|
||||
<widget class="QPushButton" name="removeButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -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"/>
|
||||
|
@ -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) :
|
||||
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)
|
||||
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)
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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:
|
||||
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();
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -16,10 +16,11 @@ class CWallet;
|
||||
class NamespaceEntry
|
||||
{
|
||||
public:
|
||||
NamespaceEntry() { }
|
||||
NamespaceEntry():confirmed(true) { }
|
||||
|
||||
std::string id;
|
||||
std::string name;
|
||||
bool confirmed;
|
||||
};
|
||||
|
||||
class NamespaceEntryLessThan
|
||||
|
@ -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) :
|
||||
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;
|
||||
|
@ -26,6 +26,8 @@ public:
|
||||
|
||||
public Q_SLOTS:
|
||||
void accept();
|
||||
void reject();
|
||||
void onNamespaceChanged(const QString & ns);
|
||||
|
||||
private:
|
||||
Ui::KevaNewNamespaceDialog *ui;
|
||||
|
@ -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
|
||||
|
||||
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
|
||||
}
|
||||
vKevaEntries.push_back(std::move(entry));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
while (it != mapObjects.end()) {
|
||||
NamespaceEntry entry;
|
||||
@ -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;
|
||||
}
|
@ -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…
x
Reference in New Issue
Block a user