From 53d69141010b3a5707e6141dccb82759d7091ef6 Mon Sep 17 00:00:00 2001
From: inso <insomniak.fr@gmaiL.com>
Date: Mon, 8 Aug 2016 19:00:21 +0200
Subject: [PATCH] New explorer component
---
src/sakia/gui/graphs/explorer/__init__.py | 0
src/sakia/gui/graphs/explorer/controller.py | 75 +++++++++++
.../explorer_edge.py => explorer/edge.py} | 2 +-
.../sakia/gui/graphs/explorer/explorer.ui | 12 +-
.../explorer.py => explorer/graphics_view.py} | 14 +-
src/sakia/gui/graphs/explorer/model.py | 54 ++++++++
.../explorer_node.py => explorer/node.py} | 2 +-
.../explorer_scene.py => explorer/scene.py} | 6 +-
src/sakia/gui/graphs/explorer/view.py | 54 ++++++++
src/sakia/gui/graphs/explorer_tab.py | 124 ------------------
src/sakia/gui/graphs/views/__init__.py | 2 -
src/sakia/gui/graphs/views/edges/__init__.py | 2 -
src/sakia/gui/graphs/views/nodes/__init__.py | 2 -
src/sakia/gui/graphs/views/scenes/__init__.py | 2 -
src/sakia/gui/informations/controller.py | 10 +-
src/sakia/gui/navigation/controller.py | 4 +-
src/sakia/gui/navigation/model.py | 8 ++
src/sakia/gui/txhistory/model.py | 1 +
18 files changed, 217 insertions(+), 157 deletions(-)
create mode 100644 src/sakia/gui/graphs/explorer/__init__.py
create mode 100644 src/sakia/gui/graphs/explorer/controller.py
rename src/sakia/gui/graphs/{views/edges/explorer_edge.py => explorer/edge.py} (99%)
rename res/ui/explorer_tab.ui => src/sakia/gui/graphs/explorer/explorer.ui (87%)
rename src/sakia/gui/graphs/{views/explorer.py => explorer/graphics_view.py} (81%)
create mode 100644 src/sakia/gui/graphs/explorer/model.py
rename src/sakia/gui/graphs/{views/nodes/explorer_node.py => explorer/node.py} (99%)
rename src/sakia/gui/graphs/{views/scenes/explorer_scene.py => explorer/scene.py} (99%)
create mode 100644 src/sakia/gui/graphs/explorer/view.py
delete mode 100644 src/sakia/gui/graphs/explorer_tab.py
delete mode 100644 src/sakia/gui/graphs/views/__init__.py
delete mode 100644 src/sakia/gui/graphs/views/edges/__init__.py
delete mode 100644 src/sakia/gui/graphs/views/nodes/__init__.py
delete mode 100644 src/sakia/gui/graphs/views/scenes/__init__.py
diff --git a/src/sakia/gui/graphs/explorer/__init__.py b/src/sakia/gui/graphs/explorer/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/sakia/gui/graphs/explorer/controller.py b/src/sakia/gui/graphs/explorer/controller.py
new file mode 100644
index 00000000..e116ab34
--- /dev/null
+++ b/src/sakia/gui/graphs/explorer/controller.py
@@ -0,0 +1,75 @@
+from ..base.controller import BaseGraphController
+from sakia.tools.decorators import asyncify, once_at_a_time
+from .view import ExplorerView
+from .model import ExplorerModel
+
+
+class ExplorerController(BaseGraphController):
+ """
+ The homescreen view
+ """
+
+ def __init__(self, parent, view, model, password_asker=None):
+ """
+ Constructor of the explorer component
+
+ :param sakia.gui.graphs.explorer.view.ExplorerView: the view
+ :param sakia.gui.graphs.explorer.model.ExplorerModel model: the model
+ """
+ super().__init__(parent, view, model, password_asker)
+ self.set_scene(view.scene())
+ self.reset()
+ self.view.button_go.clicked.connect(self.refresh)
+
+ @property
+ def view(self) -> ExplorerView:
+ return self._view
+
+ @property
+ def model(self) -> ExplorerModel:
+ return self._model
+
+ @classmethod
+ def create(cls, parent, app, **kwargs):
+ account = kwargs['account']
+ community = kwargs['community']
+
+ view = ExplorerView(parent.view)
+ model = ExplorerModel(None, app, account, community)
+ wot = cls(parent, view, model)
+ model.setParent(wot)
+ return wot
+
+ async def draw_graph(self, identity):
+ """
+ Draw community graph centered on the identity
+
+ :param sakia.core.registry.Identity identity: Center identity
+ """
+ await self.model.set_identity(identity)
+ self.model.graph.start_exploration(self.model.identity, self.view.steps())
+
+ # draw graph in qt scene
+ self.view.scene().clear()
+ self.view.update_wot(self.model.graph.nx_graph, self.model.identity)
+
+ @once_at_a_time
+ @asyncify
+ async def refresh(self):
+ """
+ Refresh graph scene to current metadata
+ """
+ self.model.graph.stop_exploration()
+ self.draw_graph(self.model.identity)
+ self.view.update_wot(self.model.graph.nx_graph, self.model.identity)
+
+ @once_at_a_time
+ @asyncify
+ async def reset(self, checked=False):
+ """
+ Reset graph scene to wallet identity
+ """
+ self.view.reset_steps()
+ maximum_steps = await self.model.maximum_steps()
+ self.view.set_steps_max(maximum_steps)
+ await self.draw_graph(None)
diff --git a/src/sakia/gui/graphs/views/edges/explorer_edge.py b/src/sakia/gui/graphs/explorer/edge.py
similarity index 99%
rename from src/sakia/gui/graphs/views/edges/explorer_edge.py
rename to src/sakia/gui/graphs/explorer/edge.py
index 6f39bea9..93584049 100644
--- a/src/sakia/gui/graphs/views/edges/explorer_edge.py
+++ b/src/sakia/gui/graphs/explorer/edge.py
@@ -2,7 +2,7 @@ from PyQt5.QtCore import Qt, QRectF, QLineF, QPointF, QSizeF, \
qFuzzyCompare, QTimeLine
from PyQt5.QtGui import QColor, QPen, QPolygonF
import math
-from .base_edge import BaseEdge
+from ..base.edge import BaseEdge
from ....core.graph.constants import EdgeStatus
diff --git a/res/ui/explorer_tab.ui b/src/sakia/gui/graphs/explorer/explorer.ui
similarity index 87%
rename from res/ui/explorer_tab.ui
rename to src/sakia/gui/graphs/explorer/explorer.ui
index 58aa9891..9b3c7087 100644
--- a/res/ui/explorer_tab.ui
+++ b/src/sakia/gui/graphs/explorer/explorer.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>ExplorerTabWidget</class>
- <widget class="QWidget" name="ExplorerTabWidget">
+ <class>ExplorerWidget</class>
+ <widget class="QWidget" name="ExplorerWidget">
<property name="geometry">
<rect>
<x>0</x>
@@ -18,7 +18,7 @@
<widget class="SearchUserWidget" name="search_user_widget" native="true"/>
</item>
<item>
- <widget class="ExplorerView" name="graphicsView">
+ <widget class="ExplorerGraphicsView" name="graphics_view">
<property name="viewportUpdateMode">
<enum>QGraphicsView::BoundingRectViewportUpdate</enum>
</property>
@@ -72,9 +72,9 @@
</widget>
<customwidgets>
<customwidget>
- <class>ExplorerView</class>
+ <class>ExplorerGraphicsView</class>
<extends>QGraphicsView</extends>
- <header>sakia.gui.views</header>
+ <header>sakia.gui.graphs.explorer.graphics_view</header>
</customwidget>
<customwidget>
<class>SearchUserWidget</class>
@@ -84,7 +84,7 @@
</customwidget>
</customwidgets>
<resources>
- <include location="../icons/icons.qrc"/>
+ <include location="../../../../../res/icons/icons.qrc"/>
</resources>
<connections/>
<slots>
diff --git a/src/sakia/gui/graphs/views/explorer.py b/src/sakia/gui/graphs/explorer/graphics_view.py
similarity index 81%
rename from src/sakia/gui/graphs/views/explorer.py
rename to src/sakia/gui/graphs/explorer/graphics_view.py
index 927d9f08..3229282c 100644
--- a/src/sakia/gui/graphs/views/explorer.py
+++ b/src/sakia/gui/graphs/explorer/graphics_view.py
@@ -1,14 +1,10 @@
-import logging
-
-import networkx
-from PyQt5.QtCore import Qt, QPoint, pyqtSignal
+from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QWheelEvent
-from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene
-
-from .scenes import ExplorerScene
+from PyQt5.QtWidgets import QGraphicsView
+from .scene import ExplorerScene
-class ExplorerView(QGraphicsView):
+class ExplorerGraphicsView(QGraphicsView):
def __init__(self, parent=None):
"""
Create View to display scene
@@ -44,4 +40,4 @@ class ExplorerView(QGraphicsView):
# act normally on scrollbar
else:
# transmit event to parent class wheelevent
- super(QGraphicsView, self).wheelEvent(event)
+ super().wheelEvent(event)
\ No newline at end of file
diff --git a/src/sakia/gui/graphs/explorer/model.py b/src/sakia/gui/graphs/explorer/model.py
new file mode 100644
index 00000000..02879cd2
--- /dev/null
+++ b/src/sakia/gui/graphs/explorer/model.py
@@ -0,0 +1,54 @@
+from ..base.model import BaseGraphModel
+from sakia.core.graph import ExplorerGraph
+from sakia.tools.exceptions import NoPeerAvailable
+
+
+class ExplorerModel(BaseGraphModel):
+ """
+ The model of Navigation component
+ """
+
+ def __init__(self, parent, app, account, community):
+ super().__init__(parent, app, account, community)
+ self.app = app
+ self.account = account
+ self.community = community
+ self.explorer_graph = ExplorerGraph(self.app, self.community)
+ self.identity = None
+
+ @property
+ def graph(self):
+ """
+ Return underlying graph object
+ """
+ return self.explorer_graph
+
+ async def set_identity(self, identity=None):
+ """
+ Change current identity
+ If identity is None, it defaults to account identity
+ :param sakia.core.registry.Identity identity: the new identity to show
+ :return:
+ """
+ identity_account = await self.account.identity(self.community)
+ if identity:
+ self.identity = identity
+ else:
+ self.identity = identity_account
+
+ async def start_exploration(self, steps):
+ """
+ Get nx graph of current identity wot graph
+ :rtype: sakia.core.registry.Identity
+ """
+ return self.explorer_graph.start_exploration(self.identity, steps)
+
+ async def maximum_steps(self):
+ """
+ Get the maximum steps to display in the view
+ """
+ try:
+ parameters = await self.community.parameters()
+ return parameters['stepMax']
+ except NoPeerAvailable:
+ return 0
diff --git a/src/sakia/gui/graphs/views/nodes/explorer_node.py b/src/sakia/gui/graphs/explorer/node.py
similarity index 99%
rename from src/sakia/gui/graphs/views/nodes/explorer_node.py
rename to src/sakia/gui/graphs/explorer/node.py
index 854d1e8f..1be84d23 100644
--- a/src/sakia/gui/graphs/views/nodes/explorer_node.py
+++ b/src/sakia/gui/graphs/explorer/node.py
@@ -2,7 +2,7 @@ from PyQt5.QtWidgets import QGraphicsSimpleTextItem
from PyQt5.QtCore import Qt, QPointF, QTimeLine, QTimer
from PyQt5.QtGui import QTransform, QColor, QPen, QBrush, QRadialGradient
from ....core.graph.constants import NodeStatus
-from .base_node import BaseNode
+from ..base.node import BaseNode
import math
diff --git a/src/sakia/gui/graphs/views/scenes/explorer_scene.py b/src/sakia/gui/graphs/explorer/scene.py
similarity index 99%
rename from src/sakia/gui/graphs/views/scenes/explorer_scene.py
rename to src/sakia/gui/graphs/explorer/scene.py
index 11b8511c..1036bc38 100644
--- a/src/sakia/gui/graphs/views/scenes/explorer_scene.py
+++ b/src/sakia/gui/graphs/explorer/scene.py
@@ -4,10 +4,10 @@ import math
from PyQt5.QtCore import QPoint, pyqtSignal
from PyQt5.QtWidgets import QGraphicsScene
-from ..edges import ExplorerEdge
-from ..nodes import ExplorerNode
+from .edge import ExplorerEdge
+from .node import ExplorerNode
-from .base_scene import BaseScene
+from ..base.scene import BaseScene
class ExplorerScene(BaseScene):
diff --git a/src/sakia/gui/graphs/explorer/view.py b/src/sakia/gui/graphs/explorer/view.py
new file mode 100644
index 00000000..7157e74f
--- /dev/null
+++ b/src/sakia/gui/graphs/explorer/view.py
@@ -0,0 +1,54 @@
+from PyQt5.QtCore import QEvent
+from ..base.view import BaseGraphView
+from .explorer_uic import Ui_ExplorerWidget
+
+
+class ExplorerView(BaseGraphView, Ui_ExplorerWidget):
+ """
+ Wot graph view
+ """
+
+ def __init__(self, parent):
+ """
+ Constructor
+ """
+ super().__init__(parent)
+ self.setupUi(self)
+
+ def set_steps_max(self, maximum):
+ """
+ Set the steps slider max value
+ :param int maximum: the max value
+ """
+ self.steps_slider.setMaximum(maximum)
+
+ def scene(self):
+ """
+ Get the scene of the underlying graphics view
+ :return:
+ """
+ return self.graphics_view.scene()
+
+ def reset_steps(self):
+ """
+ Reset the steps slider
+ """
+ self.steps_slider.setValue(0)
+
+ def steps(self):
+ """
+ Get the number of steps selected
+ :return:
+ """
+ return self.steps_slider.value()
+
+ def update_wot(self, nx_graph, identity):
+ """
+ Display given wot around given identity
+ :param nx_graph:
+ :param identity:
+ :param steps:
+ :return:
+ """
+ # draw graph in qt scene
+ self.scene().update_wot(nx_graph, identity, self.steps_slider.maximum())
diff --git a/src/sakia/gui/graphs/explorer_tab.py b/src/sakia/gui/graphs/explorer_tab.py
deleted file mode 100644
index 66ac4c7b..00000000
--- a/src/sakia/gui/graphs/explorer_tab.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import logging
-
-from PyQt5.QtCore import QEvent, pyqtSignal
-from PyQt5.QtWidgets import QWidget
-
-from ...tools.exceptions import NoPeerAvailable
-from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task
-from ...core.graph import ExplorerGraph
-from .graph_tab import GraphTabWidget
-from ...presentation.explorer_tab_uic import Ui_ExplorerTabWidget
-
-
-class ExplorerTabWidget(GraphTabWidget, Ui_ExplorerTabWidget):
-
- money_sent = pyqtSignal()
-
- def __init__(self, app, account=None, community=None, password_asker=None,
- widget=QWidget, view=Ui_ExplorerTabWidget):
- """
- :param sakia.core.app.Application app: Application instance
- :param sakia.core.app.Application app: Application instance
- :param sakia.core.Account account: The account displayed in the widget
- :param sakia.core.Community community: The community displayed in the widget
- :param sakia.gui.Password_Asker: password_asker: The widget to ask for passwords
- """
- # construct from qtDesigner
- super().__init__(app, account, community, password_asker, widget)
- self.ui = view()
- self.ui.setupUi(self.widget)
- self.ui.search_user_widget.init(app)
-
- self.set_scene(self.ui.graphicsView.scene())
- self.graph = None
- self.app = app
- self.draw_task = None
-
- # nodes list for menu from search
- self.nodes = list()
-
- # create node metadata from account
- self._current_identity = None
- self.ui.button_go.clicked.connect(self.go_clicked)
- self.ui.search_user_widget.identity_selected.connect(self.draw_graph)
- self.ui.search_user_widget.reset.connect(self.reset)
-
- def cancel_once_tasks(self):
- cancel_once_task(self, self.refresh_informations_frame)
- cancel_once_task(self, self.reset)
-
- def change_account(self, account, password_asker):
- self.ui.search_user_widget.change_account(account)
- self.account = account
- self.password_asker = password_asker
-
- def change_community(self, community):
- self.community = community
- if self.graph:
- self.graph.stop_exploration()
- self.graph = ExplorerGraph(self.app, self.community)
- self.graph.graph_changed.connect(self.refresh)
- self.ui.search_user_widget.change_community(community)
- self.graph.current_identity_changed.connect(self.ui.graphicsView.scene().update_current_identity)
- self.reset()
-
- def go_clicked(self):
- if self.graph:
- self.graph.stop_exploration()
- self.draw_graph(self._current_identity)
-
- def draw_graph(self, identity):
- """
- Draw community graph centered on the identity
-
- :param sakia.core.registry.Identity identity: Graph node identity
- """
- logging.debug("Draw graph - " + identity.uid)
-
- if self.community:
- #Connect new identity
- if self._current_identity != identity:
- self._current_identity = identity
-
- self.graph.start_exploration(identity, self.ui.steps_slider.value())
-
- # draw graph in qt scene
- self.ui.graphicsView.scene().clear()
- self.ui.graphicsView.scene().update_wot(self.graph.nx_graph, identity, self.ui.steps_slider.maximum())
-
- def refresh(self):
- """
- Refresh graph scene to current metadata
- """
- if self._current_identity:
- # draw graph in qt scene
- self.ui.graphicsView.scene().update_wot(self.graph.nx_graph, self._current_identity, self.ui.steps_slider.maximum())
- else:
- self.reset()
-
- @once_at_a_time
- @asyncify
- async def reset(self, checked=False):
- """
- Reset graph scene to wallet identity
- """
- if self.account and self.community:
- try:
- parameters = await self.community.parameters()
- self.ui.steps_slider.setMaximum(parameters['stepMax'])
- self.ui.steps_slider.setValue(int(0.33 * parameters['stepMax']))
- identity = await self.account.identity(self.community)
- self.draw_graph(identity)
- except NoPeerAvailable:
- logging.debug("No peer available")
-
- def changeEvent(self, event):
- """
- Intercepte LanguageChange event to translate UI
- :param QEvent QEvent: Event
- :return:
- """
- if event.type() == QEvent.LanguageChange:
- self.retranslateUi(self)
- self.refresh()
- return super().changeEvent(event)
diff --git a/src/sakia/gui/graphs/views/__init__.py b/src/sakia/gui/graphs/views/__init__.py
deleted file mode 100644
index 3ca1e9f7..00000000
--- a/src/sakia/gui/graphs/views/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .explorer import ExplorerView
-from .wot import WotView
\ No newline at end of file
diff --git a/src/sakia/gui/graphs/views/edges/__init__.py b/src/sakia/gui/graphs/views/edges/__init__.py
deleted file mode 100644
index 188e3acf..00000000
--- a/src/sakia/gui/graphs/views/edges/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .wot_edge import WotEdge
-from .explorer_edge import ExplorerEdge
\ No newline at end of file
diff --git a/src/sakia/gui/graphs/views/nodes/__init__.py b/src/sakia/gui/graphs/views/nodes/__init__.py
deleted file mode 100644
index 28332381..00000000
--- a/src/sakia/gui/graphs/views/nodes/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .wot_node import WotNode
-from .explorer_node import ExplorerNode
\ No newline at end of file
diff --git a/src/sakia/gui/graphs/views/scenes/__init__.py b/src/sakia/gui/graphs/views/scenes/__init__.py
deleted file mode 100644
index f2eef13e..00000000
--- a/src/sakia/gui/graphs/views/scenes/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .wot_scene import WotScene
-from .explorer_scene import ExplorerScene
\ No newline at end of file
diff --git a/src/sakia/gui/informations/controller.py b/src/sakia/gui/informations/controller.py
index a54b5581..df4eab85 100644
--- a/src/sakia/gui/informations/controller.py
+++ b/src/sakia/gui/informations/controller.py
@@ -2,7 +2,8 @@ from ..component.controller import ComponentController
from .model import InformationsModel
from .view import InformationsView
from sakia.tools.decorators import asyncify
-
+from sakia.tools.exceptions import NoPeerAvailable
+import logging
class InformationsController(ComponentController):
"""
@@ -55,9 +56,10 @@ class InformationsController(ComponentController):
self.view.set_general_text_no_dividend()
self.view.set_text_referentials(referentials)
params = await self.model.parameters()
- self.view.set_money_text(params, self.model.short_currency())
- self.view.set_wot_text(params)
- self.refresh_localized_data()
+ if params:
+ self.view.set_money_text(params, self.model.short_currency())
+ self.view.set_wot_text(params)
+ self.refresh_localized_data()
@asyncify
async def refresh_localized_data(self):
diff --git a/src/sakia/gui/navigation/controller.py b/src/sakia/gui/navigation/controller.py
index c09825c3..ac01f3bb 100644
--- a/src/sakia/gui/navigation/controller.py
+++ b/src/sakia/gui/navigation/controller.py
@@ -7,6 +7,7 @@ from ..network.controller import NetworkController
from ..identities.controller import IdentitiesController
from ..informations.controller import InformationsController
from ..graphs.wot.controller import WotController
+from ..graphs.explorer.controller import ExplorerController
class NavigationController(ComponentController):
@@ -28,7 +29,8 @@ class NavigationController(ComponentController):
'Network': NetworkController,
'Identities': IdentitiesController,
'Informations': InformationsController,
- 'Wot': WotController
+ 'Wot': WotController,
+ 'Explorer': ExplorerController
}
@classmethod
diff --git a/src/sakia/gui/navigation/model.py b/src/sakia/gui/navigation/model.py
index 0d59fe1d..166e625d 100644
--- a/src/sakia/gui/navigation/model.py
+++ b/src/sakia/gui/navigation/model.py
@@ -69,6 +69,14 @@ class NavigationModel(ComponentModel):
'community': c,
'account': self.app.current_account
}
+ },
+ {
+ 'node': {
+ 'title': self.tr('Explorer'),
+ 'component': "Explorer",
+ 'community': c,
+ 'account': self.app.current_account
+ }
}
]
})
diff --git a/src/sakia/gui/txhistory/model.py b/src/sakia/gui/txhistory/model.py
index fd6bf345..c516b4d6 100644
--- a/src/sakia/gui/txhistory/model.py
+++ b/src/sakia/gui/txhistory/model.py
@@ -96,6 +96,7 @@ class TxHistoryModel(ComponentModel):
logging.debug(str(e))
except errors.DuniterError as e:
logging.debug(str(e))
+ return QDateTime().currentDateTime(), QDateTime.currentDateTime().addDays(1)
async def received_amount(self, received_list):
"""
--
GitLab