1 #if defined(HAVE_CONFIG_H)
2 #include <config/bitcoin-config.h>
3 #endif
4
5 #include <qt/superstakeritemwidget.h>
6 #include <qt/platformstyle.h>
7 #include <qt/forms/ui_superstakeritemwidget.h>
8 #include <qt/bitcoinunits.h>
9 #include <qt/optionsmodel.h>
10 #include <qt/walletmodel.h>
11 #include <qt/clientmodel.h>
12 #include <interfaces/node.h>
13 #include <chainparams.h>
14 #include <rpc/server.h>
15 #include <qt/guiutil.h>
16
17 #include <QFile>
18
19 class SuperStakerItemWidgetPriv
20 {
21 public:
22 QString fee;
23 QString staker;
24 QString address;
25 bool staking_on = false;
26 int64_t balance = 0;
27 int64_t stake = 0;
28 int64_t weight = 0;
29 int64_t delegationsWeight = 0;
30 };
31
32 #define SUPERSTAKER_ITEM_ICONSIZE 24
33 #define SUPERSTAKER_STAKER_SIZE 210
SuperStakerItemWidget(const PlatformStyle * platformStyle,QWidget * parent,ItemType type)34 SuperStakerItemWidget::SuperStakerItemWidget(const PlatformStyle *platformStyle, QWidget *parent, ItemType type) :
35 QWidget(parent),
36 ui(new Ui::SuperStakerItemWidget),
37 m_platfromStyle(platformStyle),
38 m_type(type),
39 m_position(-1),
40 m_model(0),
41 m_clientModel(0)
42
43 {
44 ui->setupUi(this);
45 ui->stackedWidget->setCurrentIndex(type);
46 ui->buttonSplit->setIcon(platformStyle->MultiStatesIcon(":/icons/split", PlatformStyle::PushButtonIcon));
47 ui->buttonConfig->setIcon(platformStyle->MultiStatesIcon(":/icons/configure", PlatformStyle::PushButtonIcon));
48 ui->buttonRemove->setIcon(platformStyle->MultiStatesIcon(":/icons/remove_entry", PlatformStyle::PushButtonIcon));
49 ui->buttonAdd->setIcon(platformStyle->MultiStatesIcon(":/icons/plus_full", PlatformStyle::PushButtonIcon));
50 ui->buttonRestore->setIcon(platformStyle->MultiStatesIcon(":/icons/restore", PlatformStyle::PushButtonIcon));
51 ui->superStakerLogo->setPixmap(platformStyle->MultiStatesIcon(m_type == New ? ":/icons/superstake" : ":/icons/staking_off").pixmap(SUPERSTAKER_ITEM_ICONSIZE, SUPERSTAKER_ITEM_ICONSIZE));
52
53 ui->buttonDelegations->setToolTip(tr("Delegations for super staker"));
54 ui->buttonSplit->setToolTip(tr("Split coins for super staker"));
55 ui->buttonConfig->setToolTip(tr("Configure super staker"));
56 ui->buttonRemove->setToolTip(tr("Remove super staker"));
57 ui->buttonAdd->setToolTip(tr("Add super staker"));
58 ui->buttonRestore->setToolTip(tr("Restore super stakers"));
59
60 d = new SuperStakerItemWidgetPriv();
61 }
62
~SuperStakerItemWidget()63 SuperStakerItemWidget::~SuperStakerItemWidget()
64 {
65 delete ui;
66 }
67
setData(const QString & fee,const QString & staker,const QString & address,const bool & staking_on,const int64_t & balance,const int64_t & stake,const int64_t & weight,const int64_t & delegationsWeight)68 void SuperStakerItemWidget::setData(const QString &fee, const QString &staker, const QString &address, const bool &staking_on, const int64_t &balance, const int64_t &stake, const int64_t &weight, const int64_t &delegationsWeight)
69 {
70 // Set data
71 d->fee = fee;
72 d->staker = staker;
73 d->address = address;
74 d->staking_on = staking_on;
75 d->balance = balance;
76 d->stake = stake;
77 d->weight = weight;
78 d->delegationsWeight = delegationsWeight;
79
80 // Update GUI
81 if(d->fee != ui->labelFee->text())
82 ui->labelFee->setText(d->fee);
83 if(d->staker != ui->labelStaker->toolTip())
84 updateLabelStaker();
85 if(d->address != ui->labelAddress->text())
86 ui->labelAddress->setText(d->address);
87 updateLogo();
88 updateBalance();
89 }
90
setPosition(int position)91 void SuperStakerItemWidget::setPosition(int position)
92 {
93 m_position = position;
94 }
95
on_buttonAdd_clicked()96 void SuperStakerItemWidget::on_buttonAdd_clicked()
97 {
98 Q_EMIT clicked(m_position, Buttons::Add);
99 }
100
on_buttonRemove_clicked()101 void SuperStakerItemWidget::on_buttonRemove_clicked()
102 {
103 Q_EMIT clicked(m_position, Buttons::Remove);
104 }
105
on_buttonConfig_clicked()106 void SuperStakerItemWidget::on_buttonConfig_clicked()
107 {
108 Q_EMIT clicked(m_position, Buttons::Config);
109 }
110
on_buttonDelegations_clicked()111 void SuperStakerItemWidget::on_buttonDelegations_clicked()
112 {
113 Q_EMIT clicked(m_position, Buttons::Delegations);
114 }
115
on_buttonSplit_clicked()116 void SuperStakerItemWidget::on_buttonSplit_clicked()
117 {
118 Q_EMIT clicked(m_position, Buttons::Split);
119 }
120
on_buttonRestore_clicked()121 void SuperStakerItemWidget::on_buttonRestore_clicked()
122 {
123 Q_EMIT clicked(m_position, Buttons::Restore);
124 }
125
position() const126 int SuperStakerItemWidget::position() const
127 {
128 return m_position;
129 }
130
updateLogo()131 void SuperStakerItemWidget::updateLogo()
132 {
133 if(!m_model || !m_clientModel)
134 return;
135
136 if(m_model->node().shutdownRequested())
137 return;
138
139 QString filename = d->staking_on ? ":/icons/staking_on" : ":/icons/staking_off";
140 if(m_filename != filename)
141 {
142 m_filename = filename;
143 QPixmap pixmap = m_platfromStyle->MultiStatesIcon(m_filename).pixmap(SUPERSTAKER_ITEM_ICONSIZE, SUPERSTAKER_ITEM_ICONSIZE);
144 ui->superStakerLogo->setPixmap(pixmap);
145 }
146
147 uint64_t nWeight = d->weight;
148 uint64_t nDelegationsWeight = d->delegationsWeight;
149 if (d->staking_on && nWeight && nDelegationsWeight)
150 {
151 uint64_t nNetworkWeight = GetPoSKernelPS();
152 int headersTipHeight = m_clientModel->getHeaderTipHeight();
153 int64_t nTargetSpacing = Params().GetConsensus().TargetSpacing(headersTipHeight);
154
155 unsigned nEstimateTime = nTargetSpacing * nNetworkWeight / nDelegationsWeight;
156
157 QString text;
158 if (nEstimateTime < 60)
159 {
160 text = tr("%n second(s)", "", nEstimateTime);
161 }
162 else if (nEstimateTime < 60*60)
163 {
164 text = tr("%n minute(s)", "", nEstimateTime/60);
165 }
166 else if (nEstimateTime < 24*60*60)
167 {
168 text = tr("%n hour(s)", "", nEstimateTime/(60*60));
169 }
170 else
171 {
172 text = tr("%n day(s)", "", nEstimateTime/(60*60*24));
173 }
174
175 nWeight /= COIN;
176 nNetworkWeight /= COIN;
177 nDelegationsWeight /= COIN;
178
179 ui->superStakerLogo->setToolTip(tr("Super staking.<br>Your weight is %1<br>Delegations weight is %2<br>Network weight is %3<br>Expected time to earn reward is %4").arg(nWeight).arg(nDelegationsWeight).arg(nNetworkWeight).arg(text));
180 }
181 else
182 {
183 if (m_model->node().getNodeCount(CConnman::CONNECTIONS_ALL) == 0)
184 ui->superStakerLogo->setToolTip(tr("Not staking because wallet is offline"));
185 else if (m_model->node().isInitialBlockDownload())
186 ui->superStakerLogo->setToolTip(tr("Not staking because wallet is syncing"));
187 else if (!m_model->wallet().getEnabledSuperStaking())
188 ui->superStakerLogo->setToolTip(tr("Not staking because super staking is not enabled"));
189 else if (!nWeight)
190 ui->superStakerLogo->setToolTip(tr("Not staking because you don't have mature coins"));
191 else if (!nDelegationsWeight)
192 ui->superStakerLogo->setToolTip(tr("Not staking because you don't have mature delegated coins"));
193 else if (m_model->wallet().isLocked())
194 ui->superStakerLogo->setToolTip(tr("Not staking because wallet is locked"));
195 else
196 ui->superStakerLogo->setToolTip(tr("Not staking"));
197 }
198 }
199
setModel(WalletModel * _model)200 void SuperStakerItemWidget::setModel(WalletModel *_model)
201 {
202 m_model = _model;
203 if(m_model && m_model->getOptionsModel())
204 {
205 connect(m_model->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &SuperStakerItemWidget::updateDisplayUnit);
206 }
207 updateDisplayUnit();
208 }
209
setClientModel(ClientModel * _clientModel)210 void SuperStakerItemWidget::setClientModel(ClientModel *_clientModel)
211 {
212 m_clientModel = _clientModel;
213 }
214
updateDisplayUnit()215 void SuperStakerItemWidget::updateDisplayUnit()
216 {
217 updateBalance();
218 }
219
updateBalance()220 void SuperStakerItemWidget::updateBalance()
221 {
222 int unit = BitcoinUnits::BTC;
223 if(m_model && m_model->getOptionsModel())
224 unit = m_model->getOptionsModel()->getDisplayUnit();
225 ui->labelAssets->setText(BitcoinUnits::formatWithUnit(unit, d->balance, false, BitcoinUnits::separatorAlways));
226 ui->labelStake->setText(BitcoinUnits::formatWithUnit(unit, d->stake, false, BitcoinUnits::separatorAlways));
227 }
228
updateLabelStaker()229 void SuperStakerItemWidget::updateLabelStaker()
230 {
231 QString text = d->staker;
232 QFontMetrics fm = ui->labelStaker->fontMetrics();
233 for(int i = d->staker.length(); i>3; i--)
234 {
235 text = GUIUtil::cutString(d->staker, i);
236 if(GUIUtil::TextWidth(fm, text) < SUPERSTAKER_STAKER_SIZE)
237 break;
238 }
239 ui->labelStaker->setText(text);
240 ui->labelStaker->setToolTip(d->staker);
241 }
242