From eaaae2655100926819ef821b03d1506e635cfd2f Mon Sep 17 00:00:00 2001
From: inso <insomniak.fr@gmaiL.com>
Date: Sat, 13 May 2017 08:56:42 +0200
Subject: [PATCH] Refresh animation during blockchain loading

---
 res/icons/icons.qrc                           |   1 +
 res/icons/loader.gif                          | Bin 0 -> 4276 bytes
 src/sakia/app.py                              |   2 ++
 src/sakia/gui/main_window/controller.py       |   2 ++
 .../gui/main_window/status_bar/controller.py  |  10 ++++++--
 src/sakia/gui/main_window/status_bar/view.py  |  22 ++++++++++++++----
 src/sakia/services/blockchain.py              |   2 ++
 7 files changed, 32 insertions(+), 7 deletions(-)
 create mode 100644 res/icons/loader.gif

diff --git a/res/icons/icons.qrc b/res/icons/icons.qrc
index d7193f25..c8a8a8e9 100644
--- a/res/icons/icons.qrc
+++ b/res/icons/icons.qrc
@@ -1,5 +1,6 @@
 <RCC>
   <qresource prefix="icons">
+    <file alias="loader">loader.gif</file>
     <file alias="guest_icon">noun_178537_cc.svg</file>
     <file alias="menu_icon">noun_100552_cc.svg</file>
     <file alias="leave_icon">noun_155520_cc.svg</file>
diff --git a/res/icons/loader.gif b/res/icons/loader.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6a4c333d919c7aa2802f921cf9c95126743c3654
GIT binary patch
literal 4276
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
E0Dwk&EdT%j

literal 0
HcmV?d00001

diff --git a/src/sakia/app.py b/src/sakia/app.py
index 8636db9b..d66c5424 100644
--- a/src/sakia/app.py
+++ b/src/sakia/app.py
@@ -52,6 +52,8 @@ class Application(QObject):
     sources_refreshed = pyqtSignal()
     new_blocks_handled = pyqtSignal()
     view_in_wot = pyqtSignal(Identity)
+    refresh_started = pyqtSignal()
+    refresh_finished = pyqtSignal()
 
     qapp = attr.ib()
     loop = attr.ib()
diff --git a/src/sakia/gui/main_window/controller.py b/src/sakia/gui/main_window/controller.py
index f74102c2..b9848b11 100644
--- a/src/sakia/gui/main_window/controller.py
+++ b/src/sakia/gui/main_window/controller.py
@@ -87,6 +87,8 @@ class MainWindowController(QObject):
             main_window.view.showMaximized()
         else:
             main_window.view.show()
+        app.refresh_started.connect(main_window.status_bar.start_loading)
+        app.refresh_finished.connect(main_window.status_bar.stop_loading)
         main_window.model.load_plugins(main_window)
         main_window.refresh(app.currency)
         return main_window
diff --git a/src/sakia/gui/main_window/status_bar/controller.py b/src/sakia/gui/main_window/status_bar/controller.py
index 8500b1a8..ffd20c19 100644
--- a/src/sakia/gui/main_window/status_bar/controller.py
+++ b/src/sakia/gui/main_window/status_bar/controller.py
@@ -14,8 +14,8 @@ class StatusBarController(QObject):
         """
         Constructor of the navigation component
 
-        :param sakia.gui.status_bar.view.StatusBarView view: the presentation
-        :param sakia.core.status_bar.model.StatusBarModel model: the model
+        :param sakia.gui.main_window.status_bar.view.StatusBarView view: the presentation
+        :param sakia.gui.main_window.status_bar.model.StatusBarModel model: the model
         """
         super().__init__()
         self.view = view
@@ -53,6 +53,12 @@ class StatusBarController(QObject):
         timer.timeout.connect(self.update_time)
         timer.start(1000)
 
+    def start_loading(self):
+        self.view.start_loading()
+
+    def stop_loading(self):
+        self.view.stop_loading()
+
     def new_blocks_handled(self):
         current_block = self.model.current_block()
         current_time = self.model.current_time()
diff --git a/src/sakia/gui/main_window/status_bar/view.py b/src/sakia/gui/main_window/status_bar/view.py
index 14ade070..ef8721b4 100644
--- a/src/sakia/gui/main_window/status_bar/view.py
+++ b/src/sakia/gui/main_window/status_bar/view.py
@@ -1,6 +1,7 @@
 from PyQt5.QtWidgets import QStatusBar
-from PyQt5.QtWidgets import QLabel, QComboBox
-from PyQt5.QtCore import Qt
+from PyQt5.QtWidgets import QLabel, QComboBox, QSpacerItem, QSizePolicy
+from PyQt5.QtGui import QMovie
+from PyQt5.QtCore import Qt, QSize
 
 
 class StatusBarView(QStatusBar):
@@ -10,7 +11,6 @@ class StatusBarView(QStatusBar):
 
     def __init__(self, parent):
         super().__init__(parent)
-        self.label_icon = QLabel("", parent)
 
         self.status_label = QLabel("", parent)
         self.status_label.setTextFormat(Qt.RichText)
@@ -18,8 +18,20 @@ class StatusBarView(QStatusBar):
         self.label_time = QLabel("", parent)
 
         self.combo_referential = QComboBox(parent)
-
-        self.addPermanentWidget(self.label_icon, 1)
+        self.movie_loader = QMovie(":/icons/loader")
+        self.label_loading = QLabel(parent)
+        self.label_loading.setMovie(self.movie_loader)
+        self.label_loading.setMaximumHeight(self.height())
+        self.movie_loader.setScaledSize(QSize(16, 16))
+        self.movie_loader.start()
+        self.movie_loader.setPaused(True)
+        self.addPermanentWidget(self.label_loading)
         self.addPermanentWidget(self.status_label, 2)
         self.addPermanentWidget(self.label_time)
         self.addPermanentWidget(self.combo_referential)
+
+    def start_loading(self):
+        self.movie_loader.setPaused(False)
+
+    def stop_loading(self):
+        self.movie_loader.setPaused(True)
diff --git a/src/sakia/services/blockchain.py b/src/sakia/services/blockchain.py
index a1659d3a..ac4aab31 100644
--- a/src/sakia/services/blockchain.py
+++ b/src/sakia/services/blockchain.py
@@ -60,6 +60,7 @@ class BlockchainService(QObject):
         if self._blockchain_processor.initialized(self.currency) and not self._update_lock:
             try:
                 self._update_lock = True
+                self.app.refresh_started.emit()
                 block_numbers = await self.new_blocks(network_blockstamp)
                 while block_numbers:
                     start = self.current_buid().number
@@ -92,6 +93,7 @@ class BlockchainService(QObject):
             except (NoPeerAvailable, DuniterError) as e:
                 self._logger.debug(str(e))
             finally:
+                self.app.refresh_finished.emit()
                 self._update_lock = False
 
     def current_buid(self):
-- 
GitLab