diff --git a/src/cutecoin/core/app.py b/src/cutecoin/core/app.py index 6246660bc84600352e36ecfab3ba1d57ba02c61b..2a9654f5a043b308081a9dbe66f6b30565f456e2 100644 --- a/src/cutecoin/core/app.py +++ b/src/cutecoin/core/app.py @@ -46,8 +46,10 @@ class Application(QObject): self.current_account = None self.monitor = None self.available_version = __version__ + self._network_manager = QNetworkAccessManager(self) config.parse_arguments(argv) - self._network_manager = QNetworkAccessManager() + self._network_manager.finished.connect(lambda reply: logging.debug("Thread : {0} , Network : {1}".format(self.thread(), + reply.url().toString()))) self.get_last_version() self.preferences = {'account': "", 'lang': 'en_GB', diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py index feb42d3fa4b94e3073db2fe82204f27623b4ed8e..5e2aacd8d597c3f9195fc6b870fddfe5a935d67d 100644 --- a/src/cutecoin/core/community.py +++ b/src/cutecoin/core/community.py @@ -9,8 +9,8 @@ from PyQt5.QtNetwork import QNetworkReply from ucoinpy.api import bma from ucoinpy.documents.block import Block from ..tools.exceptions import NoPeerAvailable -from .net.network import Network -from .net.api import qtbma +from .net.discover.network import Network +from cutecoin.core.net.api import bma as qtbma import logging import inspect import hashlib @@ -149,17 +149,25 @@ class Cache(QObject): str(tuple(frozenset(sorted(get_args.keys())))), str(tuple(frozenset(sorted(get_args.values()))))) strdata = bytes(reply.readAll()).decode('utf-8') - logging.debug("Data in reply : {0}".format(strdata)) + #logging.debug("Data in reply : {0}".format(strdata)) if cache_key not in self.data: self.data[cache_key] = {} - self.data[cache_key]['value'] = json.loads(strdata) if 'metadata' not in self.data[cache_key]: self.data[cache_key]['metadata'] = {} self.data[cache_key]['metadata']['block'] = self.latest_block - caller.data_changed.emit() + change = False + if 'value' in self.data[cache_key]: + if self.data[cache_key]['value'] != json.loads(strdata): + change = True + else: + change = True + + if change == True: + self.data[cache_key]['value'] = json.loads(strdata) + caller.data_changed.emit(request) else: logging.debug("Error in reply : {0}".format(reply.error())) self.community.qtrequest(caller, request, req_args, get_args) @@ -173,7 +181,7 @@ class Community(QObject): .. warning:: The currency name is supposed to be unique in cutecoin but nothing exists in ucoin to assert that a currency name is unique. ''' - data_changed = pyqtSignal() + data_changed = pyqtSignal(int) def __init__(self, currency, network): ''' @@ -495,7 +503,7 @@ class Community(QObject): ''' Start a request to the community. - :param request: A qtbma request class calling for data + :param request: A bma request class calling for data :param caller: The components :param req_args: Arguments to pass to the request constructor :param get_args: Arguments to pass to the request __get__ method diff --git a/src/cutecoin/core/net/api/qtbma/__init__.py b/src/cutecoin/core/net/api/bma/__init__.py similarity index 98% rename from src/cutecoin/core/net/api/qtbma/__init__.py rename to src/cutecoin/core/net/api/bma/__init__.py index 145eb7c8a82b34cedb4e19c1990283ff370876b7..770ea5d5876cbe5892b6c6ca5cebc58b0d091402 100644 --- a/src/cutecoin/core/net/api/qtbma/__init__.py +++ b/src/cutecoin/core/net/api/bma/__init__.py @@ -90,12 +90,13 @@ class API(object): Arguments: - `path`: the request path """ - query = QUrlQuery(self.reverse_url(path)) + query = QUrlQuery() for k,v in kwargs.items(): query.addQueryItem(k, v); url = QUrl(self.reverse_url(path)) url.setQuery(query) request = QNetworkRequest(url) + logging.debug(url.toString()) reply = self.conn_handler.network_manager.get(request) return reply diff --git a/src/cutecoin/core/net/api/qtbma/blockchain/__init__.py b/src/cutecoin/core/net/api/bma/blockchain/__init__.py similarity index 100% rename from src/cutecoin/core/net/api/qtbma/blockchain/__init__.py rename to src/cutecoin/core/net/api/bma/blockchain/__init__.py diff --git a/src/cutecoin/core/net/api/qtbma/network/__init__.py b/src/cutecoin/core/net/api/bma/network/__init__.py similarity index 100% rename from src/cutecoin/core/net/api/qtbma/network/__init__.py rename to src/cutecoin/core/net/api/bma/network/__init__.py diff --git a/src/cutecoin/core/net/api/qtbma/network/peering/__init__.py b/src/cutecoin/core/net/api/bma/network/peering/__init__.py similarity index 96% rename from src/cutecoin/core/net/api/qtbma/network/peering/__init__.py rename to src/cutecoin/core/net/api/bma/network/peering/__init__.py index 1127f275263d76873e49f4d923b2b8752f2e40ff..8da405735be29d99eaea8c590d6c328b3d95a954 100644 --- a/src/cutecoin/core/net/api/qtbma/network/peering/__init__.py +++ b/src/cutecoin/core/net/api/bma/network/peering/__init__.py @@ -32,7 +32,7 @@ class Peers(Base): def __get__(self, **kwargs): """creates a generator with one peering entry per iteration.""" - return self.requests_get('/peers') + return self.requests_get('/peers', **kwargs) def __post__(self, **kwargs): assert 'entry' in kwargs diff --git a/src/cutecoin/core/net/api/qtbma/tx/__init__.py b/src/cutecoin/core/net/api/bma/tx/__init__.py similarity index 100% rename from src/cutecoin/core/net/api/qtbma/tx/__init__.py rename to src/cutecoin/core/net/api/bma/tx/__init__.py diff --git a/src/cutecoin/core/net/api/qtbma/wot/__init__.py b/src/cutecoin/core/net/api/bma/wot/__init__.py similarity index 100% rename from src/cutecoin/core/net/api/qtbma/wot/__init__.py rename to src/cutecoin/core/net/api/bma/wot/__init__.py diff --git a/src/cutecoin/core/net/discover/__init__.py b/src/cutecoin/core/net/discover/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/cutecoin/core/net/discover/network.py b/src/cutecoin/core/net/discover/network.py new file mode 100644 index 0000000000000000000000000000000000000000..81c3d6a8f64e2df4f0dcae0166a5d6f1e1481942 --- /dev/null +++ b/src/cutecoin/core/net/discover/network.py @@ -0,0 +1,213 @@ +''' +Created on 24 févr. 2015 + +@author: inso +''' +from .node import Node + +import logging +import time + +from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QCoreApplication, QTimer + + +class Network(QObject): + ''' + A network is managing nodes polling and crawling of a + given community. + ''' + nodes_changed = pyqtSignal() + new_block_mined = pyqtSignal(int) + + def __init__(self, network_manager, currency, nodes): + ''' + Constructor of a network + + :param str currency: The currency name of the community + :param list nodes: The root nodes of the network + ''' + super().__init__() + self._root_nodes = nodes + self._nodes = [] + for n in nodes: + self.add_node(n) + self.currency = currency + self._must_crawl = False + self._is_perpetual = False + self.network_manager = network_manager + self._block_found = self.latest_block + self._timer = QTimer() + + @classmethod + def create(cls, network_manager, node): + ''' + Create a new network with one knew node + Crawls the nodes from the first node to build the + community network + + :param node: The first knew node of the network + ''' + nodes = [node] + network = cls(network_manager, node.currency, nodes) + return network + + def merge_with_json(self, json_data): + ''' + We merge with knew nodes when we + last stopped cutecoin + + :param dict json_data: Nodes in json format + ''' + for data in json_data: + node = Node.from_json(self.network_manager, self.currency, data) + if node.pubkey not in [n.pubkey for n in self.nodes]: + self.add_node(node) + logging.debug("Loading : {:}".format(data['pubkey'])) + else: + other_node = [n for n in self.nodes if n.pubkey == node.pubkey][0] + if other_node.block < node.block: + other_node.block = node.block + other_node.last_change = node.last_change + other_node.state = node.state + + @classmethod + def from_json(cls, network_manager, currency, json_data): + ''' + Load a network from a configured community + + :param str currency: The currency name of a community + :param dict json_data: A json_data view of a network + ''' + nodes = [] + for data in json_data: + node = Node.from_json(network_manager, currency, data) + nodes.append(node) + network = cls(network_manager, currency, nodes) + return network + + def jsonify(self): + ''' + Get the network in json format. + + :return: The network as a dict in json format. + ''' + data = [] + for node in self.nodes: + data.append(node.jsonify()) + return data + + def stop_crawling(self): + ''' + Stop network nodes crawling. + ''' + self._must_crawl = False + + def continue_crawling(self): + if self._is_perpetual: + return self._must_crawl + else: + return True + + @property + def synced_nodes(self): + ''' + Get nodes which are in the ONLINE state. + ''' + return [n for n in self.nodes if n.state == Node.ONLINE] + + @property + def online_nodes(self): + ''' + Get nodes which are in the ONLINE state. + ''' + return [n for n in self.nodes if n.state in (Node.ONLINE, Node.DESYNCED)] + + @property + def nodes(self): + ''' + Get all knew nodes. + ''' + return self._nodes + + @property + def root_nodes(self): + ''' + Get root nodes. + ''' + return self._root_nodes + + @property + def latest_block(self): + ''' + Get latest block known + ''' + return max([n.block for n in self.nodes]) + + def add_node(self, node): + ''' + Add a node to the network. + ''' + self._nodes.append(node) + node.changed.connect(self.handle_change) + node.neighbour_found.connect(self.handle_new_node) + node.destroyed.connect(lambda: logging.debug("Node destroyed")) + logging.debug("{:} connected".format(node.pubkey[:5])) + + def add_root_node(self, node): + ''' + Add a node to the root nodes list + ''' + self._root_nodes.append(node) + + def remove_root_node(self, index): + ''' + Remove a node from the root nodes list + ''' + self._root_nodes.pop(index) + + def is_root_node(self, node): + ''' + Check if this node is in the root nodes + ''' + return node in self._root_nodes + + def root_node_index(self, index): + ''' + Get the index of a root node from its index + in all nodes list + ''' + node = self.nodes[index] + return self._root_nodes.index(node) + + def discover_network(self): + ''' + Start crawling which never stops. + To stop this crawling, call "stop_crawling" method. + ''' + self._must_crawl = True + self._is_perpetual = True + for node in self.nodes: + node.refresh() + + @pyqtSlot() + def handle_new_node(self, peer): + pubkeys = [n.pubkey for n in self.nodes] + if peer.pubkey not in pubkeys: + node = Node.from_peer(self._currency, peer) + self.add_node(node) + self.nodes_changed.emit() + + @pyqtSlot() + def handle_change(self): + node = self.sender() + if node.state in (Node.ONLINE, Node.DESYNCED): + node.check_sync(self.latest_block) + else: + if node.last_change + 3600 < time.time(): + self.nodes.remove(node) + self.nodes_changed.emit() + + logging.debug("{0} -> {1}".format(self.latest_block, self.latest_block)) + if self._block_found < self.latest_block: + logging.debug("New block found : {0}".format(self.latest_block)) + self.new_block_mined.emit(self.latest_block) diff --git a/src/cutecoin/core/net/discover/node.py b/src/cutecoin/core/net/discover/node.py new file mode 100644 index 0000000000000000000000000000000000000000..22e8af667e534f7d5453708c0ecf44d11ddd6830 --- /dev/null +++ b/src/cutecoin/core/net/discover/node.py @@ -0,0 +1,403 @@ +''' +Created on 21 févr. 2015 + +@author: inso +''' + +from ucoinpy.documents.peer import Peer, BMAEndpoint, Endpoint +from requests.exceptions import RequestException, ConnectionError +from ....tools.exceptions import InvalidNodeCurrency, PersonNotFoundError +from ...person import Person +from ..api import bma as qtbma +from ..api.bma import ConnectionHandler + +import logging +import time +import ctypes +import sys +import json + +from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot +from PyQt5.QtNetwork import QNetworkReply, QNetworkRequest + + +def some_print(): + logging.debug("Module : ok !") + +class Node(QObject): + ''' + A node is a peer seend from the client point of view. + This node can have multiple states : + - ONLINE : The node is available for requests + - OFFLINE: The node is disconnected + - DESYNCED : The node is online but is desynced from the network + - CORRUPTED : The node is corrupted, some weird behaviour is going on + ''' + + ONLINE = 1 + OFFLINE = 2 + DESYNCED = 3 + CORRUPTED = 4 + + changed = pyqtSignal() + neighbour_found = pyqtSignal(Peer) + + def __init__(self, network_manager, currency, endpoints, uid, pubkey, block, + state, last_change): + ''' + Constructor + ''' + super().__init__() + self.network_manager = network_manager + self._endpoints = endpoints + self._uid = uid + self._pubkey = pubkey + self.block = block + self._state = state + self._neighbours = [] + self._currency = currency + self._last_change = last_change + + @classmethod + def from_address(cls, network_manager, currency, address, port): + ''' + Factory method to get a node from a given address + + :param str currency: The node currency. None if we don't know\ + the currency it should have, for example if its the first one we add + :param str address: The node address + :param int port: The node port + ''' + peer_data = qtbma.network.Peering(ConnectionHandler(network_manager, address, port)).get() + + peer = Peer.from_signed_raw("{0}{1}\n".format(peer_data['raw'], + peer_data['signature'])) + + if currency is not None: + if peer.currency != currency: + raise InvalidNodeCurrency(peer.currency, currency) + + node = cls(network_manager, peer.currency, peer.endpoints, + "", peer.pubkey, 0, + Node.ONLINE, time.time()) + logging.debug("Node from address : {:}".format(str(node))) + return node + + @classmethod + def from_peer(cls, network_manager, currency, peer): + ''' + Factory method to get a node from a peer document. + + :param str currency: The node currency. None if we don't know\ + the currency it should have, for example if its the first one we add + :param peer: The peer document + ''' + if currency is not None: + if peer.currency != currency: + raise InvalidNodeCurrency(peer.currency, currency) + + node = cls(network_manager, peer.currency, peer.endpoints, "", "", 0, + Node.ONLINE, time.time()) + logging.debug("Node from peer : {:}".format(str(node))) + return node + + @classmethod + def from_json(cls, network_manager, currency, data): + endpoints = [] + uid = "" + pubkey = "" + block = 0 + last_change = time.time() + state = Node.ONLINE + logging.debug(data) + for endpoint_data in data['endpoints']: + endpoints.append(Endpoint.from_inline(endpoint_data)) + + if currency in data: + currency = data['currency'] + + if 'uid' in data: + uid = data['uid'] + + if 'pubkey' in data: + pubkey = data['pubkey'] + + if 'last_change' in data: + last_change = data['last_change'] + + if 'block' in data: + block = data['block'] + + if 'state' in data: + state = data['state'] + else: + logging.debug("Error : no state in node") + + node = cls(network_manager, currency, endpoints, + uid, pubkey, block, + state, last_change) + logging.debug("Node from json : {:}".format(str(node))) + return node + + def jsonify_root_node(self): + logging.debug("Saving root node : {:}".format(str(self))) + data = {'pubkey': self._pubkey, + 'uid': self._uid, + 'currency': self._currency} + endpoints = [] + for e in self._endpoints: + endpoints.append(e.inline()) + data['endpoints'] = endpoints + return data + + def jsonify(self): + logging.debug("Saving node : {:}".format(str(self))) + data = {'pubkey': self._pubkey, + 'uid': self._uid, + 'currency': self._currency, + 'state': self._state, + 'last_change': self._last_change, + 'block': self.block} + endpoints = [] + for e in self._endpoints: + endpoints.append(e.inline()) + data['endpoints'] = endpoints + return data + + @property + def pubkey(self): + return self._pubkey + + @property + def endpoint(self) -> BMAEndpoint: + return next((e for e in self._endpoints if type(e) is BMAEndpoint)) + + @property + def block(self): + return self._block + + @block.setter + def block(self, new_block): + self._block = new_block + + @property + def state(self): + return self._state + + @property + def currency(self): + return self._currency + + @property + def neighbours(self): + return self._neighbours + + @property + def uid(self): + return self._uid + + @property + def last_change(self): + return self._last_change + + @last_change.setter + def last_change(self, val): + logging.debug("{:} | Changed state : {:}".format(self.pubkey[:5], + val)) + self._last_change = val + + @state.setter + def state(self, new_state): + logging.debug("{:} | Last state : {:} / new state : {:}".format(self.pubkey[:5], + self.state, new_state)) + if self._state != new_state: + self.last_change = time.time() + self._state = new_state + + def check_sync(self, block): + logging.debug("Check sync") + if self.block < block: + self.state = Node.DESYNCED + else: + self.state = Node.ONLINE + + def check_noerror(self, error_code, status_code): + if error_code != QNetworkReply.NoError: + if self.state == Node.OFFLINE: + self.state = Node.ONLINE + return False + if status_code == 503: + return False + return True + + @pyqtSlot() + def refresh(self): + logging.debug("Refresh block") + self.refresh_block() + logging.debug("Refresh info") + self.refresh_informations() + logging.debug("Refresh uid") + self.refresh_uid() + logging.debug("Refresh peers") + self.refresh_peers() + + def refresh_block(self): + conn_handler = ConnectionHandler(self.network_manager, + self.endpoint.conn_handler().server, + self.endpoint.conn_handler().port) + + logging.debug("Requesting {0}".format(conn_handler)) + reply = qtbma.blockchain.Current(conn_handler).get() + + reply.finished.connect(lambda: self.handle_block_reply(reply)) + + @pyqtSlot() + def handle_block_reply(self, reply): + logging.debug("Handle block reply") + #reply = self.sender() + logging.debug("Found thread : {0}".format(self.thread())) + logging.debug("Found reply : {0}".format(reply)) + logging.debug("Found sender : {0}".format(self.sender())) + logging.debug("Found url : {0}".format(reply.url().toString())) + logging.debug("Found manager : {0}".format(reply.manager())) + status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + logging.debug("Status code : {0}".format(status_code)) + logging.debug("Error : {0}".format(reply.error())) + + if self.check_noerror(reply.error(), status_code): + if status_code == 200: + strdata = bytes(reply.readAll()).decode('utf-8') + block_data = json.loads(strdata) + block_number = block_data['number'] + elif status_code == 404: + block_number = 0 + + if block_number != self.block: + self.block = block_number + logging.debug("Changed block {0} -> {1}".format(self.block, + block_number)) + self.changed.emit() + + else: + logging.debug("Error in block reply") + + def refresh_informations(self): + conn_handler = ConnectionHandler(self.network_manager, + self.endpoint.conn_handler().server, + self.endpoint.conn_handler().port) + + peering_reply = qtbma.network.Peering(conn_handler).get() + peering_reply.finished.connect(lambda: self.handle_peering_reply(peering_reply)) + + @pyqtSlot() + def handle_peering_reply(self, reply): + logging.debug("Handle peering reply") + reply = self.sender() + status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + + if self.check_noerror(reply.error(), status_code): + strdata = bytes(reply.readAll()).decode('utf-8') + peering_data = json.loads(strdata) + node_pubkey = peering_data["pubkey"] + node_currency = peering_data["currency"] + + change = False + if node_pubkey != self.pubkey: + self.pubkey = node_pubkey + change = True + + if node_currency != self.currency: + self.state = Node.CORRUPTED + logging.debug("Change : new state corrupted") + change = True + + if change: + self.changed.emit() + else: + logging.debug("Error in peering reply") + + def refresh_uid(self): + conn_handler = ConnectionHandler(self.network_manager, + self.endpoint.conn_handler().server, + self.endpoint.conn_handler().port) + uid_reply = qtbma.wot.Lookup(conn_handler, self.pubkey).get() + uid_reply.finished.connect(lambda: self.handle_uid_reply(uid_reply)) + uid_reply.error.connect(lambda code: logging.debug("Error : {0}".format(code))) + + @pyqtSlot() + def handle_uid_reply(self, reply): + logging.debug("Handle uid reply") + #reply = self.sender() + status_code = reply.attribute( QNetworkRequest.HttpStatusCodeAttribute ); + + if self.check_noerror(reply.error(), status_code): + uid = '' + if status_code == 200: + strdata = bytes(reply.readAll()).decode('utf-8') + data = json.loads(strdata) + timestamp = 0 + for result in data['results']: + if result["pubkey"] == self.pubkey: + uids = result['uids'] + for uid in uids: + if uid["meta"]["timestamp"] > timestamp: + timestamp = uid["meta"]["timestamp"] + uid = uid["uid"] + elif status_code == 404: + logging.debug("UID not found") + + if self._uid != uid: + self._uid = uid + self.changed.emit() + else: + logging.debug("error in uid reply") + + def refresh_peers(self): + conn_handler = ConnectionHandler(self.network_manager, + self.endpoint.conn_handler().server, + self.endpoint.conn_handler().port) + + reply = qtbma.network.peering.Peers(conn_handler).get(leaves='true') + reply.finished.connect(lambda: self.handle_peers_reply(reply)) + reply.error.connect(lambda code: logging.debug("Error : {0}".format(code))) + + + @pyqtSlot() + def handle_peers_reply(self, reply): + logging.debug("Handle peers reply") + #reply = self.sender() + status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + + if self.check_noerror(reply.error(), status_code): + strdata = bytes(reply.readAll()).decode('utf-8') + peers_data = json.loads(strdata) + if True: #peers_data['root'] != self._last_root: + leaves = [leaf for leaf in peers_data['leaves']] + #if leaf not in self._last_leaves] + for leaf_hash in leaves: + conn_handler = ConnectionHandler(self.network_manager, + self.endpoint.conn_handler().server, + self.endpoint.conn_handler().port) + leaf_reply = qtbma.network.peering.Peers(conn_handler).get(leaf=leaf_hash) + leaf_reply.finished.connect(lambda: self.handle_leaf_reply(leaf_reply)) + else: + logging.debug("Error in peers reply") + + @pyqtSlot() + def handle_leaf_reply(self, reply): + logging.debug("Handle leaf reply") + reply = self.sender() + status_code = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) + + if self.check_noerror(reply.error(), status_code): + strdata = bytes(reply.readAll()).decode('utf-8') + leaf_data = json.loads(strdata) + doc = Peer.from_signed_raw("{0}{1}\n".format(leaf_data['leaf']['value']['raw'], + leaf_data['leaf']['value']['signature'])) + self.neighbour_found.emit(doc) + else: + logging.debug("Error in leaf reply") + + def __str__(self): + return ','.join([str(self.pubkey), str(self.endpoint.server), str(self.endpoint.port), str(self.block), + str(self.currency), str(self.state), str(self.neighbours)]) diff --git a/src/cutecoin/core/watching/monitor.py b/src/cutecoin/core/watching/monitor.py index da4c3eb22825cbab83f303d4a54d2de444e638c9..6f9e0122f0094a251b01e2439ca38de530cf3984 100644 --- a/src/cutecoin/core/watching/monitor.py +++ b/src/cutecoin/core/watching/monitor.py @@ -28,7 +28,6 @@ class Monitor(object): self.account = account self.threads_pool = [] self._blockchain_watchers = {} - self._network_watchers = {} self._persons_watchers = {} Monitor.___dirty_monitors.append(self) @@ -59,13 +58,6 @@ class Monitor(object): self.connect_watcher_to_thread(bc_watcher) self._blockchain_watchers[c.name] = bc_watcher - self.connect_watcher_to_thread(c.network) - self._network_watchers[c.name] = c.network - - def start_network_watchers(self): - for watcher in self._network_watchers.values(): - watcher.thread().start() - def stop_watching(self): for watcher in self._persons_watchers.values(): watcher.stop() @@ -79,13 +71,6 @@ class Monitor(object): watcher.deleteLater() watcher.thread().deleteLater() - for watcher in self._network_watchers.values(): - watcher.stop() - self.threads_pool.remove(watcher.thread()) - watcher.deleteLater() - watcher.thread().deleteLater() - self.threads_pool = [] self._blockchain_watchers = {} - self._network_watchers = {} self._persons_watchers = {} diff --git a/src/cutecoin/gui/community_tab.py b/src/cutecoin/gui/community_tab.py index ff0e7938a082789f7f1719508ff3aa790299c251..b544d11cffad0302ff6ea9c12a3c3d7fa22ceb54 100644 --- a/src/cutecoin/gui/community_tab.py +++ b/src/cutecoin/gui/community_tab.py @@ -21,6 +21,7 @@ from . import toast from ..tools.exceptions import PersonNotFoundError, NoPeerAvailable from ..core.person import Person from ucoinpy.api import bma +from ..core.net.api import bma as qtbma class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): @@ -265,9 +266,10 @@ Publishing your UID cannot be canceled.""") self.edit_textsearch.clear() self.refresh(persons) - def handle_change(self): - if self._last_search == 'members': - self.search_members() + def handle_change(self, origin): + if origin == qtbma.wot.Members: + if self._last_search == 'members': + self.search_members() def search_members(self): """ diff --git a/src/cutecoin/gui/currency_tab.py b/src/cutecoin/gui/currency_tab.py index 1f3efa89fd9c5f8d7ec377060bea5e77ead670be..491c7e16170227ddadb3339a09b44f96d50357ed 100644 --- a/src/cutecoin/gui/currency_tab.py +++ b/src/cutecoin/gui/currency_tab.py @@ -102,11 +102,11 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget): self.tr("Informations")) # fix bug refresh_nodes launch on destroyed NetworkTabWidget - logging.debug('Disconnect community.network.nodes_changed') - try: - self.community.network.nodes_changed.disconnect() - except TypeError: - logging.debug('No signals on community.network.nodes_changed') + #logging.debug('Disconnect community.network.nodes_changed') + #try: + # self.community.network.nodes_changed.disconnect() + #except TypeError: + # logging.debug('No signals on community.network.nodes_changed') self.tab_network = NetworkTabWidget(self.community) self.tabs_account.addTab(self.tab_network, @@ -213,6 +213,7 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget): self.tab_wallets.refresh() def showEvent(self, event): + self.community.network.discover_network() self.refresh_status() def referential_changed(self): diff --git a/src/cutecoin/gui/mainwindow.py b/src/cutecoin/gui/mainwindow.py index 8c93f3eb4e105b36cdf5acfbddf2439bdc79c103..7ea2d5c5057ad351fdfd3bc2d8aa07089a8aa8ac 100644 --- a/src/cutecoin/gui/mainwindow.py +++ b/src/cutecoin/gui/mainwindow.py @@ -184,7 +184,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.busybar.hide() QApplication.setOverrideCursor(Qt.ArrowCursor) self.app.disconnect() - self.app.monitor.start_network_watchers() QApplication.processEvents() def open_transfer_money_dialog(self): diff --git a/src/cutecoin/models/network.py b/src/cutecoin/models/network.py index bb10397b3a26e2f82f07f1fbd53bee758778c99e..5fe81d5108ec766e326b30cceabf5dfcf537941f 100644 --- a/src/cutecoin/models/network.py +++ b/src/cutecoin/models/network.py @@ -6,7 +6,7 @@ Created on 5 févr. 2014 import logging from ..tools.exceptions import NoPeerAvailable -from ..core.net.node import Node +from ..core.net.discover.node import Node from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant, QSortFilterProxyModel from PyQt5.QtGui import QColor, QFont