diff --git a/res/ui/certification.ui b/res/ui/certification.ui index fda8aba450a1ca89b154570dfdceb5113173aeb4..d171bd3c3ebf6b7792697875ee31a5b0651baf8a 100644 --- a/res/ui/certification.ui +++ b/res/ui/certification.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>399</width> - <height>216</height> + <height>283</height> </rect> </property> <property name="windowTitle"> @@ -36,14 +36,36 @@ <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QRadioButton" name="radio_contact"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> - <string>Contact</string> + <string>Con&tact</string> </property> <property name="checked"> <bool>true</bool> </property> </widget> </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> <item> <widget class="QComboBox" name="combo_contact"> <property name="enabled"> @@ -58,13 +80,29 @@ <item> <widget class="QRadioButton" name="radio_pubkey"> <property name="text"> - <string>User public key</string> + <string>&User public key</string> </property> <property name="checked"> <bool>false</bool> </property> </widget> </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> <item> <widget class="QLineEdit" name="edit_pubkey"> <property name="enabled"> @@ -83,6 +121,55 @@ </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="topMargin"> + <number>6</number> + </property> + <item> + <widget class="QRadioButton" name="radio_search"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>S&earch user</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Maximum</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="SearchUserWidget" name="search_user" native="true"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> </item> @@ -98,73 +185,16 @@ </item> </layout> </widget> + <customwidgets> + <customwidget> + <class>SearchUserWidget</class> + <extends>QWidget</extends> + <header>sakia.gui.widgets.search_user</header> + <container>1</container> + </customwidget> + </customwidgets> <resources/> - <connections> - <connection> - <sender>button_box</sender> - <signal>accepted()</signal> - <receiver>CertificationDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>button_box</sender> - <signal>rejected()</signal> - <receiver>CertificationDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>radio_pubkey</sender> - <signal>toggled(bool)</signal> - <receiver>CertificationDialog</receiver> - <slot>recipient_mode_changed(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>87</x> - <y>51</y> - </hint> - <hint type="destinationlabel"> - <x>199</x> - <y>244</y> - </hint> - </hints> - </connection> - <connection> - <sender>combo_community</sender> - <signal>currentIndexChanged(int)</signal> - <receiver>CertificationDialog</receiver> - <slot>change_current_community(int)</slot> - <hints> - <hint type="sourcelabel"> - <x>199</x> - <y>50</y> - </hint> - <hint type="destinationlabel"> - <x>199</x> - <y>165</y> - </hint> - </hints> - </connection> - </connections> + <connections/> <slots> <slot>open_manage_wallet_coins()</slot> <slot>change_displayed_wallet(int)</slot> diff --git a/src/sakia/gui/certification.py b/src/sakia/gui/certification.py index bac7688cf17e8a524cac19dc17526b9a2a32c76e..d1956eeab0f9179615623c7c4a8cbff1a06647a6 100644 --- a/src/sakia/gui/certification.py +++ b/src/sakia/gui/certification.py @@ -8,7 +8,7 @@ import logging from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QApplication, QMessageBox -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, QObject from ..gen_resources.certification_uic import Ui_CertificationDialog from sakia.gui.widgets import toast @@ -17,31 +17,51 @@ from ..tools.decorators import asyncify, once_at_a_time from ..tools.exceptions import NoPeerAvailable -class CertificationDialog(QDialog, Ui_CertificationDialog): +class CertificationDialog(QObject): """ classdocs """ - def __init__(self, app, certifier, password_asker): + def __init__(self, app, account, password_asker, widget=QDialog, view=Ui_CertificationDialog): """ - Constructor + Constructor if a certification dialog + + :param sakia.core.Application app: + :param sakia.core.Account account: + :param sakia.gui.password_asker.PasswordAsker password_asker: + :param class widget: the widget of the dialog + :param class view: the view of the certification dialog + :return: """ super().__init__() - self.setupUi(self) + self.widget = widget() + self.ui = view() + self.ui.setupUi(self.widget) self.app = app - self.account = certifier + self.account = account self.password_asker = password_asker self.community = self.account.communities[0] for community in self.account.communities: - self.combo_community.addItem(community.currency) - - for contact_name in sorted([c['name'] for c in certifier.contacts], key=str.lower): - self.combo_contact.addItem(contact_name) - - if len(certifier.contacts) == 0: - self.radio_pubkey.setChecked(True) - self.radio_contact.setEnabled(False) + self.ui.combo_community.addItem(community.currency) + + for contact_name in sorted([c['name'] for c in account.contacts], key=str.lower): + self.ui.combo_contact.addItem(contact_name) + + if len(account.contacts) == 0: + self.ui.radio_pubkey.setChecked(True) + self.ui.radio_contact.setEnabled(False) + + 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.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_community(self.community) + self.ui.combo_community.currentIndexChanged.connect(self.change_current_community) @classmethod async def certify_identity(cls, app, account, password_asker, community, identity): @@ -55,25 +75,30 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): :return: """ dialog = cls(app, account, password_asker) - dialog.combo_community.setCurrentText(community.name) - dialog.edit_pubkey.setText(identity.pubkey) - dialog.radio_pubkey.setChecked(True) + dialog.ui.combo_community.setCurrentText(community.name) + dialog.ui.edit_pubkey.setText(identity.pubkey) + dialog.ui.radio_pubkey.setChecked(True) return await dialog.async_exec() @asyncify async def accept(self): - self.button_box.setEnabled(False) - if self.radio_contact.isChecked(): + self.ui.button_box.setEnabled(False) + if self.ui.radio_contact.isChecked(): for contact in self.account.contacts: - if contact['name'] == self.combo_contact.currentText(): + if contact['name'] == self.ui.combo_contact.currentText(): pubkey = contact['pubkey'] break + elif self.ui.radio_search.isChecked(): + if self.ui.search_user.current_identity(): + pubkey = self.ui.search_user.current_identity().pubkey + else: + return else: - pubkey = self.edit_pubkey.text() + pubkey = self.ui.edit_pubkey.text() password = await self.password_asker.async_exec() if password == "": - self.button_box.setEnabled(True) + self.ui.button_box.setEnabled(True) return QApplication.setOverrideCursor(Qt.WaitCursor) result = await self.account.certify(password, self.community, pubkey) @@ -85,7 +110,7 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): await QAsyncMessageBox.information(self, self.tr("Certification"), self.tr("Success sending certification")) QApplication.restoreOverrideCursor() - super().accept() + self.widget.accept() else: if self.app.preferences['notifications']: toast.display(self.tr("Certification"), self.tr("Could not broadcast certification : {0}" @@ -95,10 +120,11 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): self.tr("Could not broadcast certification : {0}" .format(result[1]))) QApplication.restoreOverrideCursor() - self.button_box.setEnabled(True) + self.ui.button_box.setEnabled(True) def change_current_community(self, index): self.community = self.account.communities[index] + self.ui.search_user.change_community(self.community) if self.isVisible(): self.refresh() @@ -117,11 +143,11 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): block_0 = None if is_member or not block_0: - self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) - self.button_box.button(QDialogButtonBox.Ok).setText(self.tr("&Ok")) + self.ui.button_box.button(QDialogButtonBox.Ok).setEnabled(True) + self.ui.button_box.button(QDialogButtonBox.Ok).setText(self.tr("&Ok")) else: - self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) - self.button_box.button(QDialogButtonBox.Ok).setText(self.tr("Not a member")) + self.ui.button_box.button(QDialogButtonBox.Ok).setEnabled(False) + self.ui.button_box.button(QDialogButtonBox.Ok).setText(self.tr("Not a member")) def showEvent(self, event): super().showEvent(event) @@ -136,13 +162,20 @@ class CertificationDialog(QDialog, Ui_CertificationDialog): 3.) Don't certify an account if you believe the issuer purposely or carelessly violates rule 1 or 2 (the issuer certifies faked or double accounts """) - def recipient_mode_changed(self, pubkey_toggled): - self.edit_pubkey.setEnabled(pubkey_toggled) - self.combo_contact.setEnabled(not pubkey_toggled) + def recipient_mode_changed(self, radio): + """ + :param str 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.finished.connect(lambda r: future.set_result(r)) - self.open() + self.widget.open() self.refresh() return future + + def exec(self): + self.widget.exec() diff --git a/src/sakia/gui/mainwindow.py b/src/sakia/gui/mainwindow.py index a7f6e69ef671ec613ee7fd21e60a4f57e6b7ae49..1538cd59984883b99c14e996eaa74124e758374a 100644 --- a/src/sakia/gui/mainwindow.py +++ b/src/sakia/gui/mainwindow.py @@ -180,7 +180,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): dialog = CertificationDialog(self.app, self.app.current_account, self.password_asker) - dialog.exec_() + dialog.exec() def open_add_contact_dialog(self): dialog = ConfigureContactDialog(self.app.current_account, self) diff --git a/src/sakia/gui/widgets/search_user.py b/src/sakia/gui/widgets/search_user.py index 994d37f673470f06492a8112d6f71e07739b68e4..e93b906e39abfcfd01d07b1a66651055ef9beaba 100644 --- a/src/sakia/gui/widgets/search_user.py +++ b/src/sakia/gui/widgets/search_user.py @@ -1,6 +1,6 @@ import logging -from PyQt5.QtCore import QEvent, pyqtSignal, QT_TRANSLATE_NOOP +from PyQt5.QtCore import QEvent, pyqtSignal, QT_TRANSLATE_NOOP, Qt from PyQt5.QtWidgets import QComboBox, QWidget from ucoinpy.api import bma @@ -37,6 +37,10 @@ class SearchUserWidget(QWidget, Ui_SearchUserWidget): self.community = None self.account = None self.app = None + self._current_identity = None + + def current_identity(self): + return self._current_identity def init(self, app): """ @@ -94,17 +98,19 @@ class SearchUserWidget(QWidget, Ui_SearchUserWidget): Select node in graph when item is selected in combobox """ if index < 0 or index >= len(self.nodes): + self._current_identity = None return False node = self.nodes[index] metadata = {'id': node['pubkey'], 'text': node['uid']} - self.identity_selected.emit( - self.app.identities_registry.from_handled_data( + self._current_identity = self.app.identities_registry.from_handled_data( metadata['text'], metadata['id'], None, BlockchainState.VALIDATED, self.community ) + self.identity_selected.emit( + self._current_identity ) def retranslateUi(self, widget): @@ -113,3 +119,9 @@ class SearchUserWidget(QWidget, Ui_SearchUserWidget): """ self.combobox_search.lineEdit().setPlaceholderText(self.tr(SearchUserWidget._search_placeholder)) super().retranslateUi(self) + + def keyPressEvent(self, event): + if event.key() == Qt.Key_Return: + return + + super().keyPressEvent(event)