Skip to content
Snippets Groups Projects
Commit ac42df17 authored by inso's avatar inso
Browse files

Merge remote-tracking branch 'origin/vtexier' into dev

parents 13c4515c 8522e9ab
No related branches found
No related tags found
No related merge requests found
<RCC>
<qresource prefix="icons">
<file alias="network_icon">noun_21549_cc.svg</file>
<file alias="member_icon">iconmonstr-user-icon.svg</file>
<file alias="informations_icon">iconmonstr-info-2-icon.svg</file>
<file alias="community_icon">noun_22441_cc.svg</file>
<file alias="wot_icon">noun_2651_cc.svg</file>
......
......@@ -275,3 +275,6 @@ class Account(QObject):
'wallets': data_wallets,
'contacts': data_contacts}
return data
def get_person(self):
return Person(self.name, self.pubkey)
import logging
import copy
import time
import datetime
from cutecoin.core.person import Person
from cutecoin.gui.views.wot import NODE_STATUS_HIGHLIGHTED, NODE_STATUS_OUT, ARC_STATUS_STRONG, ARC_STATUS_WEAK
class Graph(dict):
def __init__(self, community):
"""
Init Graph instance
:param cutecoin.core.community.Community community:
:return:
"""
self.community = community
self.signature_validity = self.community.get_parameters()['sigValidity']
# arc considered strong during 75% of signature validity time
self.ARC_STATUS_STRONG_time = int(self.signature_validity * 0.75)
def get_shortest_path_between_members(self, from_person, to_person):
"""
Return path list of nodes from from_person to to_person
:param Person from_person:
:param Person to_person:
:return:
"""
path = list()
graph_tmp = copy.deepcopy(self)
logging.debug("path between %s to %s..." % (from_person.name, to_person.name))
if from_person.pubkey not in graph_tmp.keys():
graph_tmp.add_person(from_person)
certifier_list = from_person.certifiers_of(self.community)
graph_tmp.add_certifier_list(certifier_list, from_person, to_person)
certified_list = from_person.certified_by(self.community)
graph_tmp.add_certified_list(certified_list, from_person, to_person)
if to_person.pubkey not in graph_tmp.keys():
# recursively feed graph searching for account node...
graph_tmp.explore_to_find_member(to_person, graph_tmp[from_person.pubkey]['connected'], list())
if len(graph_tmp[from_person.pubkey]['connected']) > 0:
# calculate path of nodes between person and to_person
path = graph_tmp.find_shortest_path(graph_tmp[from_person.pubkey], graph_tmp[to_person.pubkey])
if path:
logging.debug([node['text'] for node in path])
else:
logging.debug('no wot path')
return path
def explore_to_find_member(self, person, connected=None, done=None):
"""
Scan graph recursively to find person
:param Person person: Person instance to find
:param list connected: Optional, default=None, Pubkey list of the connected nodes
around the current scanned node
:param list done: Optional, default=None, List of node already scanned
:return:
"""
# functions keywords args are persistent... Need to reset it with None trick
connected = connected or (list() and (connected is None))
done = done or (list() and (done is None))
logging.debug("search %s in " % person.name)
logging.debug([self[pubkey]['text'] for pubkey in connected])
# for each pubkey connected...
for pubkey in tuple(connected):
# capture node connected
node = self[pubkey]
if node['id'] in tuple(done):
continue
person_selected = Person(node['text'], node['id'])
certifier_list = person_selected.certifiers_of(self.community)
self.add_certifier_list(certifier_list, person_selected, person)
if person.pubkey in tuple(self.keys()):
return False
certified_list = person_selected.certified_by(self.community)
self.add_certified_list(certified_list, person_selected, person)
if person.pubkey in tuple(self.keys()):
return False
if node['id'] not in tuple(done):
done.append(node['id'])
if len(done) >= len(self):
return True
result = self.explore_to_find_member(person, self[person_selected.pubkey]['connected'], done)
if not result:
return False
return True
def find_shortest_path(self, start, end, path=None):
"""
Find recursively the shortest path between two nodes
:param dict start: Start node
:param dict end: End node
:param list path: Optional, default=None, List of nodes
:return:
"""
path = path or (list() and (path is None))
path = path + [start]
if start['id'] == end['id']:
return path
if start['id'] not in self.keys():
return None
shortest = None
for pubkey in tuple(self[start['id']]['connected']):
node = self[pubkey]
if node not in path:
newpath = self.find_shortest_path(node, end, path)
if newpath:
if not shortest or len(newpath) < len(shortest):
shortest = newpath
return shortest
def add_certifier_list(self, certifier_list, person, person_account):
"""
Add list of certifiers to graph
:param list certifier_list: List of certifiers from api
:param Person person: Person instance which is certified
:param Person person_account: Account person instance
:return:
"""
# add certifiers of uid
for certifier in tuple(certifier_list):
# add only valid certification...
if (time.time() - certifier['cert_time']['medianTime']) > self.signature_validity:
continue
# new node
if certifier['pubkey'] not in self.keys():
node_status = 0
if certifier['pubkey'] == person_account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if certifier['isMember'] is False:
node_status += NODE_STATUS_OUT
self[certifier['pubkey']] = {
'id': certifier['pubkey'],
'arcs': list(),
'text': certifier['uid'],
'tooltip': certifier['pubkey'],
'status': node_status,
'connected': [person.pubkey]
}
# keep only the latest certification
if self[certifier['pubkey']]['arcs']:
if certifier['cert_time']['medianTime'] < self[certifier['pubkey']]['arcs'][0]['cert_time']:
continue
# display validity status
if (time.time() - certifier['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time:
arc_status = ARC_STATUS_WEAK
else:
arc_status = ARC_STATUS_STRONG
arc = {
'id': person.pubkey,
'status': arc_status,
'tooltip': datetime.datetime.fromtimestamp(
certifier['cert_time']['medianTime'] + self.signature_validity
).strftime("%d/%m/%Y"),
'cert_time': certifier['cert_time']['medianTime']
}
# add arc to certifier
self[certifier['pubkey']]['arcs'].append(arc)
# if certifier node not in person nodes
if certifier['pubkey'] not in tuple(self[person.pubkey]['connected']):
# add certifier node to person node
self[person.pubkey]['connected'].append(certifier['pubkey'])
def add_certified_list(self, certified_list, person, person_account):
"""
Add list of certified from api to graph
:param list certified_list: List of certified from api
:param Person person: Person instance which is certifier
:param Person person_account: Account person instance
:return:
"""
# add certified by uid
for certified in tuple(certified_list):
# add only valid certification...
if (time.time() - certified['cert_time']['medianTime']) > self.signature_validity:
continue
if certified['pubkey'] not in self.keys():
node_status = 0
if certified['pubkey'] == person_account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if certified['isMember'] is False:
node_status += NODE_STATUS_OUT
self[certified['pubkey']] = {
'id': certified['pubkey'],
'arcs': list(),
'text': certified['uid'],
'tooltip': certified['pubkey'],
'status': node_status,
'connected': [person.pubkey]
}
# display validity status
if (time.time() - certified['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time:
arc_status = ARC_STATUS_WEAK
else:
arc_status = ARC_STATUS_STRONG
arc = {
'id': certified['pubkey'],
'status': arc_status,
'tooltip': datetime.datetime.fromtimestamp(
certified['cert_time']['medianTime'] + self.signature_validity
).strftime("%d/%m/%Y"),
'cert_time': certified['cert_time']['medianTime']
}
# replace old arc if this one is more recent
new_arc = True
index = 0
for a in self[person.pubkey]['arcs']:
# if same arc already exists...
if a['id'] == arc['id']:
# if arc more recent, dont keep old one...
if arc['cert_time'] >= a['cert_time']:
self[person.pubkey]['arcs'][index] = arc
new_arc = False
index += 1
# if arc not in graph...
if new_arc:
# add arc in graph
self[person.pubkey]['arcs'].append(arc)
# if certified node not in person nodes
if certified['pubkey'] not in tuple(self[person.pubkey]['connected']):
# add certified node to person node
self[person.pubkey]['connected'].append(certified['pubkey'])
def add_person(self, person, status=None, arcs=None, connected=None):
"""
Add person as a new node in graph
:param Person person: Person instance
:param int status: Optional, default=None, Node status (see cutecoin.gui.views.wot)
:param list arcs: Optional, default=None, List of arcs (certified by person)
:param list connected: Optional, default=None, Public key list of the connected nodes around the person
:return:
"""
# functions keywords args are persistent... Need to reset it with None trick
status = status or (0 and (status is None))
arcs = arcs or (list() and (arcs is None))
connected = connected or (list() and (connected is None))
self[person.pubkey] = {
'id': person.pubkey,
'arcs': arcs,
'text': person.name,
'tooltip': person.pubkey,
'status': status,
'connected': connected
}
......@@ -6,6 +6,7 @@ Created on 11 févr. 2014
import logging
import functools
import datetime
from ucoinpy.api import bma
from ucoinpy import PROTOCOL_VERSION
from ucoinpy.documents.certification import SelfCertification
......@@ -156,14 +157,28 @@ class Person(object):
signature)
raise PersonNotFoundError(self.pubkey, community.name())
def get_join_date(self, community):
try:
search = community.request(bma.blockchain.Membership, {'search': self.pubkey})
membership_data = None
if len(search['memberships']) > 0:
membership_data = search['memberships'][0]
return datetime.datetime.fromtimestamp(community.get_block(membership_data['blockNumber']).mediantime).strftime("%d/%m/%Y %I:%M")
else:
return None
except ValueError as e:
if '400' in str(e):
raise MembershipNotFoundError(self.pubkey, community.name())
@cached
def membership(self, community):
try:
search = community.request(bma.blockchain.Membership,
{'search': self.pubkey})
block_number = 0
block_number = -1
for ms in search['memberships']:
if ms['blockNumber'] >= block_number:
if ms['blockNumber'] > block_number:
block_number = ms['blockNumber']
if 'type' in ms:
if ms['type'] is 'IN':
membership_data = ms
......
......@@ -12,6 +12,7 @@ from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QMenu, QDialog, \
from ..models.members import MembersFilterProxyModel, MembersTableModel
from ..gen_resources.community_tab_uic import Ui_CommunityTabWidget
from cutecoin.gui.contact import ConfigureContactDialog
from cutecoin.gui.member import MemberDialog
from .wot_tab import WotTabWidget
from .transfer import TransferMoneyDialog
from .password_asker import PasswordAskerDialog
......@@ -64,6 +65,10 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
member = Person.lookup(pubkey, self.community)
menu = QMenu(self)
informations = QAction("Informations", self)
informations.triggered.connect(self.menu_informations)
informations.setData(member)
add_contact = QAction("Add as contact", self)
add_contact.triggered.connect(self.menu_add_as_contact)
add_contact.setData(member)
......@@ -80,6 +85,7 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
view_wot.triggered.connect(self.view_wot)
view_wot.setData(member)
menu.addAction(informations)
menu.addAction(add_contact)
menu.addAction(send_money)
menu.addAction(certify)
......@@ -88,6 +94,10 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
# Show the context menu.
menu.exec_(QCursor.pos())
def menu_informations(self):
person = self.sender().data()
self.member_informations(person)
def menu_add_as_contact(self):
person = self.sender().data()
self.add_member_as_contact(person)
......@@ -100,6 +110,10 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
person = self.sender().data()
self.certify_member(person)
def member_informations(self, person):
dialog = MemberDialog(self.account, self.community, person)
dialog.exec_()
def add_member_as_contact(self, person):
dialog = ConfigureContactDialog(self.account, self.window(), person)
result = dialog.exec_()
......
from cutecoin.core.graph import Graph
from PyQt5.QtWidgets import QDialog
from ..gen_resources.member_uic import Ui_DialogMember
class MemberDialog(QDialog, Ui_DialogMember):
"""
classdocs
"""
def __init__(self, account, community, person):
"""
Constructor
"""
super().__init__()
self.setupUi(self)
self.community = community
self.account = account
self.person = person
self.label_uid.setText(person.name)
join_date = self.person.get_join_date(self.community)
if join_date is None:
join_date = 'not a member'
# calculate path to account member
graph = Graph(self.community)
path = None
# if selected member is not the account member...
if person.pubkey != self.account.pubkey:
# add path from selected member to account member
path = graph.get_shortest_path_between_members(person, self.account.get_person())
text = """
<table cellpadding="5">
<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>
<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>
""".format(
'Public key',
self.person.pubkey,
'Join date',
join_date
)
if path:
distance = len(path) - 1
text += """<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""".format('Distance', distance)
if distance > 1:
index = 0
for node in path:
if index == 0:
text += """<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""".format('Path', node['text'])
else:
text += """<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""".format('', node['text'])
if index == distance and node['id'] != self.account.pubkey:
text += """<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""".format('', self.account.name)
index += 1
# close html text
text += "</table>"
# set text in label
self.label_properties.setText(text)
# -*- coding: utf-8 -*-
import math
from PyQt5.QtGui import QPainter, QBrush, QPen, QPolygonF, QColor, QRadialGradient,\
from PyQt5.QtGui import QPainter, QBrush, QPen, QPolygonF, QColor, QRadialGradient, \
QPainterPath, QMouseEvent, QWheelEvent, QTransform, QCursor
from PyQt5.QtCore import Qt, QRectF, QLineF, QPoint, QPointF, QSizeF, qFuzzyCompare, pyqtSignal
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsEllipseItem,\
QGraphicsSimpleTextItem, QGraphicsLineItem, QMenu, QAction, QGraphicsSceneHoverEvent,\
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsEllipseItem, \
QGraphicsSimpleTextItem, QGraphicsLineItem, QMenu, QAction, QGraphicsSceneHoverEvent, \
QGraphicsSceneContextMenuEvent
NODE_STATUS_HIGHLIGHTED = 1
......@@ -48,19 +48,19 @@ class WotView(QGraphicsView):
self.scale(sc, sc)
self.centerOn(self.mapToScene(event.pos()))
event.accept()
# act normally on scrollbar
# act normally on scrollbar
else:
# transmit event to parent class wheelevent
super(QGraphicsView, self).wheelEvent(event)
class Scene(QGraphicsScene):
# This defines signals taking string arguments
node_clicked = pyqtSignal(dict, name='nodeClicked')
node_signed = pyqtSignal(dict, name='nodeSigned')
node_transaction = pyqtSignal(dict, name='nodeTransaction')
node_contact = pyqtSignal(dict, name='nodeContact')
node_member = pyqtSignal(dict, name='nodeMember')
def __init__(self, parent=None):
"""
......@@ -73,7 +73,9 @@ class Scene(QGraphicsScene):
self.lastDragPos = QPoint()
self.setItemIndexMethod(QGraphicsScene.NoIndex)
# axis of the scene for debug purpose
# list of nodes in scene
self.nodes = dict()
# axis of the scene for debug purpose
# self.addLine(-100, 0, 100, 0)
# self.addLine(0, -100, 0, 100)
......@@ -88,6 +90,7 @@ class Scene(QGraphicsScene):
"""
node = Node(metadata, pos)
self.addItem(node)
self.nodes[node.id] = node
return node
def add_arc(self, source_node, destination_node, metadata):
......@@ -108,9 +111,9 @@ class Scene(QGraphicsScene):
"""
draw community graph
:param dict graph: graph to draw
:param cutecoin.core.graph.Graph graph: graph to draw
"""
# clear scene
# clear scene
self.clear()
# capture selected node (to draw it in the center)
......@@ -140,7 +143,8 @@ class Scene(QGraphicsScene):
y = 0
x = -200
# sort by text
nodes = ((k, v) for (k, v) in sorted(graph.items(), key=lambda kv: kv[1]['text'].lower()) if selected_id in (arc['id'] for arc in v['arcs']))
nodes = ((k, v) for (k, v) in sorted(graph.items(), key=lambda kv: kv[1]['text'].lower()) if
selected_id in (arc['id'] for arc in v['arcs']))
# add nodes and arcs
for _id, certifier_node in nodes:
node = self.add_node(certifier_node, (x, y))
......@@ -151,6 +155,31 @@ class Scene(QGraphicsScene):
self.update()
def update_path(self, path):
x = 0
y = 0
for json_node in path:
if json_node['status'] & NODE_STATUS_SELECTED:
previous_node = json_node
y -= 100
continue
node = self.add_node(json_node, (x, y))
skip_reverse_arc = False
for arc in json_node['arcs']:
if arc['id'] == previous_node['id']:
#print("arc from %s to %s" % (node.id, previous_node['id']))
self.add_arc(node, self.nodes[previous_node['id']], arc)
skip_reverse_arc = True
break
if not skip_reverse_arc:
for arc in previous_node['arcs']:
if arc['id'] == json_node['id']:
#print("arc from %s to %s" % (previous_node['id'], node.id))
self.add_arc(self.nodes[previous_node['id']], node, arc)
previous_node = json_node
y -= 100
class Node(QGraphicsEllipseItem):
def __init__(self, metadata, x_y):
......@@ -166,6 +195,7 @@ class Node(QGraphicsEllipseItem):
super(Node, self).__init__()
self.metadata = metadata
self.id = metadata['id']
self.status_wallet = self.metadata['status'] & NODE_STATUS_HIGHLIGHTED
self.status_member = not self.metadata['status'] & NODE_STATUS_OUT
self.text = self.metadata['text']
......@@ -175,6 +205,7 @@ class Node(QGraphicsEllipseItem):
self.action_sign = None
self.action_transaction = None
self.action_contact = None
self.action_show_member = None
# color around ellipse
outline_color = QColor('grey')
......@@ -185,7 +216,7 @@ class Node(QGraphicsEllipseItem):
outline_width = 2
if not self.status_member:
outline_color = QColor('red')
outline_style = Qt.DashLine
outline_style = Qt.SolidLine
self.setPen(QPen(outline_color, outline_width, outline_style))
# text inside ellipse
......@@ -203,10 +234,10 @@ class Node(QGraphicsEllipseItem):
self.text_item.boundingRect().height() * 2
)
# set anchor to the center
self.setTransform(QTransform().translate(-self.boundingRect().width()/2.0, -self.boundingRect().height()/2.0))
# set anchor to the center
self.setTransform(
QTransform().translate(-self.boundingRect().width() / 2.0, -self.boundingRect().height() / 2.0))
self.setPos(x, y)
#print(x, y)
# center text in ellipse
self.text_item.setPos(self.boundingRect().width() / 4.0, self.boundingRect().height() / 4.0)
......@@ -245,11 +276,15 @@ class Node(QGraphicsEllipseItem):
:param event: scene context menu event
"""
# no menu on the wallet node
# no menu on the wallet node
if self.status_wallet:
return None
# create node context menus
self.menu = QMenu()
# action show member
self.action_show_member = QAction('Informations', self.scene())
self.menu.addAction(self.action_show_member)
self.action_show_member.triggered.connect(self.member_action)
# action add identity as contact
self.action_contact = QAction('Add as contact', self.scene())
self.menu.addAction(self.action_contact)
......@@ -273,6 +308,20 @@ class Node(QGraphicsEllipseItem):
"""
self.arcs.append(arc)
def member_action(self):
"""
Transaction action to identity node
"""
# trigger scene signal
self.scene().node_member.emit(self.metadata)
def contact_action(self):
"""
Transaction action to identity node
"""
# trigger scene signal
self.scene().node_contact.emit(self.metadata)
def sign_action(self):
"""
Sign identity node
......@@ -287,12 +336,6 @@ class Node(QGraphicsEllipseItem):
# trigger scene signal
self.scene().node_transaction.emit(self.metadata)
def contact_action(self):
"""
Transaction action to identity node
"""
# trigger scene signal
self.scene().node_contact.emit(self.metadata)
class Arc(QGraphicsLineItem):
def __init__(self, source_node, destination_node, metadata):
......@@ -319,7 +362,7 @@ class Arc(QGraphicsLineItem):
self.setAcceptedMouseButtons(Qt.NoButton)
# cursor change on hover
# cursor change on hover
self.setAcceptHoverEvents(True)
self.adjust()
self.setZValue(0)
......@@ -405,11 +448,9 @@ class Arc(QGraphicsLineItem):
if line.dy() >= 0:
angle = (2.0 * math.pi) - angle
# arrow in the middle of the arc
hpx = (line.p2().x() + line.p1().x()) / 2.0
hpy = (line.p2().y() - line.p1().y()) / 2.0
if line.dy() < 0:
hpy = -hpy
# arrow in the middle of the arc
hpx = line.p1().x() + (line.dx() / 2.0)
hpy = line.p1().y() + (line.dy() / 2.0)
head_point = QPointF(hpx, hpy)
painter.setPen(QPen(color, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
......@@ -440,17 +481,17 @@ class Arc(QGraphicsLineItem):
# detection mouse hover on arc path
path = QPainterPath()
path.addPolygon(QPolygonF([self.line().p1(), self.line().p2()]))
# add handles at the start and end of arc
# add handles at the start and end of arc
path.addRect(QRectF(
self.line().p1().x()-5,
self.line().p1().y()-5,
self.line().p1().x()+5,
self.line().p1().y()+5
self.line().p1().x() - 5,
self.line().p1().y() - 5,
self.line().p1().x() + 5,
self.line().p1().y() + 5
))
path.addRect(QRectF(
self.line().p2().x()-5,
self.line().p2().y()-5,
self.line().p2().x()+5,
self.line().p2().y()+5
self.line().p2().x() - 5,
self.line().p2().y() - 5,
self.line().p2().x() + 5,
self.line().p2().y() + 5
))
return path
# -*- coding: utf-8 -*-
import time
import datetime
import logging
from PyQt5.QtWidgets import QWidget, QComboBox, QDialog
from cutecoin.core.graph import Graph
from PyQt5.QtWidgets import QWidget, QComboBox
from ..gen_resources.wot_tab_uic import Ui_WotTabWidget
from cutecoin.gui.views.wot import NODE_STATUS_HIGHLIGHTED, NODE_STATUS_SELECTED, NODE_STATUS_OUT, ARC_STATUS_STRONG, ARC_STATUS_WEAK
from ucoinpy.api import bma
from .certification import CertificationDialog
from cutecoin.gui.contact import ConfigureContactDialog
from .transfer import TransferMoneyDialog
from cutecoin.core.person import Person
def get_person_from_metadata(metadata):
return Person(metadata['text'], metadata['id'])
class WotTabWidget(QWidget, Ui_WotTabWidget):
def __init__(self, account, community, password_asker, parent=None):
"""
......@@ -39,6 +39,7 @@ class WotTabWidget(QWidget, Ui_WotTabWidget):
self.graphicsView.scene().node_signed.connect(self.sign_node)
self.graphicsView.scene().node_transaction.connect(self.send_money_to_node)
self.graphicsView.scene().node_contact.connect(self.add_node_as_contact)
self.graphicsView.scene().node_member.connect(self.member_informations)
self.account = account
self.community = community
......@@ -46,9 +47,6 @@ class WotTabWidget(QWidget, Ui_WotTabWidget):
# nodes list for menu from search
self.nodes = list()
self.signature_validity = self.community.get_parameters()['sigValidity']
# arc considered strong during 75% of signature validity time
self.ARC_STATUS_STRONG_time = int(self.signature_validity * 0.75)
# create node metadata from account
metadata = {'text': self.account.name, 'id': self.account.pubkey}
......@@ -60,121 +58,41 @@ class WotTabWidget(QWidget, Ui_WotTabWidget):
:param dict metadata: Graph node metadata of the identity
"""
logging.debug("Draw graph - " + metadata['text'])
# create Person from node metadata
person = self.get_person_from_metadata(metadata)
certifiers = person.certifiers_of(self.community)
person = get_person_from_metadata(metadata)
person_account = Person(self.account.name, self.account.pubkey)
certifier_list = person.certifiers_of(self.community)
certified_list = person.certified_by(self.community)
# reset graph
graph = dict()
# create empty graph instance
graph = Graph(self.community)
# add wallet node
node_status = 0
if person.pubkey == self.account.pubkey:
if person.pubkey == person_account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if person.is_member(self.community) is False:
node_status += NODE_STATUS_OUT
node_status += NODE_STATUS_SELECTED
graph.add_person(person, node_status)
# center node
graph[person.pubkey] = {
'id': person.pubkey,
'arcs': list(),
'text': person.name,
'tooltip': person.pubkey,
'status': node_status
}
# add certifiers of uid
for certifier in certifiers:
# new node
if certifier['pubkey'] not in graph.keys():
node_status = 0
if certifier['pubkey'] == self.account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if certifier['isMember'] is False:
node_status += NODE_STATUS_OUT
graph[certifier['pubkey']] = {
'id': certifier['pubkey'],
'arcs': list(),
'text': certifier['uid'],
'tooltip': certifier['pubkey'],
'status': node_status
}
# add only valid certification...
if (time.time() - certifier['cert_time']['medianTime']) > self.signature_validity:
continue
# keep only the latest certification
if graph[certifier['pubkey']]['arcs']:
if certifier['cert_time']['medianTime'] < graph[certifier['pubkey']]['arcs'][0]['cert_time']:
continue
# display validity status
if (time.time() - certifier['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time:
arc_status = ARC_STATUS_WEAK
else:
arc_status = ARC_STATUS_STRONG
arc = {
'id': person.pubkey,
'status': arc_status,
'tooltip': datetime.datetime.fromtimestamp(
certifier['cert_time']['medianTime'] + self.signature_validity
).strftime("%d/%m/%Y"),
'cert_time': certifier['cert_time']['medianTime']
}
graph[certifier['pubkey']]['arcs'] = [arc]
# add certified by uid
for certified in person.certified_by(self.community):
if certified['pubkey'] not in graph.keys():
node_status = 0
if certified['pubkey'] == self.account.pubkey:
node_status += NODE_STATUS_HIGHLIGHTED
if certified['isMember'] is False:
node_status += NODE_STATUS_OUT
graph[certified['pubkey']] = {
'id': certified['pubkey'],
'arcs': list(),
'text': certified['uid'],
'tooltip': certified['pubkey'],
'status': node_status
}
# add only valid certification...
if (time.time() - certified['cert_time']['medianTime']) > self.signature_validity:
continue
# display validity status
if (time.time() - certified['cert_time']['medianTime']) > self.ARC_STATUS_STRONG_time:
arc_status = ARC_STATUS_WEAK
else:
arc_status = ARC_STATUS_STRONG
arc = {
'id': certified['pubkey'],
'status': arc_status,
'tooltip': datetime.datetime.fromtimestamp(
certified['cert_time']['medianTime'] + self.signature_validity
).strftime("%d/%m/%Y"),
'cert_time': certified['cert_time']['medianTime']
}
# replace old arc if this one is more recent
new_arc = True
index = 0
for a in graph[person.pubkey]['arcs']:
# if same arc already exists...
if a['id'] == arc['id']:
# if arc more recent, dont keep old one...
if arc['cert_time'] >= a['cert_time']:
graph[person.pubkey]['arcs'][index] = arc
new_arc = False
index += 1
# if arc not in graph...
if new_arc:
# add arc in graph
graph[person.pubkey]['arcs'].append(arc)
# populate graph with certifiers-of
graph.add_certifier_list(certifier_list, person, person_account)
# populate graph with certified-by
graph.add_certified_list(certified_list, person, person_account)
# draw graph in qt scene
self.graphicsView.scene().update_wot(graph)
# if selected member is not the account member...
if person.pubkey != person_account.pubkey:
# add path from selected member to account member
path = graph.get_shortest_path_between_members(person, person_account)
if path:
self.graphicsView.scene().update_path(path)
def reset(self):
"""
Reset graph scene to wallet identity
......@@ -211,13 +129,6 @@ class WotTabWidget(QWidget, Ui_WotTabWidget):
self.comboBoxSearch.addItem(uid)
self.comboBoxSearch.showPopup()
if len(nodes) == 1:
node = self.nodes[0]
metadata = {'id': node['pubkey'], 'text': node['uid']}
self.draw_graph(
metadata
)
def select_node(self, index):
"""
Select node in graph when item is selected in combobox
......@@ -230,19 +141,23 @@ class WotTabWidget(QWidget, Ui_WotTabWidget):
metadata
)
def member_informations(self, metadata):
person = get_person_from_metadata(metadata)
self.parent.member_informations(person)
def sign_node(self, metadata):
person = self.get_person_from_metadata(metadata)
person = get_person_from_metadata(metadata)
self.parent.certify_member(person)
def send_money_to_node(self, metadata):
person = self.get_person_from_metadata(metadata)
person = get_person_from_metadata(metadata)
self.parent.send_money_to_member(person)
def add_node_as_contact(self, metadata):
# check if contact already exists...
if metadata['id'] == self.account.pubkey or metadata['id'] in [contact.pubkey for contact in self.account.contacts]:
return False
person = self.get_person_from_metadata(metadata)
person = get_person_from_metadata(metadata)
self.parent.add_member_as_contact(person)
def get_block_mediantime(self, number):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment