Newer
Older
from PyQt5.QtWidgets import QWidget, QComboBox, QDialog
from PyQt5.QtCore import pyqtSlot, QEvent, QLocale, QDateTime, pyqtSignal
from ..tools.exceptions import MembershipNotFoundError
from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task
from ..core.graph import Graph
from ..core.registry import BlockchainState
from .member import MemberDialog
from .certification import CertificationDialog
from .transfer import TransferMoneyDialog
from .contact import ConfigureContactDialog
from cutecoin.gui.views.wot import NODE_STATUS_HIGHLIGHTED, NODE_STATUS_SELECTED, NODE_STATUS_OUT
from cutecoin.gui.widgets.busy import Busy
:param cutecoin.core.app.Application app: Application instance
# construct from qtDesigner
self.setupUi(self)
# Default text when combo lineEdit is empty
self.comboBoxSearch.lineEdit().setPlaceholderText(self.tr('Research a pubkey, an uid...'))
# add combobox events

Vincent Texier
committed
self.comboBoxSearch.lineEdit().returnPressed.connect(self.search)
# To fix a recall of the same item with different case,
# the edited text is not added in the item list
self.comboBoxSearch.setInsertPolicy(QComboBox.NoInsert)
self.busy = Busy(self.graphicsView)
self.busy.hide()
self.graphicsView.scene().node_clicked.connect(self.handle_node_click)
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.identity_informations)
self.graphicsView.scene().node_copy_pubkey.connect(self.copy_node_pubkey)
self.account = None
self.community = None
self.password_asker = None
# nodes list for menu from search
self.nodes = list()
# create node metadata from account
def cancel_once_tasks(self):
cancel_once_task(self, self.draw_graph)
cancel_once_task(self, self.refresh_informations_frame)
cancel_once_task(self, self.reset)
def change_account(self, account, password_asker):
self.password_asker = password_asker
def change_community(self, community):
self.community = community
self.reset()
def _auto_refresh(self, new_community):
if self.community:
try:
self.community.network.new_block_mined.disconnect(self.refresh)
except TypeError as e:
if "connected" in str(e):
logging.debug("new block mined not connected")
if self.app.preferences["auto_refresh"]:
if new_community:
new_community.network.new_block_mined.connect(self.refresh)
elif self.community:
self.community.network.new_block_mined.connect(self.refresh)
def refresh_informations_frame(self):
parameters = self.community.parameters
try:
identity = yield from self.account.identity(self.community)
membership = identity.membership(self.community)
renew_block = membership['blockNumber']
last_renewal = self.community.get_block(renew_block)['medianTime']
expiration = last_renewal + parameters['sigValidity']
except MembershipNotFoundError:
last_renewal = None
expiration = None
certified = yield from identity.unique_valid_certified_by(self.app.identities_registry, self.community)
certifiers = yield from identity.unique_valid_certifiers_of(self.app.identities_registry, self.community)
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
if last_renewal and expiration:
date_renewal = QLocale.toString(
QLocale(),
QDateTime.fromTime_t(last_renewal).date(), QLocale.dateFormat(QLocale(), QLocale.LongFormat)
)
date_expiration = QLocale.toString(
QLocale(),
QDateTime.fromTime_t(expiration).date(), QLocale.dateFormat(QLocale(), QLocale.LongFormat)
)
if self.account.pubkey in self.community.members_pubkeys():
# set infos in label
self.label_general.setText(
self.tr("""
<table cellpadding="5">
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
</table>
""").format(
self.account.name, self.account.pubkey,
self.tr("Membership"),
self.tr("Last renewal on {:}, expiration on {:}").format(date_renewal, date_expiration),
self.tr("Your web of trust"),
self.tr("Certified by {:} members; Certifier of {:} members").format(len(certifiers),
len(certified))
)
)
else:
# set infos in label
self.label_general.setText(
self.tr("""
<table cellpadding="5">
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
</table>
""").format(
self.account.name, self.account.pubkey,
self.tr("Not a member"),
self.tr("Last renewal on {:}, expiration on {:}").format(date_renewal, date_expiration),
self.tr("Your web of trust"),
self.tr("Certified by {:} members; Certifier of {:} members").format(len(certifiers),
len(certified))
)
)
else:
# set infos in label
self.label_general.setText(
self.tr("""
<table cellpadding="5">
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
<tr><td align="right"><b>{:}</b></td></tr>
<tr><td align="right"><b>{:}</b></td><td>{:}</td></tr>
</table>
""").format(
self.account.name, self.account.pubkey,
self.tr("Not a member"),
self.tr("Your web of trust"),
self.tr("Certified by {:} members; Certifier of {:} members").format(len(certifiers),
len(certified))
)
)
self.draw_graph(
self.app.identities_registry.from_handled_data(
metadata['text'],
metadata['id'],
BlockchainState.VALIDATED,
self.community
Draw community graph centered on the identity
:param cutecoin.core.registry.Identity identity: Graph node identity
logging.debug("Draw graph - " + identity.uid)
identity_account = yield from self.account.identity(self.community)
#Connect new identity
if self._current_identity != identity:
self._current_identity = identity
# create Identity from node metadata
certifier_list = yield from identity.unique_valid_certifiers_of(self.app.identities_registry,
self.community)
certified_list = yield from identity.unique_valid_certified_by(self.app.identities_registry,
self.community)
# create empty graph instance
graph = Graph(self.app, self.community)
# add wallet node
node_status = 0
if identity == identity_account:
node_status += NODE_STATUS_HIGHLIGHTED
is_member = yield from identity.is_member(self.community)
if is_member is False:
node_status += NODE_STATUS_OUT
node_status += NODE_STATUS_SELECTED
graph.add_identity(identity, node_status)
# populate graph with certifiers-of
yield from graph.add_certifier_list(certifier_list, identity, identity_account)
# populate graph with certified-by
yield from graph.add_certified_list(certified_list, identity, identity_account)
# draw graph in qt scene
self.graphicsView.scene().update_wot(graph.get())
# if selected member is not the account member...
if identity.pubkey != identity_account.pubkey:
# add path from selected member to account member
path = yield from graph.get_shortest_path_between_members(identity, identity_account)
if path:
self.graphicsView.scene().update_path(path)
def reset(self, checked=False):
"""
Reset graph scene to wallet identity
"""
identity = yield from self.account.identity(self.community)
self.draw_graph(identity)
def refresh(self):
"""
Refresh graph scene to current metadata
"""
self.draw_graph(self._current_identity)
else:
self.reset()

Vincent Texier
committed
def search(self):
"""
Search nodes when return is pressed in combobox lineEdit
"""

Vincent Texier
committed
text = self.comboBoxSearch.lineEdit().text()
if len(text) < 2:
return False
response = yield from self.community.bma_access.future_request(bma.wot.Lookup, {'search': text})
nodes = {}
for identity in response['results']:

Vincent Texier
committed
nodes[identity['pubkey']] = identity['uids'][0]['uid']
if nodes:
self.nodes = list()
self.comboBoxSearch.clear()
self.comboBoxSearch.lineEdit().setText(text)
for pubkey, uid in nodes.items():
self.nodes.append({'pubkey': pubkey, 'uid': uid})
self.comboBoxSearch.addItem(uid)
self.comboBoxSearch.showPopup()
def select_node(self, index):
"""
Select node in graph when item is selected in combobox
"""
if index < 0 or index >= len(self.nodes):
return False
node = self.nodes[index]
metadata = {'id': node['pubkey'], 'text': node['uid']}
self.app.identities_registry.from_handled_data(
metadata['text'],
metadata['id'],
BlockchainState.VALIDATED,
self.community
identity = self.app.identities_registry.from_handled_data(
metadata['text'],
metadata['id'],
BlockchainState.VALIDATED,
self.community
dialog = MemberDialog(self.app, self.account, self.community, identity)
dialog.exec_()
def sign_node(self, metadata):
identity = self.app.identities_registry.from_handled_data(
metadata['text'],
metadata['id'],
BlockchainState.VALIDATED,
self.community
yield from CertificationDialog.certify_identity(self.app, self.account, self.password_asker,
def send_money_to_node(self, metadata):
identity = self.app.identities_registry.from_handled_data(
metadata['text'],
metadata['id'],
BlockchainState.VALIDATED,
self.community
result = yield from TransferMoneyDialog.send_money_to_identity(self.app, self.account, self.password_asker,
self.community, identity)
if result == QDialog.Accepted:
def copy_node_pubkey(self, metadata):
cb = self.app.qapp.clipboard()
cb.clear(mode=cb.Clipboard)
cb.setText(metadata['id'], mode=cb.Clipboard)
def add_node_as_contact(self, metadata):
# check if contact already exists...
or metadata['id'] in [contact['pubkey'] for contact in self.account.contacts]:
dialog = ConfigureContactDialog(self.account, self.window(), {'name': metadata['text'],
'pubkey': metadata['id']})
result = dialog.exec_()
if result == QDialog.Accepted:
self.window().refresh_contacts()
def resizeEvent(self, event):
self.busy.resize(event.size())
super().resizeEvent(event)
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(WotTabWidget, self).changeEvent(event)