diff --git a/README.md b/README.md index f3cfcdb7b0ce01f87078f2ed2ac7fd57f81b96f7..60c30edbe1559be622beb2315f03dcd6f1f79e58 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Qt Client for [Ucoin](http://www.ucoin.io) project. * The executable is generated in "build" folder, named "cutecoin" ### How to download latest release - * Go to the [current release](https://github.com/ucoin-io/cutecoin/releases/tag/0.8.1) + * Go to the [current release](https://github.com/ucoin-io/cutecoin/releases/tag/0.8.2) * Download the package corresponding to your operating system * Unzip and start "cutecoin" :) * Join our beta community by contacting us on ucoin forums : forum.ucoin.io diff --git a/src/cutecoin/core/community.py b/src/cutecoin/core/community.py index eeb2fb3df542d99ec95bb81715c0b5e5833ec1e6..1c0bffb488b5faba974599342d788f5f5df31417 100644 --- a/src/cutecoin/core/community.py +++ b/src/cutecoin/core/community.py @@ -176,10 +176,10 @@ class Community(object): else: return 1 - def get_ud_block(self): - ud = self.request(bma.blockchain.UD) - if len(ud['result']['blocks']) > 0: - block_number = ud['result']['blocks'][-1] + def get_ud_block(self, x=0): + blocks = self.request(bma.blockchain.UD)['result']['blocks'] + if len(blocks) > 0: + block_number = blocks[len(blocks)-(1+x)] block = self.request(bma.blockchain.Block, req_args={'number': block_number}) return block diff --git a/src/cutecoin/gui/community_tab.py b/src/cutecoin/gui/community_tab.py index 61fd2b562889d3f799919ecb22b5d90ed45aa1c8..3016af98064ef644b08b979416c88a719e659c38 100644 --- a/src/cutecoin/gui/community_tab.py +++ b/src/cutecoin/gui/community_tab.py @@ -6,7 +6,7 @@ Created on 2 févr. 2014 import logging from PyQt5.QtCore import Qt -from PyQt5.QtGui import QIcon +from PyQt5.QtGui import QIcon, QCursor from PyQt5.QtWidgets import QWidget, QMessageBox, QAction, QMenu, QDialog, \ QAbstractItemView from ..models.members import MembersFilterProxyModel, MembersTableModel @@ -49,8 +49,8 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): self.button_membership.setText("Send membership demand") self.button_leaving.hide() - self.wot_tab = WotTabWidget(account, community, password_asker) - self.tabs_information.addTab(self.wot_tab, QIcon(':/icons/wot_icon'), "Wot") + self.wot_tab = WotTabWidget(account, community, password_asker, self) + self.tabs_information.addTab(self.wot_tab, QIcon(':/icons/wot_icon'), "WoT") def member_context_menu(self, point): index = self.table_community_members.indexAt(point) @@ -65,15 +65,15 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): menu = QMenu(self) add_contact = QAction("Add as contact", self) - add_contact.triggered.connect(self.add_member_as_contact) + add_contact.triggered.connect(self.menu_add_as_contact) add_contact.setData(member) send_money = QAction("Send money", self) - send_money.triggered.connect(self.send_money_to_member) + send_money.triggered.connect(self.menu_send_money) send_money.setData(member) certify = QAction("Certify identity", self) - certify.triggered.connect(self.certify_member) + certify.triggered.connect(self.menu_certify_member) certify.setData(member) view_wot = QAction("View in WoT", self) @@ -86,18 +86,28 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): menu.addAction(view_wot) # Show the context menu. - menu.exec_(self.table_community_members.mapToGlobal(point)) + menu.exec_(QCursor.pos()) - def add_member_as_contact(self): + def menu_add_as_contact(self): person = self.sender().data() + self.add_member_as_contact(person) + + def menu_send_money(self): + person = self.sender().data() + self.send_money_to_member(person) + + def menu_certify_member(self): + person = self.sender().data() + self.certify_member(person) + + def add_member_as_contact(self, person): dialog = ConfigureContactDialog(self.account, self.window(), person) result = dialog.exec_() if result == QDialog.Accepted: self.window().refresh_contacts() - def send_money_to_member(self): + def send_money_to_member(self, person): dialog = TransferMoneyDialog(self.account, self.password_asker) - person = self.sender().data() dialog.edit_pubkey.setText(person.pubkey) dialog.combo_community.setCurrentText(self.community.name()) dialog.radio_pubkey.setChecked(True) @@ -105,9 +115,8 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): currency_tab = self.window().currencies_tabwidget.currentWidget() currency_tab.table_history.model().invalidate() - def certify_member(self): + def certify_member(self, person): dialog = CertificationDialog(self.account, self.password_asker) - person = self.sender().data() dialog.combo_community.setCurrentText(self.community.name()) dialog.edit_pubkey.setText(person.pubkey) dialog.radio_pubkey.setChecked(True) diff --git a/src/cutecoin/gui/contact.py b/src/cutecoin/gui/contact.py index 3a0cd82de7d6b45a7611f3a45e544fb77a48d89f..469b9fb88839af42fc85ed08fdc1c20c8839a92d 100644 --- a/src/cutecoin/gui/contact.py +++ b/src/cutecoin/gui/contact.py @@ -16,7 +16,7 @@ class ConfigureContactDialog(QDialog, Ui_ConfigureContactDialog): classdocs ''' - def __init__(self, account, parent=None, contact=None): + def __init__(self, account, parent=None, contact=None, edit=False): ''' Constructor ''' @@ -28,8 +28,8 @@ class ConfigureContactDialog(QDialog, Ui_ConfigureContactDialog): if contact: self.edit_name.setText(contact.name) self.edit_pubkey.setText(contact.pubkey) - - self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) + if edit: + self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) def accept(self): name = self.edit_name.text() diff --git a/src/cutecoin/gui/currency_tab.py b/src/cutecoin/gui/currency_tab.py index fc820950a6cf8a983e73cabe973b06c05ec18b60..8aa750fa1f59e85faac8df7d74ab44585097d72d 100644 --- a/src/cutecoin/gui/currency_tab.py +++ b/src/cutecoin/gui/currency_tab.py @@ -209,6 +209,26 @@ class CurrencyTabWidget(QWidget, Ui_CurrencyTabWidget): if self.app.current_account: self.tab_wallets.refresh() + def wallet_context_menu(self, point): + index = self.list_wallets.indexAt(point) + model = self.list_wallets.model() + if index.row() < model.rowCount(QModelIndex()): + wallet = model.wallets[index.row()] + menu = QMenu(model.data(index, Qt.DisplayRole), self) + + rename = QAction("Rename", self) + rename.triggered.connect(self.rename_wallet) + rename.setData(index) + + copy_pubkey = QAction("Copy pubkey to clipboard", self) + copy_pubkey.triggered.connect(self.copy_pubkey_to_clipboard) + copy_pubkey.setData(wallet) + + menu.addAction(rename) + menu.addAction(copy_pubkey) + # Show the context menu. + menu.exec_(QCursor.pos()) + def history_context_menu(self, point): index = self.table_history.indexAt(point) model = self.table_history.model() diff --git a/src/cutecoin/gui/informations_tab.py b/src/cutecoin/gui/informations_tab.py index 462094edc9c23e89008e775f68a7d5b8f80d8403..e96b6f1a617f8cb727f7fa17d2f4b91f52db72b6 100644 --- a/src/cutecoin/gui/informations_tab.py +++ b/src/cutecoin/gui/informations_tab.py @@ -6,6 +6,7 @@ Created on 31 janv. 2015 import logging import datetime +import math from PyQt5.QtWidgets import QWidget from ..gen_resources.informations_tab_uic import Ui_InformationsTabWidget @@ -40,31 +41,36 @@ class InformationsTabWidget(QWidget, Ui_InformationsTabWidget): except Exception as e: logging.debug('community get_ud_block error : ' + str(e)) return False + try: + block_t_minus_1 = self.community.get_ud_block(1) + except Exception as e: + logging.debug('community get_ud_block error : ' + str(e)) + return False # set infos in label self.label_general.setText( """ <table cellpadding="5"> - <tr><td align="right"><b>{:.2f}</b></div></td><td>{:} {:}</td></tr> - <tr><td align="right"><b>{:.2f}</b></td><td>{:} {:}</td></tr> + <tr><td align="right"><b>{:}</b></div></td><td>{:} {:}</td></tr> + <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>{:.2f}</b></td><td>{:} {:}</td></tr> + <tr><td align="right"><b>{:}</b></td><td>{:} {:}</td></tr> <tr><td align="right"><b>{:2.2%} / {:} days</b></td><td>{:}</td></tr> <tr><td align="right"><b>{:}</b></td><td>{:}</td></tr> </table> """.format( - self.get_referential_diff_value(block['dividend']), + round(self.get_referential_diff_value(block['dividend'])), 'Universal Dividend UD(t) in', self.get_referential_name(), - self.get_referential_value(block['monetaryMass']), + round(self.get_referential_value(block['monetaryMass'])), 'Monetary Mass M(t) in', self.get_referential_name(), block['membersCount'], 'Members N(t)', - self.get_referential_value(block['monetaryMass'] / block['membersCount']), + round(self.get_referential_value(block['monetaryMass'] / block['membersCount'])), 'Monetary Mass per member M(t)/N(t) in', self.get_referential_name(), - block['dividend'] / (block['monetaryMass'] / block['membersCount']), + block['dividend'] / (block_t_minus_1['monetaryMass'] / block['membersCount']), params['dt'] / 86400, 'Actual growth c = UD(t)/[M(t-1)/N(t)]', datetime.datetime.fromtimestamp(block['medianTime'] + params['dt']).strftime("%d/%m/%Y %I:%M"), @@ -120,11 +126,12 @@ class InformationsTabWidget(QWidget, Ui_InformationsTabWidget): 'Fundamental growth (c) / Delta time (dt)', 'UD(t+1) = MAX { UD(t) ; c * M(t) / N(t) }', 'Universal Dividend (formula)', - 'UD(t+1) = MAX {{ {:.2f} {:} ; {:2.0%} * {:.2f} {:} / {:} }}'.format( - self.get_referential_diff_value(block['dividend']), + '{:} = MAX {{ {:} {:} ; {:2.0%} * {:} {:} / {:} }}'.format( + math.ceil(max(block['dividend'], params['c'] * block['monetaryMass'] / block['membersCount'])), + round(self.get_referential_diff_value(block['dividend'])), self.get_referential_name(), params['c'], - self.get_referential_value(block['monetaryMass']), + round(self.get_referential_value(block['monetaryMass'])), self.get_referential_name(), block['membersCount'] ), diff --git a/src/cutecoin/gui/mainwindow.py b/src/cutecoin/gui/mainwindow.py index bb7d1c9a63a69acd9bfd62b09d4b7f8d83b53a5a..e2d776610600a9cce4320ba8e2e0455dd562749d 100644 --- a/src/cutecoin/gui/mainwindow.py +++ b/src/cutecoin/gui/mainwindow.py @@ -138,7 +138,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): @pyqtSlot() def edit_contact(self): contact = self.sender().data() - dialog = ConfigureContactDialog(self.app.current_account, self, contact) + dialog = ConfigureContactDialog(self.app.current_account, self, contact, True) result = dialog.exec_() if result == QDialog.Accepted: self.window().refresh_contacts() diff --git a/src/cutecoin/gui/views/wot.py b/src/cutecoin/gui/views/wot.py index bec31ef1ff0c73d0dd65ef1bf6ae39ff797cfe05..ce64aca6aaca8d4dc87ef885a6a51e0f6f5fc020 100644 --- a/src/cutecoin/gui/views/wot.py +++ b/src/cutecoin/gui/views/wot.py @@ -2,7 +2,7 @@ import math from PyQt5.QtGui import QPainter, QBrush, QPen, QPolygonF, QColor, QRadialGradient,\ - QPainterPath, QMouseEvent, QWheelEvent, QTransform + 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,\ diff --git a/src/cutecoin/gui/wot_tab.py b/src/cutecoin/gui/wot_tab.py index 6627fe48b1e3a298479a9ea157dae96c9fad4e2b..9933e02296d0e8b6977efebab5228977625bb75c 100644 --- a/src/cutecoin/gui/wot_tab.py +++ b/src/cutecoin/gui/wot_tab.py @@ -4,7 +4,6 @@ import time import datetime import logging from PyQt5.QtWidgets import QWidget, QComboBox, QDialog - 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 @@ -24,6 +23,7 @@ class WotTabWidget(QWidget, Ui_WotTabWidget): :return: """ super().__init__(parent) + self.parent = parent # construct from qtDesigner self.setupUi(self) @@ -61,7 +61,7 @@ class WotTabWidget(QWidget, Ui_WotTabWidget): :param dict metadata: Graph node metadata of the identity """ # create Person from node metadata - person = Person(metadata['text'], metadata['id']) + person = self.get_person_from_metadata(metadata) certifiers = person.certifiers_of(self.community) # reset graph @@ -231,32 +231,19 @@ class WotTabWidget(QWidget, Ui_WotTabWidget): ) def sign_node(self, metadata): - # open certify dialog - dialog = CertificationDialog(self.account, self.password_asker) - dialog.combo_community.setCurrentText(self.community.name()) - dialog.edit_pubkey.setText(metadata['id']) - dialog.radio_pubkey.setChecked(True) - dialog.combo_community.setCurrentText(self.community.name()) - dialog.exec_() + person = self.get_person_from_metadata(metadata) + self.parent.certify_member(person) def send_money_to_node(self, metadata): - dialog = TransferMoneyDialog(self.account, self.password_asker) - dialog.edit_pubkey.setText(metadata['id']) - dialog.combo_community.setCurrentText(self.community.name()) - dialog.radio_pubkey.setChecked(True) - - if dialog.exec_() == QDialog.Accepted: - currency_tab = self.window().currencies_tabwidget.currentWidget() - currency_tab.table_history.model().invalidate() + person = self.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 - dialog = ConfigureContactDialog(self.account, self.window()) - dialog.edit_name.setText(metadata['text']) - dialog.edit_pubkey.setText(metadata['id']) - dialog.exec_() + person = self.get_person_from_metadata(metadata) + self.parent.add_member_as_contact(person) def get_block_mediantime(self, number): try: @@ -265,3 +252,6 @@ class WotTabWidget(QWidget, Ui_WotTabWidget): logging.debug('community.get_block request error : ' + str(e)) return False return block.mediantime + + def get_person_from_metadata(self, metadata): + return Person(metadata['text'], metadata['id'])