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