Fabcoin Core  0.16.2
P2P Digital Currency
tokentransactionview.cpp
Go to the documentation of this file.
1 #include <tokentransactionview.h>
2 
3 #include <walletmodel.h>
4 #include <platformstyle.h>
7 #include <tokenfilterproxy.h>
8 #include <guiutil.h>
9 #include <optionsmodel.h>
10 #include <tokenitemmodel.h>
11 #include <tokendescdialog.h>
12 #include <styleSheet.h>
13 
14 #include <QComboBox>
15 #include <QDateTimeEdit>
16 #include <QDoubleValidator>
17 #include <QHBoxLayout>
18 #include <QHeaderView>
19 #include <QLabel>
20 #include <QLineEdit>
21 #include <QMenu>
22 #include <QPoint>
23 #include <QScrollBar>
24 #include <QTableView>
25 #include <QVBoxLayout>
26 #include <QRegularExpressionValidator>
27 
28 #define paternTokenAmount "^[0-9]{1,59}\\.{1,1}[0-9]{0,18}"
29 
31  QWidget(parent),
32  model(0),
33  tokenProxyModel(0),
34  tokenView(0),
35  columnResizingFixer(0)
36 {
37  // Build filter row
38  setContentsMargins(0,0,0,0);
39 
40  QHBoxLayout *hlayout = new QHBoxLayout();
41  hlayout->setContentsMargins(6,6,6,6);
42  hlayout->setSpacing(10);
43  hlayout->addSpacing(STATUS_COLUMN_WIDTH);
44 
45  dateWidget = new QComboBox(this);
46  dateWidget->setFixedWidth(DATE_COLUMN_WIDTH -10);
47 
48  dateWidget->addItem(tr("All"), All);
49  dateWidget->addItem(tr("Today"), Today);
50  dateWidget->addItem(tr("This week"), ThisWeek);
51  dateWidget->addItem(tr("This month"), ThisMonth);
52  dateWidget->addItem(tr("Last month"), LastMonth);
53  dateWidget->addItem(tr("This year"), ThisYear);
54  dateWidget->addItem(tr("Range..."), Range);
55  hlayout->addWidget(dateWidget);
56 
57  typeWidget = new QComboBox(this);
58  typeWidget->setFixedWidth(TYPE_COLUMN_WIDTH -10);
59 
60  typeWidget->addItem(tr("All"), TokenFilterProxy::ALL_TYPES);
64  hlayout->addWidget(typeWidget);
65 
66  addressWidget = new QLineEdit(this);
67 #if QT_VERSION >= 0x040700
68  addressWidget->setPlaceholderText(tr("Enter address to search"));
69 #endif
70  hlayout->addWidget(addressWidget);
71 
72  nameWidget = new QComboBox(this);
73  nameWidget->setFixedWidth(NAME_COLUMN_WIDTH -10);
74  nameWidget->addItem(tr("All"), "");
75 
76  hlayout->addWidget(nameWidget);
77 
78  amountWidget = new QLineEdit(this);
79 #if QT_VERSION >= 0x040700
80  amountWidget->setPlaceholderText(tr("Min amount"));
81 #endif
82  amountWidget->setFixedWidth(AMOUNT_COLUMN_WIDTH - 10);
83 
84  QRegularExpression regEx;
85  regEx.setPattern(paternTokenAmount);
86  QRegularExpressionValidator *validator = new QRegularExpressionValidator(amountWidget);
87  validator->setRegularExpression(regEx);
88  amountWidget->setValidator(validator);
89  hlayout->addWidget(amountWidget);
90 
91  QVBoxLayout *vlayout = new QVBoxLayout(this);
92  vlayout->setContentsMargins(0,0,0,0);
93  vlayout->setSpacing(0);
94 
95  QTableView *view = new QTableView(this);
96  vlayout->addLayout(hlayout);
97  vlayout->addWidget(createDateRangeWidget());
98  vlayout->addWidget(view);
99  vlayout->setSpacing(0);
100  int width = view->verticalScrollBar()->sizeHint().width();
101  // Cover scroll bar width with spacing
102  if (platformStyle->getUseExtraSpacing()) {
103  hlayout->addSpacing(width+2);
104  } else {
105  hlayout->addSpacing(width);
106  }
107  // Always show scroll bar
108  view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
109  view->setTabKeyNavigation(false);
110  view->setContextMenuPolicy(Qt::CustomContextMenu);
111 
112  view->installEventFilter(this);
113  tokenView = view;
114 
115  // Actions
116  QAction *copyAddressAction = new QAction(tr("Copy address"), this);
117  QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
118  QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this);
119  QAction *copyTxPlainText = new QAction(tr("Copy full transaction details"), this);
120  QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
121 
122  contextMenu = new QMenu(tokenView);
123  contextMenu->addAction(copyAddressAction);
124  contextMenu->addAction(copyAmountAction);
125  contextMenu->addAction(copyTxIDAction);
126  contextMenu->addAction(copyTxPlainText);
127  contextMenu->addAction(showDetailsAction);
128 
129  connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
130  connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
131  connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
132  connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString)));
133  connect(nameWidget, SIGNAL(activated(int)), this, SLOT(chooseName(int)));
134 
135  connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
136 
137  connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
138  connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
139  connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID()));
140  connect(copyTxPlainText, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
141  connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
142  connect(tokenView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(showDetails()));
143 }
144 
146 {
147  this->model = _model;
148  if(_model)
149  {
151  connect(model->getTokenItemModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),this, SLOT(addToNameWidget(QModelIndex,int,int)));
152  connect(model->getTokenItemModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),this, SLOT(removeFromNameWidget(QModelIndex,int,int)));
153 
154  tokenProxyModel = new TokenFilterProxy(this);
155  tokenProxyModel->setSourceModel(_model->getTokenTransactionTableModel());
156  tokenProxyModel->setDynamicSortFilter(true);
157  tokenProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
158  tokenProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
159 
160  tokenProxyModel->setSortRole(Qt::EditRole);
161 
162  tokenView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
163  tokenView->setModel(tokenProxyModel);
164  tokenView->setAlternatingRowColors(true);
165  tokenView->setSelectionBehavior(QAbstractItemView::SelectRows);
166  tokenView->setSelectionMode(QAbstractItemView::ExtendedSelection);
167  tokenView->setSortingEnabled(true);
168  tokenView->sortByColumn(TokenTransactionTableModel::Date, Qt::DescendingOrder);
169  tokenView->verticalHeader()->hide();
170 
176 
178  }
179 }
180 
182 {
183  dateRangeWidget = new QFrame();
184  dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
185  dateRangeWidget->setContentsMargins(1,1,1,8);
186  QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
187  layout->setContentsMargins(0,0,0,0);
188  layout->addSpacing(23);
189  layout->addWidget(new QLabel(tr("Range:")));
190 
191  dateFrom = new QDateTimeEdit(this);
192  dateFrom->setDisplayFormat("dd/MM/yy");
193  dateFrom->setCalendarPopup(true);
194  dateFrom->setMinimumWidth(100);
195  dateFrom->setDate(QDate::currentDate().addDays(-7));
196  layout->addWidget(dateFrom);
197  layout->addWidget(new QLabel(tr("to")));
198 
199  dateTo = new QDateTimeEdit(this);
200  dateTo->setDisplayFormat("dd/MM/yy");
201  dateTo->setCalendarPopup(true);
202  dateTo->setMinimumWidth(100);
203  dateTo->setDate(QDate::currentDate());
204  layout->addWidget(dateTo);
205  layout->addStretch();
206 
207  // Hide by default
208  dateRangeWidget->setVisible(false);
209 
210  // Notify on change
211  connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
212  connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
213 
214  return dateRangeWidget;
215 }
216 
218 {
219  if(model)
220  {
222  for(int i = 0; i < tim->rowCount(); i++)
223  {
224  QString name = tim->data(tim->index(i, 0), TokenItemModel::SymbolRole).toString();
225  if(nameWidget->findText(name) == -1)
226  nameWidget->addItem(name, name);
227  }
228  }
229 }
230 
231 void TokenTransactionView::addToNameWidget(const QModelIndex &parent, int start, int /*end*/)
232 {
233  if(model)
234  {
236  QString name = tim->index(start, TokenItemModel::Symbol, parent).data().toString();
237  if(nameWidget->findText(name) == -1)
238  nameWidget->addItem(name, name);
239  }
240 }
241 
242 void TokenTransactionView::removeFromNameWidget(const QModelIndex &parent, int start, int /*end*/)
243 {
244  if(model)
245  {
247  QString name = tim->index(start, TokenItemModel::Symbol, parent).data().toString();
248  int nameCount = 0;
249 
250  for(int i = 0; i < tim->rowCount(); i++)
251  {
252  QString checkName = tim->index(i, TokenItemModel::Symbol, parent).data().toString();
253  if(name == checkName)
254  {
255  nameCount++;
256  }
257  }
258 
259  int nameIndex = nameWidget->findText(name);
260  if(nameCount == 1 && nameIndex != -1)
261  nameWidget->removeItem(nameIndex);
262  }
263 }
264 
265 void TokenTransactionView::resizeEvent(QResizeEvent *event)
266 {
267  QWidget::resizeEvent(event);
269 }
270 
271 bool TokenTransactionView::eventFilter(QObject *obj, QEvent *event)
272 {
273  if (event->type() == QEvent::KeyPress)
274  {
275  QKeyEvent *ke = static_cast<QKeyEvent *>(event);
276  if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
277  {
279  return true;
280  }
281  }
282  return QWidget::eventFilter(obj, event);
283 }
284 
285 void TokenTransactionView::contextualMenu(const QPoint &point)
286 {
287  QModelIndex index = tokenView->indexAt(point);
288  QModelIndexList selection = tokenView->selectionModel()->selectedRows(0);
289  if (selection.empty())
290  return;
291 
292  if(index.isValid())
293  {
294  contextMenu->exec(QCursor::pos());
295  }
296 }
297 
299 {
300  if(!tokenProxyModel)
301  return;
303  QDateTime(dateFrom->date()),
304  QDateTime(dateTo->date()).addDays(1));
305 }
306 
308 {
309  if(!tokenView->selectionModel())
310  return;
311  QModelIndexList selection = tokenView->selectionModel()->selectedRows();
312  if(!selection.isEmpty())
313  {
314  TokenDescDialog *dlg = new TokenDescDialog(selection.at(0));
315  dlg->setAttribute(Qt::WA_DeleteOnClose);
316  dlg->show();
317  }
318 }
319 
321 {
323 }
324 
326 {
328 }
329 
331 {
333 }
334 
336 {
338 }
339 
341 {
342  if(!tokenProxyModel)
343  return;
344  QDate current = QDate::currentDate();
345  dateRangeWidget->setVisible(false);
346  switch(dateWidget->itemData(idx).toInt())
347  {
348  case All:
352  break;
353  case Today:
355  QDateTime(current),
357  break;
358  case ThisWeek: {
359  // Find last Monday
360  QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
362  QDateTime(startOfWeek),
364 
365  } break;
366  case ThisMonth:
368  QDateTime(QDate(current.year(), current.month(), 1)),
370  break;
371  case LastMonth:
373  QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)),
374  QDateTime(QDate(current.year(), current.month(), 1)));
375  break;
376  case ThisYear:
378  QDateTime(QDate(current.year(), 1, 1)),
380  break;
381  case Range:
382  dateRangeWidget->setVisible(true);
384  break;
385  }
386 }
387 
389 {
390  if(!tokenProxyModel)
391  return;
393  typeWidget->itemData(idx).toInt());
394 }
395 
397 {
398  if(!tokenProxyModel)
399  return;
401  nameWidget->itemData(idx).toString());
402 }
403 
405 {
406  if(!tokenProxyModel)
407  return;
409 }
410 
411 void TokenTransactionView::changedAmount(const QString &amount)
412 {
413  if(!tokenProxyModel)
414  return;
415  int256_t amount_parsed = 0;
416  if(FabcoinUnits::parseToken(18, amount, &amount_parsed))
417  {
418  tokenProxyModel->setMinAmount(amount_parsed);
419  }
420  else
421  {
423  }
424 }
void setModel(WalletModel *model)
static quint32 TYPE(int type)
void setTypeFilter(quint32 modes)
int rowCount(const QModelIndex &parent=QModelIndex()) const
const char * prefix
Definition: rest.cpp:623
void changedAmount(const QString &amount)
void setName(const QString _name)
void contextualMenu(const QPoint &)
void setDateRange(const QDateTime &from, const QDateTime &to)
void setAddressPrefix(const QString &addrPrefix)
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
Definition: CommonData.cpp:141
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
TokenTransactionTableModel * getTokenTransactionTableModel()
static const QDateTime MIN_DATE
Earliest date that can be represented (far in the past)
Dialog showing token details.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
static const QDateTime MAX_DATE
Last date that can be represented (far in the future)
const char * name
Definition: rest.cpp:36
static const quint32 ALL_TYPES
Type filter bit field (all types)
TokenTransactionRecord * index(int idx)
TokenTransactionView(const PlatformStyle *platformStyle, QWidget *parent=0)
TokenItemModel * getTokenItemModel()
Makes a QTableView last column feel as if it was being resized from its left border.
Definition: guiutil.h:158
GUIUtil::TableViewLastColumnResizingFixer * columnResizingFixer
void setMinAmount(const int256_t &minimum)
TokenTransactionTableModel * parent
bool eventFilter(QObject *obj, QEvent *event)
void addToNameWidget(const QModelIndex &parent, int start, int)
virtual void resizeEvent(QResizeEvent *event)
#define paternTokenAmount
Interface to Fabcoin wallet from Qt view code.
Definition: walletmodel.h:103
static bool parseToken(int decimal_units, const QString &value, int256_t *val_out)
Parse string to token amount.
void removeFromNameWidget(const QModelIndex &parent, int start, int)
bool getUseExtraSpacing() const
Definition: platformstyle.h:22
void copyEntryData(QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
Definition: guiutil.cpp:277
void changedPrefix(const QString &prefix)
TokenFilterProxy * tokenProxyModel