diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index f5812d5a9..81181b98d 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -138,6 +138,7 @@ QT_FORMS_UI = \ qt/forms/kevadialog.ui \ qt/forms/kevadetaildialog.ui \ qt/forms/kevaaddkeydialog.ui \ + qt/forms/kevabookmarksdialog.ui \ qt/forms/kevanewnamespacedialog.ui \ qt/forms/kevamynamespacesdialog.ui \ qt/forms/debugwindow.ui \ @@ -180,8 +181,10 @@ QT_MOC_CPP = \ qt/moc_recentrequeststablemodel.cpp \ qt/moc_kevatablemodel.cpp \ qt/moc_kevanamespacemodel.cpp \ + qt/moc_kevabookmarksmodel.cpp \ qt/moc_kevadetaildialog.cpp \ qt/moc_kevaaddkeydialog.cpp \ + qt/moc_kevabookmarksdialog.cpp \ qt/moc_kevanewnamespacedialog.cpp \ qt/moc_kevamynamespacesdialog.cpp \ qt/moc_rpcconsole.cpp \ @@ -273,8 +276,10 @@ BITCOIN_QT_H = \ qt/kevadialog.h \ qt/kevatablemodel.h \ qt/kevanamespacemodel.h \ + qt/kevabookmarksmodel.h \ qt/kevadetaildialog.h \ qt/kevaaddkeydialog.h \ + qt/kevabookmarksdialog.h \ qt/kevanewnamespacedialog.h \ qt/kevamynamespacesdialog.h \ qt/utilitydialog.h \ @@ -395,8 +400,10 @@ BITCOIN_QT_WALLET_CPP = \ qt/kevadialog.cpp \ qt/kevatablemodel.cpp \ qt/kevanamespacemodel.cpp \ + qt/kevabookmarksmodel.cpp \ qt/kevadetaildialog.cpp \ qt/kevaaddkeydialog.cpp \ + qt/kevabookmarksdialog.cpp \ qt/kevanewnamespacedialog.cpp \ qt/kevamynamespacesdialog.cpp \ qt/walletframe.cpp \ diff --git a/src/qt/forms/kevabookmarksdialog.ui b/src/qt/forms/kevabookmarksdialog.ui new file mode 100644 index 000000000..f1b1124a4 --- /dev/null +++ b/src/qt/forms/kevabookmarksdialog.ui @@ -0,0 +1,43 @@ + + + KevaBookmarksDialog + + + + 0 + 0 + 800 + 400 + + + + Namespace Bookmarks + + + + + + Qt::CustomContextMenu + + + false + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel + + + + + + + diff --git a/src/qt/forms/kevadialog.ui b/src/qt/forms/kevadialog.ui index 407e70866..5fcedba24 100644 --- a/src/qt/forms/kevadialog.ui +++ b/src/qt/forms/kevadialog.ui @@ -124,7 +124,7 @@ - + 0 diff --git a/src/qt/kevabookmarksdialog.cpp b/src/qt/kevabookmarksdialog.cpp new file mode 100644 index 000000000..0cc46892a --- /dev/null +++ b/src/qt/kevabookmarksdialog.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2011-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include + +#include +#include + +#include +#include + +KevaBookmarksDialog::KevaBookmarksDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::KevaBookmarksDialog) +{ + ui->setupUi(this); + ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); + ui->buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Show")); + connect(ui->buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject())); + connect(ui->buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); +} + +void KevaBookmarksDialog::setModel(WalletModel *_model) +{ + this->model = _model; + + if(_model && _model->getOptionsModel()) + { + _model->getKevaBookmarksModel()->sort(KevaBookmarksModel::Name, Qt::DescendingOrder); + QTableView* tableView = ui->namespaceView; + + tableView->verticalHeader()->hide(); + tableView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + tableView->setModel(_model->getKevaBookmarksModel()); + tableView->setAlternatingRowColors(true); + tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + tableView->setSelectionMode(QAbstractItemView::ContiguousSelection); + tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + connect(tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(namespaceView_selectionChanged())); + } +} + + +void KevaBookmarksDialog::namespaceView_selectionChanged() +{ + bool enable = !ui->namespaceView->selectionModel()->selectedRows().isEmpty(); + ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(enable); + + if (enable) { + selectedIndex = ui->namespaceView->selectionModel()->currentIndex(); + } else { + QModelIndex empty; + selectedIndex = empty; + } +} + +void KevaBookmarksDialog::apply() +{ + QModelIndex idIdx = selectedIndex.sibling(selectedIndex.row(), KevaBookmarksModel::Id); + QString idStr = idIdx.data(Qt::DisplayRole).toString(); + KevaDialog* dialog = (KevaDialog*)this->parentWidget(); + dialog->showNamespace(idStr); + QDialog::close(); +} + +void KevaBookmarksDialog::reject() +{ + QDialog::reject(); +} + +KevaBookmarksDialog::~KevaBookmarksDialog() +{ + delete ui; +} \ No newline at end of file diff --git a/src/qt/kevabookmarksdialog.h b/src/qt/kevabookmarksdialog.h new file mode 100644 index 000000000..cd96d71f1 --- /dev/null +++ b/src/qt/kevabookmarksdialog.h @@ -0,0 +1,51 @@ +// Copyright (c) 2011-2014 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_KEVABOOKMARKSDIALOG_H +#define BITCOIN_QT_KEVABOOKMARKSDIALOG_H + +#include +#include + +#include +#include +#include + +class WalletModel; + +namespace Ui { + class KevaBookmarksDialog; +} + + +/** Dialog showing namepsace creation. */ +class KevaBookmarksDialog : public QDialog +{ + Q_OBJECT + + enum ColumnWidths { + ID_COLUMN_WIDTH = 260, + NAME_COLUMN_WIDTH = 260, + MINIMUM_COLUMN_WIDTH = 260 + }; + +public: + explicit KevaBookmarksDialog(QWidget *parent = 0); + ~KevaBookmarksDialog(); + void setModel(WalletModel *_model); + +public Q_SLOTS: + void apply(); + void reject(); + +private Q_SLOTS: + void namespaceView_selectionChanged(); + +private: + Ui::KevaBookmarksDialog *ui; + WalletModel *model; + QModelIndex selectedIndex; +}; + +#endif // BITCOIN_QT_KEVABOOKMARKSDIALOG_H diff --git a/src/qt/kevabookmarksmodel.cpp b/src/qt/kevabookmarksmodel.cpp new file mode 100644 index 000000000..209322187 --- /dev/null +++ b/src/qt/kevabookmarksmodel.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2011-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +#include +#include + + +KevaBookmarksModel::KevaBookmarksModel(CWallet *wallet, WalletModel *parent) : + QAbstractTableModel(parent), walletModel(parent) +{ + Q_UNUSED(wallet) + + /* These columns must match the indices in the ColumnIndex enumeration */ + columns << tr("Id") << tr("Name"); +} + +KevaBookmarksModel::~KevaBookmarksModel() +{ + /* Intentionally left empty */ +} + +int KevaBookmarksModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return list.length(); +} + +int KevaBookmarksModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return columns.length(); +} + +QVariant KevaBookmarksModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid() || index.row() >= list.length()) + return QVariant(); + + if (role == Qt::TextColorRole) + { + return QVariant(); + } + else if(role == Qt::DisplayRole || role == Qt::EditRole) + { + const BookmarkEntry *rec = &list[index.row()]; + switch(index.column()) + { + case Id: + return QString::fromStdString(rec->id); + case Name: + return QString::fromStdString(rec->name); + } + } + else if (role == Qt::TextAlignmentRole) + { + return (int)(Qt::AlignLeft|Qt::AlignVCenter); + } + return QVariant(); +} + +bool KevaBookmarksModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + return true; +} + +QVariant KevaBookmarksModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal) + { + if(role == Qt::DisplayRole && section < columns.size()) + { + return columns[section]; + } + } + return QVariant(); +} + + +QModelIndex KevaBookmarksModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + + return createIndex(row, column); +} + +bool KevaBookmarksModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Q_UNUSED(parent); + + if(count > 0 && row >= 0 && (row+count) <= list.size()) + { + beginRemoveRows(parent, row, row + count - 1); + list.erase(list.begin() + row, list.begin() + row + count); + endRemoveRows(); + return true; + } else { + return false; + } +} + +Qt::ItemFlags KevaBookmarksModel::flags(const QModelIndex &index) const +{ + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +// actually add to table in GUI +void KevaBookmarksModel::setBookmarks(std::vector vBookmarEntries) +{ + // Remove the old ones. + removeRows(0, list.size()); + list.clear(); + + for (auto it = vBookmarEntries.begin(); it != vBookmarEntries.end(); it++) { + beginInsertRows(QModelIndex(), 0, 0); + list.prepend(*it); + endInsertRows(); + } +} + +void KevaBookmarksModel::sort(int column, Qt::SortOrder order) +{ + qSort(list.begin(), list.end(), BookmarkEntryLessThan(column, order)); + Q_EMIT dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex())); +} + + +bool BookmarkEntryLessThan::operator()(BookmarkEntry &left, BookmarkEntry &right) const +{ + BookmarkEntry *pLeft = &left; + BookmarkEntry *pRight = &right; + if (order == Qt::DescendingOrder) + std::swap(pLeft, pRight); + + switch(column) + { + case KevaBookmarksModel::Id: + return pLeft->id < pRight->id; + case KevaBookmarksModel::Name: + return pLeft->name < pRight->name; + default: + return pLeft->id < pRight->id; + } +} diff --git a/src/qt/kevabookmarksmodel.h b/src/qt/kevabookmarksmodel.h new file mode 100644 index 000000000..78210ae28 --- /dev/null +++ b/src/qt/kevabookmarksmodel.h @@ -0,0 +1,79 @@ +// Copyright (c) 2011-2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_QT_KEVABOOKMARKSMODEL_H +#define BITCOIN_QT_KEVABOOKMARKSMODEL_H + +#include + +#include +#include +#include + +class CWallet; + +class BookmarkEntry +{ +public: + BookmarkEntry() { } + + std::string id; + std::string name; +}; + +class BookmarkEntryLessThan +{ +public: + BookmarkEntryLessThan(int nColumn, Qt::SortOrder fOrder): + column(nColumn), order(fOrder) {} + bool operator()(BookmarkEntry &left, BookmarkEntry &right) const; + +private: + int column; + Qt::SortOrder order; +}; + +/** Model for list of recently generated payment requests / bitcoin: URIs. + * Part of wallet model. + */ +class KevaBookmarksModel: public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit KevaBookmarksModel(CWallet *wallet, WalletModel *parent); + ~KevaBookmarksModel(); + + enum ColumnIndex { + Id = 0, + Name = 1, + NUMBER_OF_COLUMNS + }; + + /** @name Methods overridden from QAbstractTableModel + @{*/ + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, int role); + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); + Qt::ItemFlags flags(const QModelIndex &index) const; + /*@}*/ + + const BookmarkEntry &entry(int row) const { return list[row]; } + void setBookmarks(std::vector vBookmarkEntries); + +public Q_SLOTS: + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + +private: + WalletModel *walletModel; + QStringList columns; + QList list; + int64_t nReceiveRequestsMaxId; +}; + +#endif // BITCOIN_QT_KEVABOOKMARKSMODEL_H diff --git a/src/qt/kevadialog.cpp b/src/qt/kevadialog.cpp index 415d0b181..a3eac8329 100644 --- a/src/qt/kevadialog.cpp +++ b/src/qt/kevadialog.cpp @@ -13,11 +13,12 @@ #include #include #include -#include #include #include +#include #include #include +#include #include #include #include @@ -38,11 +39,11 @@ KevaDialog::KevaDialog(const PlatformStyle *_platformStyle, QWidget *parent) : ui->setupUi(this); if (!_platformStyle->getImagesOnButtons()) { - ui->receiveButton->setIcon(QIcon()); + ui->bookmarksButton->setIcon(QIcon()); ui->showValueButton->setIcon(QIcon()); ui->removeButton->setIcon(QIcon()); } else { - ui->receiveButton->setIcon(_platformStyle->SingleColorIcon(":/icons/address-book")); + ui->bookmarksButton->setIcon(_platformStyle->SingleColorIcon(":/icons/address-book")); ui->showValueButton->setIcon(_platformStyle->SingleColorIcon(":/icons/edit")); ui->removeButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove")); ui->addKVButton->setIcon(_platformStyle->SingleColorIcon(":/icons/add")); @@ -171,6 +172,23 @@ void KevaDialog::on_listNamespaces_clicked() dialog->show(); } +void KevaDialog::on_bookmarksButton_clicked() +{ + if(!model || !model->getKevaTableModel()) + return; + + KevaBookmarksDialog *dialog = new KevaBookmarksDialog(this); + + std::vector vBookmarkEntries; + model->getKevaBookmarkEntries(vBookmarkEntries); + model->getKevaBookmarksModel()->setBookmarks(std::move(vBookmarkEntries)); + model->getKevaBookmarksModel()->sort(KevaBookmarksModel::Name, Qt::DescendingOrder); + + dialog->setModel(model); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); +} + void KevaDialog::on_showContent_clicked() { if(!model || !model->getKevaTableModel()) diff --git a/src/qt/kevadialog.h b/src/qt/kevadialog.h index 070686aa3..9f15b2961 100644 --- a/src/qt/kevadialog.h +++ b/src/qt/kevadialog.h @@ -75,6 +75,7 @@ private Q_SLOTS: void on_addKVButton_clicked(); void on_kevaView_doubleClicked(const QModelIndex &index); void kevaView_selectionChanged(); + void on_bookmarksButton_clicked(); void updateDisplayUnit(); void showMenu(const QPoint &point); void copyURI(); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e5cb2cef3..b97d38842 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, O recentRequestsTableModel(0), kevaTableModel(0), kevaNamespaceModel(0), + kevaBookmarksModel(0), cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), cachedEncryptionStatus(Unencrypted), cachedNumBlocks(0) @@ -61,6 +63,7 @@ WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, O recentRequestsTableModel = new RecentRequestsTableModel(wallet, this); kevaTableModel = new KevaTableModel(wallet, this); kevaNamespaceModel = new KevaNamespaceModel(wallet, this); + kevaBookmarksModel = new KevaBookmarksModel(wallet, this); // This timer will be fired repeatedly to update the balance pollTimer = new QTimer(this); @@ -413,6 +416,11 @@ KevaNamespaceModel *WalletModel::getKevaNamespaceModel() return kevaNamespaceModel; } +KevaBookmarksModel *WalletModel::getKevaBookmarksModel() +{ + return kevaBookmarksModel; +} + WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const { if(!wallet->IsCrypted()) @@ -881,6 +889,14 @@ void WalletModel::getNamespaceEntries(std::vector& vNamespaceEnt } } +void WalletModel::getKevaBookmarkEntries(std::vector& vBookmarkEntries) +{ + BookmarkEntry entry; + entry.id = "NgKBKkBAJMtzsuit85TpTpo5Xj6UQUg1wr"; + entry.name = "Kevacoin Official Blog"; + vBookmarkEntries.push_back(std::move(entry)); +} + int WalletModel::createNamespace(std::string displayNameStr, std::string& namespaceId) { diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index e0f4030f0..0ae31b825 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -23,8 +23,10 @@ class PlatformStyle; class RecentRequestsTableModel; class KevaTableModel; class KevaNamespaceModel; +class KevaBookmarksModel; class KevaEntry; class NamespaceEntry; +class BookmarkEntry; class TransactionTableModel; class WalletModelTransaction; @@ -142,6 +144,7 @@ public: RecentRequestsTableModel *getRecentRequestsTableModel(); KevaTableModel *getKevaTableModel(); KevaNamespaceModel *getKevaNamespaceModel(); + KevaBookmarksModel *getKevaBookmarksModel(); CAmount getBalance(const CCoinControl *coinControl = nullptr) const; CAmount getUnconfirmedBalance() const; @@ -235,6 +238,7 @@ public: // Keva void getKevaEntries(std::vector& vKevaEntries, std::string nameSpace); void getNamespaceEntries(std::vector& vNamespaceEntries); + void getKevaBookmarkEntries(std::vector& vBookmarkEntries); int createNamespace(std::string displayName, std::string& namespaceId); int deleteKevaEntry(std::string nameSpace, std::string key); @@ -252,6 +256,7 @@ private: RecentRequestsTableModel *recentRequestsTableModel; KevaTableModel *kevaTableModel; KevaNamespaceModel *kevaNamespaceModel; + KevaBookmarksModel *kevaBookmarksModel; // Cache some values to be able to detect changes CAmount cachedBalance;