qt: Make sure the statusbar reflects internal states correct (#3698)

* qt: Increase number of spinner frames

* qt: Add and use BitcoinGUI::startSpinner and BitcoinGUI::stopSpinner

* qt: Handle CMasternodeSync::Reset calls

* qt: Make sure the statusbar always reflects the sync state/progress

* qt: Add BitcoinGUI::updateProgressBarVisibility

* qt: Animate connection icon while connecting

* qt: Refactor check in BitcoinGUI::updateProgressBarVisibility

* qt: Rename some variables

* Update src/qt/bitcoingui.cpp

Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com>

Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com>
This commit is contained in:
dustinface 2020-09-13 00:48:10 +02:00 committed by GitHub
parent df536f269a
commit 3fe3ca9666
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
94 changed files with 229 additions and 32 deletions

View File

@ -120,8 +120,8 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle* networkStyle, QWidget* parent) :
helpMessageDialog(0),
modalOverlay(0),
tabGroup(0),
prevBlocks(0),
spinnerFrame(0)
timerConnecting(0),
timerSpinner(0)
{
QSettings settings;
if (!restoreGeometry(settings.value("MainWindowGeometry").toByteArray())) {
@ -211,6 +211,10 @@ BitcoinGUI::BitcoinGUI(const NetworkStyle* networkStyle, QWidget* parent) :
frameBlocksLayout->addWidget(labelBlocksIcon);
frameBlocksLayout->addStretch();
// Hide the spinner/synced icon by default to avoid
// that the spinner starts before we have any connections
labelBlocksIcon->hide();
// Progress bar and label for blocks download
progressBarLabel = new QLabel();
progressBarLabel->setVisible(true);
@ -281,6 +285,88 @@ BitcoinGUI::~BitcoinGUI()
delete tabGroup;
}
void BitcoinGUI::startSpinner()
{
if (labelBlocksIcon == nullptr || labelBlocksIcon->isHidden() || timerSpinner != nullptr) {
return;
}
auto getNextFrame = []() {
static std::vector<std::unique_ptr<QPixmap>> vecFrames;
static std::vector<std::unique_ptr<QPixmap>>::iterator itFrame;
while (vecFrames.size() < SPINNER_FRAMES) {
QString&& strFrame = QString("spinner-%1").arg(vecFrames.size(), 3, 10, QChar('0'));
QPixmap&& frame = getIcon(strFrame, GUIUtil::ThemedColor::ORANGE, MOVIES_PATH).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE);
itFrame = vecFrames.insert(vecFrames.end(), std::make_unique<QPixmap>(frame));
}
assert(vecFrames.size() == SPINNER_FRAMES);
if (itFrame == vecFrames.end()) {
itFrame = vecFrames.begin();
}
return *itFrame++->get();
};
timerSpinner = new QTimer(this);
QObject::connect(timerSpinner, &QTimer::timeout, [=]() {
if (timerSpinner == nullptr) {
return;
}
labelBlocksIcon->setPixmap(getNextFrame());
});
timerSpinner->start(40);
}
void BitcoinGUI::stopSpinner()
{
if (timerSpinner == nullptr) {
return;
}
timerSpinner->deleteLater();
timerSpinner = nullptr;
}
void BitcoinGUI::startConnectingAnimation()
{
static int nStep{-1};
const int nAnimationSteps = 10;
if (timerConnecting != nullptr) {
return;
}
timerConnecting = new QTimer(this);
QObject::connect(timerConnecting, &QTimer::timeout, [=]() {
if (timerConnecting == nullptr) {
return;
}
QString strImage;
GUIUtil::ThemedColor color;
nStep = (nStep + 1) % (nAnimationSteps + 1);
if (nStep == 0) {
strImage = "connect_4";
color = GUIUtil::ThemedColor::ICON_ALTERNATIVE_COLOR;
} else if (nStep == nAnimationSteps / 2) {
strImage = "connect_1";
color = GUIUtil::ThemedColor::ORANGE;
} else {
return;
}
labelConnectionsIcon->setPixmap(GUIUtil::getIcon(strImage, color).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
});
timerConnecting->start(100);
}
void BitcoinGUI::stopConnectingAnimation()
{
if (timerConnecting == nullptr) {
return;
}
timerConnecting->deleteLater();
timerConnecting = nullptr;
}
void BitcoinGUI::createActions()
{
tabGroup = new QButtonGroup(this);
@ -1002,7 +1088,10 @@ void BitcoinGUI::gotoVerifyMessageTab(QString addr)
void BitcoinGUI::updateNetworkState()
{
static int nCountPrev{0};
static bool fNetworkActivePrev{false};
int count = clientModel->getNumConnections();
bool fNetworkActive = clientModel->getNetworkActive();
QString icon;
GUIUtil::ThemedColor color = GUIUtil::ThemedColor::ORANGE;
switch(count)
@ -1014,7 +1103,35 @@ void BitcoinGUI::updateNetworkState()
default: icon = "connect_4"; color = GUIUtil::ThemedColor::GREEN; break;
}
if (clientModel->getNetworkActive()) {
labelBlocksIcon->setVisible(count > 0);
updateProgressBarVisibility();
bool fNetworkBecameActive = (!fNetworkActivePrev && fNetworkActive) || (nCountPrev == 0 && count > 0);
bool fNetworkBecameInactive = (fNetworkActivePrev && !fNetworkActive) || (nCountPrev > 0 && count == 0);
if (fNetworkBecameActive) {
// If the sync process still signals synced after five seconds represent it in the UI.
if (masternodeSync.IsSynced()) {
QTimer::singleShot(5000, this, [&]() {
if (clientModel->getNumConnections() > 0 && masternodeSync.IsSynced()) {
setAdditionalDataSyncProgress(1);
}
});
}
startSpinner();
} else if (fNetworkBecameInactive) {
labelBlocksIcon->hide();
stopSpinner();
}
if (fNetworkBecameActive || fNetworkBecameInactive) {
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getLastBlockHash(), clientModel->getVerificationProgress(nullptr), false);
}
nCountPrev = count;
fNetworkActivePrev = fNetworkActive;
if (fNetworkActive) {
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Dash network", "", count));
} else {
labelConnectionsIcon->setToolTip(tr("Network activity disabled"));
@ -1022,7 +1139,13 @@ void BitcoinGUI::updateNetworkState()
color = GUIUtil::ThemedColor::RED;
}
labelConnectionsIcon->setPixmap(GUIUtil::getIcon(icon, color).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
if (fNetworkActive && count == 0) {
startConnectingAnimation();
}
if (!fNetworkActive || count > 0) {
stopConnectingAnimation();
labelConnectionsIcon->setPixmap(GUIUtil::getIcon(icon, color).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
}
}
void BitcoinGUI::setNumConnections(int count)
@ -1044,6 +1167,21 @@ void BitcoinGUI::updateHeadersSyncProgressLabel()
progressBarLabel->setText(tr("Syncing Headers (%1%)...").arg(QString::number(100.0 / (headersTipHeight+estHeadersLeft)*headersTipHeight, 'f', 1)));
}
void BitcoinGUI::updateProgressBarVisibility()
{
if (clientModel == nullptr) {
return;
}
// Show the progress bar label if the network is active + we are out of sync or we have no connections.
bool fShowProgressBarLabel = clientModel->getNetworkActive() && (!masternodeSync.IsSynced() || clientModel->getNumConnections() == 0);
// Show the progress bar only if the the network active + we are not synced + we have any connection. Unlike with the label
// which gives an info text about the connecting phase there is no reason to show the progress bar if we don't have connections
// since it will not get any updates in this case.
bool fShowProgressBar = clientModel->getNetworkActive() && !masternodeSync.IsSynced() && clientModel->getNumConnections() > 0;
progressBarLabel->setVisible(fShowProgressBarLabel);
progressBar->setVisible(fShowProgressBar);
}
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QString& blockHash, double nVerificationProgress, bool header)
{
#ifdef Q_OS_MAC
@ -1071,6 +1209,8 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QStri
if (!clientModel)
return;
updateProgressBarVisibility();
// Prevent orphan statusbar messages (e.g. hover Quit in main menu, wait until chain-sync starts -> garbled text)
statusBar()->clearMessage();
@ -1131,21 +1271,11 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, const QStri
{
QString timeBehindText = GUIUtil::formatNiceTimeOffset(secs);
progressBarLabel->setVisible(true);
progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
progressBar->setMaximum(1000000000);
progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
progressBar->setVisible(true);
tooltip = tr("Catching up...") + QString("<br>") + tooltip;
if(count != prevBlocks)
{
labelBlocksIcon->setPixmap(GUIUtil::getIcon(QString(
"spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')), GUIUtil::ThemedColor::ORANGE, MOVIES_PATH)
.pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
}
prevBlocks = count;
#ifdef ENABLE_WALLET
if(walletFrame)
@ -1175,6 +1305,16 @@ void BitcoinGUI::setAdditionalDataSyncProgress(double nSyncProgress)
if(!clientModel)
return;
// If masternodeSync.Reset() has been called make sure status bar shows the correct information.
if (nSyncProgress == -1) {
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getLastBlockHash(), clientModel->getVerificationProgress(nullptr), false);
if (clientModel->getNumConnections()) {
labelBlocksIcon->show();
startSpinner();
}
return;
}
// No additional data sync should be happening while blockchain is not synced, nothing to update
if(!masternodeSync.IsBlockchainSynced())
return;
@ -1193,17 +1333,12 @@ void BitcoinGUI::setAdditionalDataSyncProgress(double nSyncProgress)
walletFrame->showOutOfSyncWarning(false);
#endif // ENABLE_WALLET
updateProgressBarVisibility();
if(masternodeSync.IsSynced()) {
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
stopSpinner();
labelBlocksIcon->setPixmap(GUIUtil::getIcon("synced", GUIUtil::ThemedColor::GREEN).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
} else {
labelBlocksIcon->setPixmap(GUIUtil::getIcon(QString(
"spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')), GUIUtil::ThemedColor::ORANGE, MOVIES_PATH)
.pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES;
progressBar->setFormat(tr("Synchronizing additional data: %p%"));
progressBar->setMaximum(1000000000);
progressBar->setValue(nSyncProgress * 1000000000.0 + 0.5);
@ -1310,10 +1445,6 @@ void BitcoinGUI::changeEvent(QEvent *e)
#endif
if (masternodeSync.IsSynced()) {
labelBlocksIcon->setPixmap(GUIUtil::getIcon("synced", GUIUtil::ThemedColor::GREEN).pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
} else {
labelBlocksIcon->setPixmap(GUIUtil::getIcon(QString(
"spinner-%1").arg(spinnerFrame, 3, 10, QChar('0')), GUIUtil::ThemedColor::ORANGE, MOVIES_PATH)
.pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE));
}
}
}

View File

@ -146,9 +146,19 @@ private:
CAppNapInhibitor* m_app_nap_inhibitor = nullptr;
#endif
/** Keep track of previous number of blocks, to detect progress */
int prevBlocks;
int spinnerFrame;
/** Timer to update the spinner animation in the status bar periodically */
QTimer* timerSpinner;
/** Start the spinner animation in the status bar if it's not running and if labelBlocksIcon is visible. */
void startSpinner();
/** Stop the spinner animation in the status bar */
void stopSpinner();
/** Timer to update the connection icon during connecting phase */
QTimer* timerConnecting;
/** Start the connecting animation */
void startConnectingAnimation();
/** Stop the connecting animation */
void stopConnectingAnimation();
struct IncomingTransactionMessage {
QString date;
@ -186,6 +196,8 @@ private:
void updateHeadersSyncProgressLabel();
void updateProgressBarVisibility();
Q_SIGNALS:
/** Signal raised when a URI was entered or dragged to the GUI */
void receivedURI(const QString &uri);

View File

@ -169,5 +169,59 @@
<file alias="spinner-033">res/movies/spinner-033.png</file>
<file alias="spinner-034">res/movies/spinner-034.png</file>
<file alias="spinner-035">res/movies/spinner-035.png</file>
<file alias="spinner-036">res/movies/spinner-036.png</file>
<file alias="spinner-037">res/movies/spinner-037.png</file>
<file alias="spinner-038">res/movies/spinner-038.png</file>
<file alias="spinner-039">res/movies/spinner-039.png</file>
<file alias="spinner-040">res/movies/spinner-040.png</file>
<file alias="spinner-041">res/movies/spinner-041.png</file>
<file alias="spinner-042">res/movies/spinner-042.png</file>
<file alias="spinner-043">res/movies/spinner-043.png</file>
<file alias="spinner-044">res/movies/spinner-044.png</file>
<file alias="spinner-045">res/movies/spinner-045.png</file>
<file alias="spinner-046">res/movies/spinner-046.png</file>
<file alias="spinner-047">res/movies/spinner-047.png</file>
<file alias="spinner-048">res/movies/spinner-048.png</file>
<file alias="spinner-049">res/movies/spinner-049.png</file>
<file alias="spinner-050">res/movies/spinner-050.png</file>
<file alias="spinner-051">res/movies/spinner-051.png</file>
<file alias="spinner-052">res/movies/spinner-052.png</file>
<file alias="spinner-053">res/movies/spinner-053.png</file>
<file alias="spinner-054">res/movies/spinner-054.png</file>
<file alias="spinner-055">res/movies/spinner-055.png</file>
<file alias="spinner-056">res/movies/spinner-056.png</file>
<file alias="spinner-057">res/movies/spinner-057.png</file>
<file alias="spinner-058">res/movies/spinner-058.png</file>
<file alias="spinner-059">res/movies/spinner-059.png</file>
<file alias="spinner-060">res/movies/spinner-060.png</file>
<file alias="spinner-061">res/movies/spinner-061.png</file>
<file alias="spinner-062">res/movies/spinner-062.png</file>
<file alias="spinner-063">res/movies/spinner-063.png</file>
<file alias="spinner-064">res/movies/spinner-064.png</file>
<file alias="spinner-065">res/movies/spinner-065.png</file>
<file alias="spinner-066">res/movies/spinner-066.png</file>
<file alias="spinner-067">res/movies/spinner-067.png</file>
<file alias="spinner-068">res/movies/spinner-068.png</file>
<file alias="spinner-069">res/movies/spinner-069.png</file>
<file alias="spinner-070">res/movies/spinner-070.png</file>
<file alias="spinner-071">res/movies/spinner-071.png</file>
<file alias="spinner-072">res/movies/spinner-072.png</file>
<file alias="spinner-073">res/movies/spinner-073.png</file>
<file alias="spinner-074">res/movies/spinner-074.png</file>
<file alias="spinner-075">res/movies/spinner-075.png</file>
<file alias="spinner-076">res/movies/spinner-076.png</file>
<file alias="spinner-077">res/movies/spinner-077.png</file>
<file alias="spinner-078">res/movies/spinner-078.png</file>
<file alias="spinner-079">res/movies/spinner-079.png</file>
<file alias="spinner-080">res/movies/spinner-080.png</file>
<file alias="spinner-081">res/movies/spinner-081.png</file>
<file alias="spinner-082">res/movies/spinner-082.png</file>
<file alias="spinner-083">res/movies/spinner-083.png</file>
<file alias="spinner-084">res/movies/spinner-084.png</file>
<file alias="spinner-085">res/movies/spinner-085.png</file>
<file alias="spinner-086">res/movies/spinner-086.png</file>
<file alias="spinner-087">res/movies/spinner-087.png</file>
<file alias="spinner-088">res/movies/spinner-088.png</file>
<file alias="spinner-089">res/movies/spinner-089.png</file>
</qresource>
</RCC>

View File

@ -39,7 +39,7 @@ static const int MAX_URI_LENGTH = 255;
#define QR_IMAGE_SIZE 300
/* Number of frames in spinner animation */
#define SPINNER_FRAMES 36
#define SPINNER_FRAMES 90
#define QAPP_ORG_NAME "Dash"
#define QAPP_ORG_DOMAIN "dash.org"

View File

@ -4,9 +4,9 @@
export LC_ALL=C
FRAMEDIR=$(dirname $0)
for i in {0..35}
for i in {0..89}
do
frame=$(printf "%03d" $i)
angle=$(($i * 10))
angle=$(($i * 4))
convert $FRAMEDIR/../src/spinner.png -background "rgba(0,0,0,0.0)" -distort SRT $angle $FRAMEDIR/spinner-$frame.png
done

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 956 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 992 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB