diff --git a/src/sakia/data/processors/identities.py b/src/sakia/data/processors/identities.py index 4a78f8536afc8a4990d4cc215aaf6d645436c70c..f697c363f1c1fff54d0b51b23833e5ded16c2699 100644 --- a/src/sakia/data/processors/identities.py +++ b/src/sakia/data/processors/identities.py @@ -87,8 +87,6 @@ class IdentitiesProcessor: except (errors.DuniterError, asyncio.TimeoutError, ClientError) as e: tries += 1 self._logger.debug(str(e)) - except NoPeerAvailable as e: - self._logger.debug(str(e)) return identities def get_written(self, currency, pubkey): diff --git a/src/sakia/data/processors/transactions.py b/src/sakia/data/processors/transactions.py index 25b8399086be6331479e842147413bc30c2b3a9b..d573ff0a9ee6a1af13c5f576e415384506ce6933 100644 --- a/src/sakia/data/processors/transactions.py +++ b/src/sakia/data/processors/transactions.py @@ -113,6 +113,7 @@ class TransactionsProcessor: :param txdoc: A transaction duniterpy object :param currency: The community target of the transaction """ + self._repo.insert(tx) responses = await self._bma_connector.broadcast(currency, bma.tx.process, req_args={'transaction': txdoc.signed_raw()}) result = (False, "") for r in responses: diff --git a/src/sakia/gui/dialogs/transfer/controller.py b/src/sakia/gui/dialogs/transfer/controller.py index c9a368a4eff6a2d3d43cf7c9098c20a0b0139460..8e1f43de02f5aef64867fe551764f80ee829c5d8 100644 --- a/src/sakia/gui/dialogs/transfer/controller.py +++ b/src/sakia/gui/dialogs/transfer/controller.py @@ -21,8 +21,8 @@ class TransferController(QObject): """ Constructor of the transfer component - :param sakia.gui.transfer.view.TransferView: the view - :param sakia.gui.transfer.model.TransferModel model: the model + :param sakia.gui.dialogs.transfer.view.TransferView: the view + :param sakia.gui.dialogs.transfer.model.TransferModel model: the model """ super().__init__() self.view = view @@ -54,6 +54,8 @@ class TransferController(QObject): user_information = UserInformationController.create(transfer, app, "", None) transfer.set_user_information(user_information) + search_user.identity_selected.connect(user_information.search_identity) + view.set_keys(transfer.model.available_connections()) return transfer @@ -61,16 +63,14 @@ class TransferController(QObject): def open_dialog(cls, parent, app, connection): dialog = cls.create(parent, app) if connection: - dialog.view.combo_currency.setCurrentText(connection.currency) - dialog.view.combo_wallets.setCurrentText(connection.title()) + dialog.view.combo_connections.setCurrentText(connection.title()) dialog.refresh() return dialog.exec() @classmethod async def send_money_to_identity(cls, parent, app, connection, identity): dialog = cls.create(parent, app) - dialog.view.combo_currency.setCurrentText(identity.currency) - dialog.view.combo_wallets.setCurrentText(connection.title()) + dialog.view.combo_connections.setCurrentText(connection.title()) dialog.view.edit_pubkey.setText(identity.pubkey) dialog.view.radio_pubkey.setChecked(True) @@ -80,8 +80,7 @@ class TransferController(QObject): @classmethod async def send_transfer_again(cls, parent, app, connection, resent_transfer): dialog = cls.create(parent, app) - dialog.view.combo_currency.setCurrentText(resent_transfer.currency) - dialog.view.combo_wallets.setCurrentText(connection.title()) + dialog.view.combo_connections.setCurrentText(connection.title()) dialog.view.edit_pubkey.setText(resent_transfer.receiver) dialog.view.radio_pubkey.setChecked(True) @@ -93,7 +92,7 @@ class TransferController(QObject): account = resent_transfer.metadata['issuer'] wallet_index = [w.pubkey for w in app.current_account.wallets].index(account) - dialog.view.combo_wallets.setCurrentIndex(wallet_index) + dialog.view.combo_connections.setCurrentIndex(wallet_index) dialog.view.edit_pubkey.setText(resent_transfer.metadata['receiver']) dialog.view.radio_pubkey.setChecked(True) dialog.view.edit_message.setText(resent_transfer.metadata['comment']) @@ -108,7 +107,6 @@ class TransferController(QObject): """ self.search_user = search_user self.view.set_search_user(search_user.view) - search_user.identity_selected.connect(self.refresh_user_information) def set_user_information(self, user_information): """ @@ -119,13 +117,6 @@ class TransferController(QObject): self.user_information = user_information self.view.set_user_information(user_information.view) - def refresh_user_information(self): - """ - Refresh user information - """ - pubkey = self.selected_pubkey() - self.user_information.search_identity(pubkey) - def selected_pubkey(self): """ Get selected pubkey in the widgets of the window @@ -224,6 +215,8 @@ class TransferController(QObject): def change_current_connection(self, index): self.model.set_connection(index) + self.search_user.set_currency(self.model.connection.currency) + self.user_information.set_currency(self.model.connection.currency) self.refresh() def async_exec(self): diff --git a/src/sakia/gui/dialogs/transfer/model.py b/src/sakia/gui/dialogs/transfer/model.py index 91c8072b0470fb3ec4a6f5541c1e8519fa68a8da..3d6ce2668c663e9e48f72998544759d60c8efb9e 100644 --- a/src/sakia/gui/dialogs/transfer/model.py +++ b/src/sakia/gui/dialogs/transfer/model.py @@ -26,13 +26,13 @@ class TransferModel(QObject): self._sources_processor = SourcesProcessor.instanciate(self.app) self._connections_processor = ConnectionsProcessor.instanciate(self.app) - async def rel_to_quant(self, rel_value): + def rel_to_quant(self, rel_value): """ Get the quantitative value of a relative amount :param float rel_value: :rtype: int """ - dividend, base = await self._blockchain_processor.last_ud(self.connection.currency) + dividend, base = self._blockchain_processor.last_ud(self.connection.currency) amount = rel_value * dividend * pow(10, base) # amount is rounded to the nearest power of 10 depending of last ud base rounded = int(pow(10, base) * round(float(amount) / pow(10, base))) @@ -93,8 +93,10 @@ class TransferModel(QObject): :return: the result of the send """ - return await self.app.documents_service.send_money(self.connection, password, + result = await self.app.documents_service.send_money(self.connection, password, recipient, amount, amount_base, comment) + self.app.db.commit() + return result def notifications(self): return self.app.parameters.notifications diff --git a/src/sakia/gui/dialogs/transfer/transfer.py b/src/sakia/gui/dialogs/transfer/transfer.py deleted file mode 100644 index 343b93f33c2987dd5a65e28f5e206dc46283490f..0000000000000000000000000000000000000000 --- a/src/sakia/gui/dialogs/transfer/transfer.py +++ /dev/null @@ -1,252 +0,0 @@ -""" -Created on 2 févr. 2014 - -@author: inso -""" -import asyncio -import logging - -from PyQt5.QtWidgets import QDialog, QApplication, QDialogButtonBox -from PyQt5.QtCore import QRegExp, Qt, QObject - -from PyQt5.QtGui import QRegExpValidator - -from ..presentation.transfer_uic import Ui_TransferMoneyDialog -from .widgets import toast -from .widgets.dialogs import QAsyncMessageBox, QMessageBox -from ..tools.decorators import asyncify - - -class TransferMoneyDialog(QObject): - - """ - classdocs - """ - - def __init__(self, app, account, password_asker, community, transfer, widget=QDialog, view=Ui_TransferMoneyDialog): - """ - Constructor - :param sakia.core.Application app: The application - :param sakia.core.Account account: The account - :param sakia.gui.password_asker.Password_Asker password_asker: The password asker - :param sakia.core.Community community: - :param sakia.core.Transfer transfer: - :param class widget: - :param class view: - :return: - """ - super().__init__() - self.widget = widget() - self.ui = view() - self.ui.setupUi(self.widget) - - self.app = app - self.account = account - self.password_asker = password_asker - self.recipient_trusts = [] - self.transfer = transfer - self.wallet = None - self.community = community if community else self.account.communities[0] - self.wallet = self.account.wallets[0] - - self.ui.radio_contact.toggled.connect(lambda c, radio="contact": self.recipient_mode_changed(radio)) - self.ui.radio_pubkey.toggled.connect(lambda c, radio="pubkey": self.recipient_mode_changed(radio)) - self.ui.radio_search.toggled.connect(lambda c, radio="search": self.recipient_mode_changed(radio)) - self.ui.button_box.accepted.connect(self.accept) - self.ui.button_box.rejected.connect(self.widget.reject) - self.ui.combo_wallets.currentIndexChanged.connect(self.change_displayed_wallet) - self.ui.combo_community.currentIndexChanged.connect(self.change_current_community) - self.ui.spinbox_relative.valueChanged.connect(self.relative_amount_changed) - self.ui.spinbox_amount.valueChanged.connect(self.amount_changed) - self.ui.search_user.button_reset.hide() - self.ui.search_user.init(self.app) - self.ui.search_user.change_account(self.account) - self.ui.search_user.change_currency(self.community) - self.ui.search_user.search_started.connect(lambda: self.ui.button_box.setEnabled(False)) - self.ui.search_user.search_completed.connect(lambda: self.ui.button_box.setEnabled(True)) - - regexp = QRegExp('^([ a-zA-Z0-9-_:/;*?\[\]\(\)\\\?!^+=@&~#{}|<>%.]{0,255})$') - validator = QRegExpValidator(regexp) - self.ui.edit_message.setValidator(validator) - - for community in self.account.communities: - self.ui.combo_community.addItem(community.currency) - - for wallet in self.account.wallets: - self.ui.combo_wallets.addItem(wallet.name) - - for contact_name in sorted([c['name'] for c in account.contacts], key=str.lower): - self.ui.combo_contact.addItem(contact_name) - - if len(self.account.contacts) == 0: - self.ui.combo_contact.setEnabled(False) - self.ui.radio_contact.setEnabled(False) - self.ui.radio_pubkey.setChecked(True) - - self.ui.combo_community.setCurrentText(self.community.name) - - if self.transfer: - account = self.transfer.metadata['issuer'] - wallet_index = [w.pubkey for w in app.current_account.wallets].index(account) - self.ui.combo_wallets.setCurrentIndex(wallet_index) - self.ui.edit_pubkey.setText(transfer.metadata['receiver']) - self.ui.radio_pubkey.setChecked(True) - self.ui.edit_message.setText(transfer.metadata['comment']) - - @classmethod - async def send_money_to_identity(cls, app, account, password_asker, community, identity): - dialog = cls(app, account, password_asker, community, None) - dialog.ui.edit_pubkey.setText(identity.pubkey) - dialog.ui.radio_pubkey.setChecked(True) - return await dialog.async_exec() - - @classmethod - async def send_transfer_again(cls, app, account, password_asker, community, transfer): - dialog = cls(app, account, password_asker, community, transfer) - dividend = await community.dividend() - relative = transfer.metadata['amount'] / dividend - dialog.ui.spinbox_amount.setMaximum(transfer.metadata['amount']) - dialog.ui.spinbox_relative.setMaximum(relative) - dialog.ui.spinbox_amount.setValue(transfer.metadata['amount']) - - return await dialog.async_exec() - - @asyncify - async def accept(self): - logging.debug("Accept transfer action...") - self.ui.button_box.setEnabled(False) - comment = self.ui.edit_message.text() - - logging.debug("checking recipient mode...") - if self.ui.radio_contact.isChecked(): - for contact in self.account.contacts: - if contact['name'] == self.ui.combo_contact.currentText(): - recipient = contact['pubkey'] - break - elif self.ui.radio_search.isChecked(): - if self.ui.search_user.current_identity(): - recipient = self.ui.search_user.current_identity().pubkey - else: - return - else: - recipient = self.ui.edit_pubkey.text() - amount = self.ui.spinbox_amount.value() - - logging.debug("checking amount...") - if not amount: - await QAsyncMessageBox.critical(self.widget, self.tr("Money transfer"), - self.tr("No amount. Please give the transfert amount"), - QMessageBox.Ok) - self.ui.button_box.setEnabled(True) - return - logging.debug("Showing password dialog...") - password = await self.password_asker.async_exec() - if self.password_asker.result() == QDialog.Rejected: - self.ui.button_box.setEnabled(True) - return - - logging.debug("Setting cursor...") - QApplication.setOverrideCursor(Qt.WaitCursor) - - logging.debug("Send money...") - result = await self.wallet.send_money(self.account.salt, password, self.community, - recipient, amount, comment) - if result[0]: - logging.debug("Checking result to display...") - if self.app.preferences['notifications']: - toast.display(self.tr("Transfer"), - self.tr("Success sending money to {0}").format(recipient)) - else: - await QAsyncMessageBox.information(self.widget, self.tr("Transfer"), - self.tr("Success sending money to {0}").format(recipient)) - logging.debug("Restore cursor...") - QApplication.restoreOverrideCursor() - - # If we sent back a transaction we cancel the first one - if self.transfer: - self.transfer.cancel() - self.app.refresh_transfers.emit() - self.widget.accept() - else: - logging.debug("Error occured...") - if self.app.preferences['notifications']: - toast.display(self.tr("Transfer"), "Error : {0}".format(result[1])) - else: - await QAsyncMessageBox.critical(self.widget, self.tr("Transfer"), result[1]) - - QApplication.restoreOverrideCursor() - self.ui.button_box.setEnabled(True) - - @asyncify - async def amount_changed(self, value): - ud_block = await self.community.get_ud_block() - if ud_block: - dividend = ud_block['dividend'] - base = ud_block['unitbase'] - else: - dividend = 1 - base = 0 - relative = value / (dividend * pow(10, base)) - self.ui.spinbox_relative.blockSignals(True) - self.ui.spinbox_relative.setValue(relative) - self.ui.spinbox_relative.blockSignals(False) - correct_amount = int(pow(10, base) * round(float(value) / pow(10, base))) - self.ui.button_box.button(QDialogButtonBox.Ok).setEnabled(correct_amount == value) - - @asyncify - async def relative_amount_changed(self, value): - self.ui.spinbox_amount.blockSignals(True) - self.ui.spinbox_amount.setValue(amount) - self.ui.spinbox_amount.blockSignals(False) - self.ui.button_box.button(QDialogButtonBox.Ok).setEnabled(True) - - @asyncify - async def change_current_community(self, index): - self.community = self.account.communities[index] - amount = await self.wallet.value(self.community) - - ref_text = await self.account.current_ref.instance(amount, self.community, self.app)\ - .diff_localized(units=True, - international_system=self.app.preferences['international_system_of_units']) - self.ui.label_total.setText("{0}".format(ref_text)) - self.ui.spinbox_amount.setSuffix(" " + self.community.currency) - await self.refresh_spinboxes() - - @asyncify - async def change_displayed_wallet(self, index): - self.wallet = self.account.wallets[index] - amount = await self.wallet.value(self.community) - ref_text = await self.account.current_ref.instance(amount, self.community, self.app)\ - .diff_localized(units=True, - international_system=self.app.preferences['international_system_of_units']) - self.ui.label_total.setText("{0}".format(ref_text)) - await self.refresh_spinboxes() - - async def refresh_spinboxes(self): - max_amount = await self.wallet.value(self.community) - ud_block = await self.community.get_ud_block() - if ud_block: - dividend = ud_block['dividend'] - base = ud_block['unitbase'] - else: - dividend = 1 - base = 0 - max_amount = int(pow(10, base) * round(float(max_amount) / pow(10, base))) - max_relative = max_amount / dividend - self.ui.spinbox_amount.setMaximum(max_amount) - self.ui.spinbox_relative.setMaximum(max_relative) - self.ui.spinbox_amount.setSingleStep(pow(10, base)) - - def recipient_mode_changed(self, radio): - self.ui.edit_pubkey.setEnabled(radio == "pubkey") - self.ui.combo_contact.setEnabled(radio == "contact") - self.ui.search_user.setEnabled(radio == "search") - - def async_exec(self): - future = asyncio.Future() - self.widget.finished.connect(lambda r: future.set_result(r) and self.widget.finished.disconnect()) - self.widget.open() - return future - - def exec(self): - self.widget.exec() \ No newline at end of file diff --git a/src/sakia/gui/navigation/txhistory/model.py b/src/sakia/gui/navigation/txhistory/model.py index a3830d1e71dc166cf8fea5e0f1feb236b5c47168..d20c6254866f3211beea697cecf49a85758a680a 100644 --- a/src/sakia/gui/navigation/txhistory/model.py +++ b/src/sakia/gui/navigation/txhistory/model.py @@ -47,6 +47,7 @@ class TxHistoryModel(QObject): self._proxy.setDynamicSortFilter(True) self._proxy.setSortRole(Qt.DisplayRole) self._model.refresh_transfers() + self.app.new_transfer.connect(self._model.add_transfer) return self._proxy diff --git a/src/sakia/gui/navigation/txhistory/table_model.py b/src/sakia/gui/navigation/txhistory/table_model.py index 08fe5cb2a7947775e6fe8a0353a753b96b9b6a1c..c587b9d2153e89b8b051300288127ae299a86608 100644 --- a/src/sakia/gui/navigation/txhistory/table_model.py +++ b/src/sakia/gui/navigation/txhistory/table_model.py @@ -10,7 +10,7 @@ import logging import math from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant, QSortFilterProxyModel, \ - QDateTime, QLocale + QDateTime, QLocale, QModelIndex from PyQt5.QtGui import QFont, QColor, QIcon from sakia.errors import NoPeerAvailable from sakia.data.entities import Transaction @@ -234,6 +234,15 @@ class HistoryTableModel(QAbstractTableModel): #TODO: Handle dividends return self.transactions_service.transfers(self.connection.pubkey) + def add_transfer(self, transfer): + self.beginInsertRows(QModelIndex(), 0, 0) + if type(transfer) is Transaction: + if transfer.issuer == self.connection.pubkey: + self.transfers_data.append(self.data_sent(transfer)) + else: + self.transfers_data.append(self.data_received(transfer)) + self.endInsertRows() + def data_received(self, transfer): """ Converts a transaction to table data