1 #include <qt/superstakerpage.h>
2 #include <qt/forms/ui_superstakerpage.h>
3 #include <qt/superstakeritemmodel.h>
4 #include <qt/walletmodel.h>
5 #include <qt/platformstyle.h>
6 #include <qt/styleSheet.h>
7 #include <qt/superstakerlistwidget.h>
8 #include <qt/guiutil.h>
9 #include <qt/editsuperstakerdialog.h>
10
11 #include <QPainter>
12 #include <QAbstractItemDelegate>
13 #include <QStandardItem>
14 #include <QStandardItemModel>
15 #include <QSortFilterProxyModel>
16 #include <QSizePolicy>
17 #include <QMenu>
18 #include <QMessageBox>
19
SuperStakerPage(const PlatformStyle * platformStyle,QWidget * parent)20 SuperStakerPage::SuperStakerPage(const PlatformStyle *platformStyle, QWidget *parent) :
21 QWidget(parent),
22 ui(new Ui::SuperStakerPage),
23 m_model(0),
24 m_clientModel(0)
25 {
26 ui->setupUi(this);
27
28 m_platformStyle = platformStyle;
29
30 m_configSuperStakerPage = new SuperStakerConfigDialog(this);
31 m_addSuperStakerPage = new AddSuperStakerPage(this);
32 m_delegationsSuperStakerPage = new DelegationsStakerDialog(this);
33 m_splitUtxoPage = new SplitUTXOPage(this, SplitUTXOPage::SuperStaker);
34
35 m_configSuperStakerPage->setEnabled(false);
36 m_delegationsSuperStakerPage->setEnabled(false);
37 m_splitUtxoPage->setEnabled(false);
38
39 QAction *copyStakerNameAction = new QAction(tr("Copy staker name"), this);
40 QAction *copyStakerAddressAction = new QAction(tr("Copy staker address"), this);
41 QAction *copyStekerMinFeeAction = new QAction(tr("Copy staker minimum fee"), this);
42 QAction *copyStekerWeightAction = new QAction(tr("Copy staker weight"), this);
43 QAction *copyDelegationsWeightAction = new QAction(tr("Copy delegations weight"), this);
44 QAction *configSuperStakerAction = new QAction(tr("Configure super staker"), this);
45 QAction *editStakerNameAction = new QAction(tr("Edit staker name"), this);
46 QAction *removeSuperStakerAction = new QAction(tr("Remove super staker"), this);
47
48 m_superStakerList = new SuperStakerListWidget(platformStyle, this);
49 m_superStakerList->setContextMenuPolicy(Qt::CustomContextMenu);
50 new QVBoxLayout(ui->scrollArea);
51 ui->scrollArea->setWidget(m_superStakerList);
52 ui->scrollArea->setWidgetResizable(true);
53 connect(m_superStakerList, &SuperStakerListWidget::configSuperStaker, this, &SuperStakerPage::on_configSuperStaker);
54 connect(m_superStakerList, &SuperStakerListWidget::addSuperStaker, this, &SuperStakerPage::on_addSuperStaker);
55 connect(m_superStakerList, &SuperStakerListWidget::removeSuperStaker, this, &SuperStakerPage::on_removeSuperStaker);
56 connect(m_superStakerList, &SuperStakerListWidget::delegationsSuperStaker, this, &SuperStakerPage::on_delegationsSuperStaker);
57 connect(m_superStakerList, &SuperStakerListWidget::splitCoins, this, &SuperStakerPage::on_splitCoins);
58 connect(m_superStakerList, &SuperStakerListWidget::restoreSuperStakers, this, &SuperStakerPage::on_restoreSuperStakers);
59
60 contextMenu = new QMenu(m_superStakerList);
61 contextMenu->addAction(copyStakerNameAction);
62 contextMenu->addAction(copyStakerAddressAction);
63 contextMenu->addAction(copyStekerWeightAction);
64 contextMenu->addAction(copyDelegationsWeightAction);
65 contextMenu->addAction(copyStekerMinFeeAction);
66 contextMenu->addAction(configSuperStakerAction);
67 contextMenu->addAction(editStakerNameAction);
68 contextMenu->addAction(removeSuperStakerAction);
69
70 connect(copyStakerNameAction, &QAction::triggered, this, &SuperStakerPage::copyStakerName);
71 connect(copyStakerAddressAction, &QAction::triggered, this, &SuperStakerPage::copyStakerAddress);
72 connect(copyStekerMinFeeAction, &QAction::triggered, this, &SuperStakerPage::copyStekerMinFee);
73 connect(copyStekerWeightAction, &QAction::triggered, this, &SuperStakerPage::copyStakerWeight);
74 connect(copyDelegationsWeightAction, &QAction::triggered, this, &SuperStakerPage::copyDelegationsWeight);
75 connect(configSuperStakerAction, &QAction::triggered, this, &SuperStakerPage::configSuperStaker);
76 connect(editStakerNameAction, &QAction::triggered, this, &SuperStakerPage::editStakerName);
77 connect(removeSuperStakerAction, &QAction::triggered, this, &SuperStakerPage::removeSuperStaker);
78
79 connect(m_superStakerList, &SuperStakerListWidget::customContextMenuRequested, this, &SuperStakerPage::contextualMenu);
80 }
81
~SuperStakerPage()82 SuperStakerPage::~SuperStakerPage()
83 {
84 delete ui;
85 }
86
setModel(WalletModel * _model)87 void SuperStakerPage::setModel(WalletModel *_model)
88 {
89 m_model = _model;
90 m_addSuperStakerPage->setModel(m_model);
91 m_configSuperStakerPage->setModel(m_model);
92 m_delegationsSuperStakerPage->setModel(m_model);
93 m_superStakerList->setModel(m_model);
94 m_splitUtxoPage->setModel(m_model);
95 if(m_model && m_model->getSuperStakerItemModel())
96 {
97 // Set current super staker
98 connect(m_superStakerList->superStakerModel(), &QAbstractItemModel::dataChanged, this, &SuperStakerPage::on_dataChanged);
99 connect(m_superStakerList->superStakerModel(), &QAbstractItemModel::rowsInserted, this, &SuperStakerPage::on_rowsInserted);
100 if(m_superStakerList->superStakerModel()->rowCount() > 0)
101 {
102 QModelIndex currentSuperStaker(m_superStakerList->superStakerModel()->index(0, 0));
103 on_currentSuperStakerChanged(currentSuperStaker);
104 }
105 }
106 }
107
setClientModel(ClientModel * _clientModel)108 void SuperStakerPage::setClientModel(ClientModel *_clientModel)
109 {
110 m_clientModel = _clientModel;
111 m_configSuperStakerPage->setClientModel(_clientModel);
112 m_superStakerList->setClientModel(_clientModel);
113 }
114
on_goToConfigSuperStakerPage()115 void SuperStakerPage::on_goToConfigSuperStakerPage()
116 {
117 m_configSuperStakerPage->show();
118 }
119
on_goToAddSuperStakerPage()120 void SuperStakerPage::on_goToAddSuperStakerPage()
121 {
122 m_addSuperStakerPage->show();
123 }
124
on_currentSuperStakerChanged(QModelIndex index)125 void SuperStakerPage::on_currentSuperStakerChanged(QModelIndex index)
126 {
127 if(m_superStakerList->superStakerModel())
128 {
129 if(index.isValid())
130 {
131 QString hash = m_superStakerList->superStakerModel()->data(index, SuperStakerItemModel::HashRole).toString();
132 m_selectedSuperStakerHash = hash;
133 QString address = m_superStakerList->superStakerModel()->data(index, SuperStakerItemModel::StakerAddressRole).toString();
134 QString name = m_superStakerList->superStakerModel()->data(index, SuperStakerItemModel::StakerNameRole).toString();
135 int minFee = m_superStakerList->superStakerModel()->data(index, SuperStakerItemModel::MinFeeRole).toInt();
136 m_configSuperStakerPage->setSuperStakerData(hash);
137 m_delegationsSuperStakerPage->setSuperStakerData(name, address, minFee, hash);
138 m_splitUtxoPage->setAddress(address);
139
140 if(!m_configSuperStakerPage->isEnabled())
141 m_configSuperStakerPage->setEnabled(true);
142 if(!m_delegationsSuperStakerPage->isEnabled())
143 m_delegationsSuperStakerPage->setEnabled(true);
144 if(!m_splitUtxoPage->isEnabled())
145 m_splitUtxoPage->setEnabled(true);
146 }
147 else
148 {
149 m_configSuperStakerPage->setEnabled(false);
150 m_configSuperStakerPage->setSuperStakerData("");
151 m_delegationsSuperStakerPage->setEnabled(false);
152 m_delegationsSuperStakerPage->setSuperStakerData("", "", 0, "");
153 m_splitUtxoPage->setEnabled(false);
154 m_splitUtxoPage->setAddress("");
155 m_selectedSuperStakerHash = "";
156 }
157 }
158 }
159
on_dataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight,const QVector<int> & roles)160 void SuperStakerPage::on_dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
161 {
162 Q_UNUSED(bottomRight);
163 Q_UNUSED(roles);
164
165 if(m_superStakerList->superStakerModel())
166 {
167 QString superStakerHash = m_superStakerList->superStakerModel()->data(topLeft, SuperStakerItemModel::HashRole).toString();
168 if(m_selectedSuperStakerHash.isEmpty() ||
169 superStakerHash == m_selectedSuperStakerHash)
170 {
171 on_currentSuperStakerChanged(topLeft);
172 }
173 }
174 }
175
on_currentChanged(QModelIndex current,QModelIndex previous)176 void SuperStakerPage::on_currentChanged(QModelIndex current, QModelIndex previous)
177 {
178 Q_UNUSED(previous);
179
180 on_currentSuperStakerChanged(current);
181 }
182
on_rowsInserted(QModelIndex index,int first,int last)183 void SuperStakerPage::on_rowsInserted(QModelIndex index, int first, int last)
184 {
185 Q_UNUSED(index);
186 Q_UNUSED(first);
187 Q_UNUSED(last);
188
189 if(m_superStakerList->superStakerModel()->rowCount() == 1)
190 {
191 QModelIndex currentSuperStaker(m_superStakerList->superStakerModel()->index(0, 0));
192 on_currentSuperStakerChanged(currentSuperStaker);
193 }
194 }
195
contextualMenu(const QPoint & point)196 void SuperStakerPage::contextualMenu(const QPoint &point)
197 {
198 QModelIndex index = m_superStakerList->indexAt(point);
199 if(index.isValid())
200 {
201 indexMenu = index;
202 contextMenu->exec(QCursor::pos());
203 }
204 }
205
copyStekerMinFee()206 void SuperStakerPage::copyStekerMinFee()
207 {
208 if(indexMenu.isValid())
209 {
210 GUIUtil::setClipboard(indexMenu.data(SuperStakerItemModel::FormattedMinFeeRole).toString());
211 indexMenu = QModelIndex();
212 }
213 }
214
copyStakerName()215 void SuperStakerPage::copyStakerName()
216 {
217 if(indexMenu.isValid())
218 {
219 GUIUtil::setClipboard(indexMenu.data(SuperStakerItemModel::StakerNameRole).toString());
220 indexMenu = QModelIndex();
221 }
222 }
223
copyStakerAddress()224 void SuperStakerPage::copyStakerAddress()
225 {
226 if(indexMenu.isValid())
227 {
228 GUIUtil::setClipboard(indexMenu.data(SuperStakerItemModel::StakerAddressRole).toString());
229 indexMenu = QModelIndex();
230 }
231 }
232
copyStakerWeight()233 void SuperStakerPage::copyStakerWeight()
234 {
235 if(indexMenu.isValid())
236 {
237 GUIUtil::setClipboard(indexMenu.data(SuperStakerItemModel::FormattedWeightRole).toString());
238 indexMenu = QModelIndex();
239 }
240 }
241
copyDelegationsWeight()242 void SuperStakerPage::copyDelegationsWeight()
243 {
244 if(indexMenu.isValid())
245 {
246 GUIUtil::setClipboard(indexMenu.data(SuperStakerItemModel::FormattedDelegationsWeightRole).toString());
247 indexMenu = QModelIndex();
248 }
249 }
250
configSuperStaker()251 void SuperStakerPage::configSuperStaker()
252 {
253 if(indexMenu.isValid())
254 {
255 on_configSuperStaker(indexMenu);
256 indexMenu = QModelIndex();
257 }
258 }
259
editStakerName()260 void SuperStakerPage::editStakerName()
261 {
262 if(indexMenu.isValid())
263 {
264 QString stakerName = indexMenu.data(SuperStakerItemModel::StakerNameRole).toString();
265 QString stakerAddress = indexMenu.data(SuperStakerItemModel::StakerAddressRole).toString();
266 QString sHash = indexMenu.data(SuperStakerItemModel::HashRole).toString();
267 uint256 hash;
268 hash.SetHex(sHash.toStdString());
269
270 EditSuperStakerDialog dlg;
271 dlg.setData(stakerName, stakerAddress);
272
273 if(dlg.exec())
274 {
275 interfaces::SuperStakerInfo staker = m_model->wallet().getSuperStaker(hash);
276 if(staker.hash == hash)
277 {
278 staker.staker_name = dlg.getSuperStakerName().toStdString();
279 m_model->wallet().removeSuperStakerEntry(sHash.toStdString());
280 m_model->wallet().addSuperStakerEntry(staker);
281 }
282 }
283 }
284 }
285
on_configSuperStaker(const QModelIndex & index)286 void SuperStakerPage::on_configSuperStaker(const QModelIndex &index)
287 {
288 m_configSuperStakerPage->clearAll();
289 on_currentSuperStakerChanged(index);
290 on_goToConfigSuperStakerPage();
291 }
292
on_addSuperStaker()293 void SuperStakerPage::on_addSuperStaker()
294 {
295 on_goToAddSuperStakerPage();
296 }
297
removeSuperStaker()298 void SuperStakerPage::removeSuperStaker()
299 {
300 if(indexMenu.isValid())
301 {
302 on_removeSuperStaker(indexMenu);
303 indexMenu = QModelIndex();
304 }
305 }
306
on_removeSuperStaker(const QModelIndex & index)307 void SuperStakerPage::on_removeSuperStaker(const QModelIndex &index)
308 {
309 if(index.isValid() && m_model)
310 {
311 QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm super staker removal"), tr("The selected super staker will be removed from the list. Are you sure?"),
312 QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
313
314 if(btnRetVal == QMessageBox::Yes)
315 {
316 QString hash = m_superStakerList->superStakerModel()->data(index, SuperStakerItemModel::HashRole).toString();
317 m_model->wallet().removeSuperStakerEntry(hash.toStdString());
318 }
319 }
320 }
321
on_delegationsSuperStaker(const QModelIndex & index)322 void SuperStakerPage::on_delegationsSuperStaker(const QModelIndex &index)
323 {
324 on_currentSuperStakerChanged(index);
325 on_goToDelegationsSuperStakerPage();
326 }
327
on_restoreSuperStakers()328 void SuperStakerPage::on_restoreSuperStakers()
329 {
330 if(m_model)
331 {
332 bool fSuperStake = m_model->wallet().getEnabledSuperStaking();
333 if(!fSuperStake)
334 {
335 QMessageBox::information(this, tr("Super staking"), tr("Enable super staking from the option menu in order to start the restoration."));
336 }
337 else
338 {
339 QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm super stakers restoration"), tr("Are you sure you wish to restore your super stakers?"),
340 QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
341
342 if(btnRetVal == QMessageBox::Yes)
343 {
344 if(m_model->wallet().restoreSuperStakers() == 0)
345 {
346 QMessageBox::information(this, tr("Super stakers not found"), tr("No super stakers found to restore."), QMessageBox::Ok);
347 }
348 }
349 }
350 }
351 }
352
on_goToDelegationsSuperStakerPage()353 void SuperStakerPage::on_goToDelegationsSuperStakerPage()
354 {
355 m_delegationsSuperStakerPage->show();
356 }
357
on_splitCoins(const QModelIndex & index)358 void SuperStakerPage::on_splitCoins(const QModelIndex &index)
359 {
360 on_currentSuperStakerChanged(index);
361 on_goToSplitCoinsPage();
362 }
363
on_goToSplitCoinsPage()364 void SuperStakerPage::on_goToSplitCoinsPage()
365 {
366 m_splitUtxoPage->show();
367 }
368