Aditya Kulkarni
6 years ago
12 changed files with 450 additions and 9 deletions
@ -0,0 +1,192 @@ |
|||
#include "addressbook.h" |
|||
#include "ui_addressbook.h" |
|||
#include "ui_mainwindow.h" |
|||
#include "settings.h" |
|||
#include "mainwindow.h" |
|||
#include "utils.h" |
|||
|
|||
AddressBookModel::AddressBookModel(QTableView *parent) |
|||
: QAbstractTableModel(parent) { |
|||
headers << "Label" << "Address"; |
|||
|
|||
this->parent = parent; |
|||
loadDataFromStorage(); |
|||
} |
|||
|
|||
AddressBookModel::~AddressBookModel() { |
|||
if (labels != nullptr) |
|||
saveDataToStorage(); |
|||
|
|||
delete labels; |
|||
} |
|||
|
|||
void AddressBookModel::saveDataToStorage() { |
|||
QFile file(writeableFile()); |
|||
file.open(QIODevice::ReadWrite | QIODevice::Truncate); |
|||
QDataStream out(&file); // we will serialize the data into the file
|
|||
out << QString("v1") << *labels; |
|||
file.close(); |
|||
|
|||
// Save column positions
|
|||
QSettings().setValue("addresstablegeometry", parent->horizontalHeader()->saveState()); |
|||
} |
|||
|
|||
|
|||
void AddressBookModel::loadDataFromStorage() { |
|||
QFile file(writeableFile()); |
|||
|
|||
delete labels; |
|||
labels = new QList<QPair<QString, QString>>(); |
|||
|
|||
file.open(QIODevice::ReadOnly); |
|||
QDataStream in(&file); // read the data serialized from the file
|
|||
QString version; |
|||
in >> version >> *labels; |
|||
|
|||
file.close(); |
|||
|
|||
parent->horizontalHeader()->restoreState(QSettings().value("addresstablegeometry").toByteArray()); |
|||
} |
|||
|
|||
void AddressBookModel::addNewLabel(QString label, QString addr) { |
|||
labels->push_back(QPair<QString, QString>(label, addr)); |
|||
|
|||
dataChanged(index(0, 0), index(labels->size()-1, columnCount(index(0,0))-1)); |
|||
layoutChanged(); |
|||
} |
|||
|
|||
void AddressBookModel::removeItemAt(int row) { |
|||
if (row >= labels->size()) |
|||
return; |
|||
labels->removeAt(row); |
|||
|
|||
dataChanged(index(0, 0), index(labels->size()-1, columnCount(index(0,0))-1)); |
|||
layoutChanged(); |
|||
} |
|||
|
|||
QPair<QString, QString> AddressBookModel::itemAt(int row) { |
|||
if (row >= labels->size()) return QPair<QString, QString>(); |
|||
|
|||
return labels->at(row); |
|||
} |
|||
|
|||
QString AddressBookModel::writeableFile() { |
|||
auto filename = QStringLiteral("addresslabels.dat"); |
|||
|
|||
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); |
|||
if (!dir.exists()) |
|||
QDir().mkpath(dir.absolutePath()); |
|||
|
|||
if (Settings::getInstance()->isTestnet()) { |
|||
return dir.filePath("testnet-" % filename); |
|||
} else { |
|||
return dir.filePath(filename); |
|||
} |
|||
} |
|||
|
|||
int AddressBookModel::rowCount(const QModelIndex&) const { |
|||
if (labels == nullptr) return 0; |
|||
return labels->size(); |
|||
} |
|||
|
|||
int AddressBookModel::columnCount(const QModelIndex&) const { |
|||
return headers.size(); |
|||
} |
|||
|
|||
|
|||
QVariant AddressBookModel::data(const QModelIndex &index, int role) const { |
|||
if (role == Qt::DisplayRole) { |
|||
switch(index.column()) { |
|||
case 0: return labels->at(index.row()).first; |
|||
case 1: return labels->at(index.row()).second; |
|||
} |
|||
} |
|||
return QVariant(); |
|||
} |
|||
|
|||
|
|||
QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const { |
|||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { |
|||
return headers.at(section); |
|||
} |
|||
|
|||
return QVariant(); |
|||
} |
|||
|
|||
void AddressBook::open(MainWindow* parent, QLineEdit* target) { |
|||
QDialog d(parent); |
|||
Ui_addressBook ab; |
|||
ab.setupUi(&d); |
|||
|
|||
AddressBookModel model(ab.addresses); |
|||
ab.addresses->setModel(&model); |
|||
|
|||
// If there is no target, the we'll call the button "Ok", else "Pick"
|
|||
if (target != nullptr) { |
|||
ab.buttonBox->button(QDialogButtonBox::Ok)->setText("Pick"); |
|||
} |
|||
|
|||
// If there is a target then make it the addr for the "Add to" button
|
|||
if (target != nullptr && Utils::isValidAddress(target->text())) { |
|||
ab.addr->setText(target->text()); |
|||
ab.label->setFocus(); |
|||
} |
|||
|
|||
// Add new address button
|
|||
QObject::connect(ab.addNew, &QPushButton::clicked, [&] () { |
|||
auto addr = ab.addr->text().trimmed(); |
|||
if (!addr.isEmpty() && !ab.label->text().isEmpty()) { |
|||
// Test if address is valid.
|
|||
if (!Utils::isValidAddress(addr)) { |
|||
QMessageBox::critical(parent, "Address Format Error", addr + " doesn't seem to be a valid Zcash address.", QMessageBox::Ok); |
|||
} else { |
|||
model.addNewLabel(ab.label->text(), ab.addr->text()); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// Double-Click picks the item
|
|||
QObject::connect(ab.addresses, &QTableView::doubleClicked, [&] (auto index) { |
|||
if (index.row() < 0) return; |
|||
|
|||
QString addr = model.itemAt(index.row()).second; |
|||
d.accept(); |
|||
target->setText(addr); |
|||
}); |
|||
|
|||
// Right-Click
|
|||
ab.addresses->setContextMenuPolicy(Qt::CustomContextMenu); |
|||
QObject::connect(ab.addresses, &QTableView::customContextMenuRequested, [&] (QPoint pos) { |
|||
QModelIndex index = ab.addresses->indexAt(pos); |
|||
|
|||
if (index.row() < 0) return; |
|||
|
|||
QString addr = model.itemAt(index.row()).second; |
|||
|
|||
QMenu menu(parent); |
|||
|
|||
if (target != nullptr) { |
|||
menu.addAction("Pick", [&] () { |
|||
target->setText(addr); |
|||
}); |
|||
} |
|||
|
|||
menu.addAction("Copy Address", [&] () { |
|||
QGuiApplication::clipboard()->setText(addr); |
|||
parent->ui->statusBar->showMessage("Copied to clipboard", 3 * 1000); |
|||
}); |
|||
|
|||
menu.addAction("Delete Label", [&] () { |
|||
model.removeItemAt(index.row()); |
|||
}); |
|||
|
|||
menu.exec(ab.addresses->viewport()->mapToGlobal(pos)); |
|||
}); |
|||
|
|||
if (d.exec() == QDialog::Accepted && target != nullptr) { |
|||
auto selection = ab.addresses->selectionModel(); |
|||
if (selection->hasSelection()) { |
|||
target->setText(model.itemAt(selection->selectedRows().at(0).row()).second); |
|||
} |
|||
}; |
|||
} |
@ -0,0 +1,39 @@ |
|||
#ifndef ADDRESSBOOK_H |
|||
#define ADDRESSBOOK_H |
|||
|
|||
#include "precompiled.h" |
|||
|
|||
class MainWindow; |
|||
|
|||
class AddressBookModel : public QAbstractTableModel { |
|||
|
|||
public: |
|||
AddressBookModel(QTableView* parent); |
|||
~AddressBookModel(); |
|||
|
|||
void addNewLabel(QString label, QString addr); |
|||
void removeItemAt(int row); |
|||
QPair<QString, QString> itemAt(int row); |
|||
|
|||
int rowCount(const QModelIndex &parent) const; |
|||
int columnCount(const QModelIndex &parent) const; |
|||
QVariant data(const QModelIndex &index, int role) const; |
|||
QVariant headerData(int section, Qt::Orientation orientation, int role) const; |
|||
|
|||
private: |
|||
void loadDataFromStorage(); |
|||
void saveDataToStorage(); |
|||
|
|||
QString writeableFile(); |
|||
|
|||
QTableView* parent; |
|||
QList<QPair<QString, QString>>* labels = nullptr; |
|||
QStringList headers; |
|||
}; |
|||
|
|||
class AddressBook { |
|||
public: |
|||
static void open(MainWindow* parent, QLineEdit* target = nullptr); |
|||
}; |
|||
|
|||
#endif // ADDRESSBOOK_H
|
@ -0,0 +1,133 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ui version="4.0"> |
|||
<class>addressBook</class> |
|||
<widget class="QDialog" name="addressBook"> |
|||
<property name="geometry"> |
|||
<rect> |
|||
<x>0</x> |
|||
<y>0</y> |
|||
<width>690</width> |
|||
<height>562</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>Address Book</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout"> |
|||
<item> |
|||
<widget class="QGroupBox" name="groupBox"> |
|||
<property name="title"> |
|||
<string>Add New Address</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout_2"> |
|||
<item> |
|||
<widget class="QLabel" name="label_1"> |
|||
<property name="text"> |
|||
<string>Address (z-Addr or t-Addr)</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QLineEdit" name="addr"/> |
|||
</item> |
|||
<item> |
|||
<widget class="QLabel" name="label_2"> |
|||
<property name="text"> |
|||
<string>Label</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QLineEdit" name="label"/> |
|||
</item> |
|||
<item> |
|||
<layout class="QHBoxLayout" name="horizontalLayout"> |
|||
<item> |
|||
<spacer name="horizontalSpacer"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Horizontal</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>40</width> |
|||
<height>20</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
<item> |
|||
<widget class="QPushButton" name="addNew"> |
|||
<property name="text"> |
|||
<string>Add to Address Book</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QTableView" name="addresses"> |
|||
<property name="selectionMode"> |
|||
<enum>QAbstractItemView::SingleSelection</enum> |
|||
</property> |
|||
<property name="selectionBehavior"> |
|||
<enum>QAbstractItemView::SelectRows</enum> |
|||
</property> |
|||
<attribute name="horizontalHeaderStretchLastSection"> |
|||
<bool>true</bool> |
|||
</attribute> |
|||
<attribute name="verticalHeaderVisible"> |
|||
<bool>false</bool> |
|||
</attribute> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QDialogButtonBox" name="buttonBox"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Horizontal</enum> |
|||
</property> |
|||
<property name="standardButtons"> |
|||
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
<resources/> |
|||
<connections> |
|||
<connection> |
|||
<sender>buttonBox</sender> |
|||
<signal>accepted()</signal> |
|||
<receiver>addressBook</receiver> |
|||
<slot>accept()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>248</x> |
|||
<y>254</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>157</x> |
|||
<y>274</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
<connection> |
|||
<sender>buttonBox</sender> |
|||
<signal>rejected()</signal> |
|||
<receiver>addressBook</receiver> |
|||
<slot>reject()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>316</x> |
|||
<y>260</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>286</x> |
|||
<y>274</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
</connections> |
|||
</ui> |
Loading…
Reference in new issue