diff --git a/src/sakia/core/registry/identity.py b/src/sakia/core/registry/identity.py index fcc16720a99c12e2f79b5aea89fc323a79452c91..200265631a00afa660268e582a0179242d312604 100644 --- a/src/sakia/core/registry/identity.py +++ b/src/sakia/core/registry/identity.py @@ -147,8 +147,6 @@ class Identity(QObject): raise LookupFailureError(self.pubkey, community) except MalformedDocumentError: raise LookupFailureError(self.pubkey, community) - except NoPeerAvailable: - logging.debug("No peer available") async def get_join_date(self, community): """ diff --git a/src/sakia/gui/certification/controller.py b/src/sakia/gui/certification/controller.py index eee867cb04de40643dfdb064e3d2976a8903383f..4d9171a1ede6807adc694ef5970efc8185a13bf4 100644 --- a/src/sakia/gui/certification/controller.py +++ b/src/sakia/gui/certification/controller.py @@ -2,6 +2,7 @@ from ..component.controller import ComponentController from .view import CertificationView from .model import CertificationModel from ..search_user.controller import SearchUserController +from ..user_information.controller import UserInformationController from PyQt5.QtWidgets import QApplication from PyQt5.QtCore import Qt from ...tools.decorators import asyncify, once_at_a_time @@ -13,19 +14,21 @@ class CertificationController(ComponentController): The Certification view """ - def __init__(self, parent, view, model, search_user): + def __init__(self, parent, view, model, search_user, user_information): """ Constructor of the Certification component - :param sakia.gui.Certification.view.CertificationView: the view - :param sakia.gui.Certification.model.CertificationModel model: the model - :param sakia.gui.SearchUser.controller.SearchUserController search_user: the search user component + :param sakia.gui.certification.view.CertificationView: the view + :param sakia.gui.certification.model.CertificationModel model: the model + :param sakia.gui.search_user.controller.SearchUserController search_user: the search user component + :param sakia.gui.user_information.controller.UserInformationController search_user: the search user component """ super().__init__(parent, view, model) self.view.button_box.accepted.connect(self.accept) self.view.button_box.rejected.connect(self.reject) self.view.combo_community.currentIndexChanged.connect(self.change_current_community) self.search_user = search_user + self.user_information = user_information @classmethod def create(cls, parent, app, **kwargs): @@ -40,12 +43,20 @@ class CertificationController(ComponentController): communities_names = [c.name for c in account.communities] contacts_names = [c['name'] for c in account.contacts] - view = CertificationView(parent.view, None, communities_names, contacts_names) + view = CertificationView(parent.view, None, None, communities_names, contacts_names) model = CertificationModel(None, app, account, community) - certification = cls(parent, view, model, None) - - search_user = SearchUserController.create(certification, app, account=model.account, community=model.community) - view.set_search_user(search_user.view) + certification = cls(parent, view, model, None, None) + + search_user = SearchUserController.create(certification, app, + account=model.account, + community=model.community) + certification.set_search_user(search_user) + + user_information = UserInformationController.create(certification, app, + account=model.account, + community=model.community, + identity=None) + certification.set_user_information(user_information) model.setParent(certification) return certification @@ -62,7 +73,7 @@ class CertificationController(ComponentController): """ dialog = cls.create(parent, app, account=account, community=community, password_asker=password_asker) if community: - dialog.ui.combo_community.setCurrentText(community.name) + dialog.view.combo_community.setCurrentText(community.name) dialog.refresh() return dialog.exec() @@ -93,6 +104,25 @@ class CertificationController(ComponentController): def model(self) -> CertificationModel: return self._model + def set_search_user(self, search_user): + """ + + :param search_user: + :return: + """ + 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): + """ + + :param user_information: + :return: + """ + self.user_information = user_information + self.view.set_user_information(user_information.view) + @asyncify async def accept(self): """ @@ -160,10 +190,17 @@ class CertificationController(ComponentController): else: self.view.set_button_box(CertificationView.ButtonBoxState.NOT_A_MEMBER) + def refresh_user_information(self): + """ + Refresh user information + """ + pubkey = self.selected_pubkey() + self.user_information.search_identity(pubkey) + def change_current_community(self, index): self.model.change_community(index) self.search_user.set_community(self.community) - #self.member_widget.change_community(self.community) + self.member_widget.change_community(self.community) self.refresh() def async_exec(self): diff --git a/src/sakia/gui/certification/view.py b/src/sakia/gui/certification/view.py index 3afba6ff21a7368ba48151ff8e0c5a284034ca33..98df71845f25279536677c2b7295e61a5d31cc25 100644 --- a/src/sakia/gui/certification/view.py +++ b/src/sakia/gui/certification/view.py @@ -1,5 +1,5 @@ from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox -from PyQt5.QtCore import QT_TRANSLATE_NOOP +from PyQt5.QtCore import QT_TRANSLATE_NOOP, pyqtSignal from .certification_uic import Ui_CertificationDialog from ..widgets import toast from ..widgets.dialogs import QAsyncMessageBox @@ -32,9 +32,16 @@ class CertificationView(QDialog, Ui_CertificationDialog): ButtonBoxState.OK: (True, QT_TRANSLATE_NOOP("CertificationView", "&Ok")) } - def __init__(self, parent, search_user_view, communities_names, contacts_names): + pubkey_changed = pyqtSignal() + + def __init__(self, parent, search_user_view, user_information_view, communities_names, contacts_names): """ - Constructor + + :param parent: + :param sakia.gui.search_user.view.SearchUserView search_user_view: + :param sakia.gui.user_information.view.UserInformationView user_information_view: + :param list[str] communities_names: + :param list[str] contacts_names: """ super().__init__(parent) self.setupUi(self) @@ -54,13 +61,13 @@ class CertificationView(QDialog, Ui_CertificationDialog): self.radio_contact.setEnabled(False) self.search_user = search_user_view + self.user_information_view = user_information_view - #self.combo_contact.currentIndexChanged.connect(self.refresh_member) - #self.edit_pubkey.textChanged.connect(self.refresh_member) - #self.search_user.identity_selected.connect(self.refresh_member) - #self.radio_contact.toggled.connect(self.refresh_member) - #self.radio_search.toggled.connect(self.refresh_member) - #self.radio_pubkey.toggled.connect(self.refresh_member) + self.combo_contact.currentIndexChanged.connect(self.pubkey_changed) + self.edit_pubkey.textChanged.connect(self.pubkey_changed) + self.radio_contact.toggled.connect(self.pubkey_changed) + self.radio_search.toggled.connect(self.pubkey_changed) + self.radio_pubkey.toggled.connect(self.pubkey_changed) def set_search_user(self, search_user_view): """ @@ -72,8 +79,9 @@ class CertificationView(QDialog, Ui_CertificationDialog): self.layout_mode_search.addWidget(search_user_view) self.search_user.button_reset.hide() - def set_member_widget(self, member_widget): - self.horizontalLayout_5.addWidget(member_widget) + def set_user_information(self, user_information_view): + self.user_information_view = user_information_view + self.layout_target_choice.addWidget(user_information_view) def recipient_mode(self): if self.radio_contact.isChecked(): @@ -129,6 +137,7 @@ class CertificationView(QDialog, Ui_CertificationDialog): else: remaining_localized = self.tr("{hours} hours and {min} min.").format(hours=remaining_hours, min=remaining_minutes) + cert_text += "\n" cert_text += self.tr("Remaining time before next certification validation : {0}".format(remaining_localized)) self.label_cert_stock.setText(cert_text) @@ -150,4 +159,3 @@ class CertificationView(QDialog, Ui_CertificationDialog): self.edit_pubkey.setEnabled(radio == CertificationView.RecipientMode.PUBKEY) self.combo_contact.setEnabled(radio == CertificationView.RecipientMode.CONTACT) self.search_user.setEnabled(radio == CertificationView.RecipientMode.SEARCH) - diff --git a/src/sakia/gui/homescreen/view.py b/src/sakia/gui/homescreen/view.py index 5f8f92acc6c2f6d4b42f14382356b5ce090a2241..828780f12b75a11de3d7fee306e38d774fda5949 100644 --- a/src/sakia/gui/homescreen/view.py +++ b/src/sakia/gui/homescreen/view.py @@ -4,7 +4,7 @@ from .homescreen_uic import Ui_HomescreenWidget class HomeScreenView(QWidget, Ui_HomescreenWidget): """ - classdocs + Home screen view """ def __init__(self, parent): diff --git a/src/sakia/gui/member.py b/src/sakia/gui/member.py deleted file mode 100644 index d81d312ccc11eadb7cb73292a38fac71b38992f2..0000000000000000000000000000000000000000 --- a/src/sakia/gui/member.py +++ /dev/null @@ -1,155 +0,0 @@ -import datetime - -from PyQt5.QtCore import QObject, QEvent, QLocale, QDateTime -from PyQt5.QtWidgets import QDialog, QWidget - -from ..core.graph import WoTGraph -from .widgets.busy import Busy -from ..tools.decorators import asyncify -from ..presentation.member_uic import Ui_MemberView -from ..tools.exceptions import MembershipNotFoundError, LookupFailureError, NoPeerAvailable -from ..core.registry import LocalState - - -class MemberDialog(QObject): - """ - A widget showing informations about a member - """ - - def __init__(self, app, account, community, identity, widget, ui): - """ - Init MemberDialog - - :param sakia.core.app.Application app: Application instance - :param sakia.core.account.Account account: Account instance - :param sakia.core.community.Community community: Community instance - :param sakia.core.registry.identity.Identity identity: Identity instance - :param PyQt5.QtWidget widget: The class of the widget - :param sakia.presentation.member_uic.Ui_DialogMember ui: the class of the ui applyed to the widget - :return: - """ - super().__init__() - self.widget = widget - self.ui = ui - self.ui.setupUi(self.widget) - self.ui.busy = Busy(self.widget) - self.widget.installEventFilter(self) - self.app = app - self.community = community - self.account = account - self.identity = identity - - @classmethod - def open_dialog(cls, app, account, community, identity): - dialog = cls(app, account, community, identity, QDialog(), Ui_MemberView()) - dialog.refresh() - dialog.refresh_path() - dialog.exec() - - @classmethod - def as_widget(cls, parent_widget, app, account, community, identity): - return cls(app, account, community, identity, QWidget(parent_widget), Ui_MemberView()) - - def change_community(self, community): - """ - Change current community - :param sakia.core.Community community: the new community - """ - self.community = community - self.refresh() - - @asyncify - async def refresh(self): - if self.identity and self.identity.local_state != LocalState.NOT_FOUND: - self.ui.busy.show() - self.ui.label_uid.setText(self.identity.uid) - self.ui.label_properties.setText("") - try: - identity_selfcert = await self.identity.selfcert(self.community) - publish_time = await self.community.time(identity_selfcert.timestamp.number) - - join_date = await self.identity.get_join_date(self.community) - if join_date is None: - join_date = self.tr('not a member') - else: - join_date = datetime.datetime.fromtimestamp(join_date).strftime("%d/%m/%Y %I:%M") - - except MembershipNotFoundError: - join_date = "###" - except (LookupFailureError, NoPeerAvailable): - publish_time = None - join_date = "###" - - if publish_time: - uid_publish_date = QLocale.toString( - QLocale(), - QDateTime.fromTime_t(publish_time), - QLocale.dateTimeFormat(QLocale(), QLocale.ShortFormat) - ) - else: - uid_publish_date = "###" - - text = self.tr(""" - <table cellpadding="5"> - <tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr> - <tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr> - <tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr> - """).format( - self.tr('Public key'), - self.identity.pubkey, - self.tr('UID Published on'), - uid_publish_date, - self.tr('Join date'), - join_date - ) - # close html text - text += "</table>" - - # set text in label - self.ui.label_properties.setText(text) - self.ui.busy.hide() - - @asyncify - async def refresh_path(self): - text = "" - self.ui.label_path.setText("") - # calculate path to account member - graph = WoTGraph(self.app, self.community) - path = None - # if selected member is not the account member... - if self.identity.pubkey != self.account.pubkey: - # add path from us to him - account_identity = await self.account.identity(self.community) - path = await graph.get_shortest_path_to_identity(self.identity, - account_identity) - nodes = graph.nx_graph.nodes(data=True) - - if path: - distance = len(path) - 1 - text += self.tr( - """<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""" - .format(self.tr('Distance'), distance)) - if distance > 1: - index = 0 - for node_id in path: - node = [n for n in nodes if n[0] == node_id][0] - if index == 0: - text += self.tr("""<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""")\ - .format(self.tr('Path'), node[1]['text']) - else: - text += self.tr("""<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""")\ - .format('', node[1]['text'] ) - if index == distance and node_id != self.account.pubkey: - text += self.tr("""<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""")\ - .format('', self.account.name) - index += 1 - self.ui.label_path.setText(text) - - def eventFilter(self, source, event): - if event.type() == QEvent.Resize: - self.ui.busy.resize(event.size()) - self.widget.resizeEvent(event) - return self.widget.eventFilter(source, event) - - def exec(self): - self.widget.exec() diff --git a/src/sakia/gui/search_user/controller.py b/src/sakia/gui/search_user/controller.py index ba26cc77be7f6d8a77443c20338d8c3dfb6e49a8..1963b41e0168e15eaac92119072f6ff9461c0e1f 100644 --- a/src/sakia/gui/search_user/controller.py +++ b/src/sakia/gui/search_user/controller.py @@ -55,6 +55,13 @@ class SearchUserController(ComponentController): user_nodes = self.model.user_nodes() self.view.set_search_result(text, user_nodes) + def current_identity(self): + """ + + :rtype: sakia.core.registry.Identity + """ + return self.model.identity() + def select_node(self, index): """ Select node in graph when item is selected in combobox diff --git a/src/sakia/gui/user_information/__init__.py b/src/sakia/gui/user_information/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/sakia/gui/user_information/controller.py b/src/sakia/gui/user_information/controller.py new file mode 100644 index 0000000000000000000000000000000000000000..a2210059c484ad5b828569d4743b5a757ee86e29 --- /dev/null +++ b/src/sakia/gui/user_information/controller.py @@ -0,0 +1,97 @@ +from ..component.controller import ComponentController +from .view import UserInformationView +from .model import UserInformationModel +from sakia.tools.decorators import asyncify +from sakia.core.registry import LocalState +from PyQt5.QtWidgets import QDialog + + +class UserInformationController(ComponentController): + """ + The homescreen view + """ + + def __init__(self, parent, view, model): + """ + Constructor of the homescreen component + + :param sakia.gui.homescreen.view.HomeScreenView: the view + :param sakia.gui.homescreen.model.HomeScreenModel model: the model + """ + super().__init__(parent, view, model) + + @classmethod + def create(cls, parent, app, **kwargs): + """ + Instanciate a homescreen component + :param sakia.gui.component.controller.ComponentController parent: + :param sakia.core.Application app: + :return: a new Homescreen controller + :rtype: UserInformationController + """ + account = kwargs['account'] + community = kwargs['community'] + identity = kwargs['identity'] + view = UserInformationView(parent.view) + model = UserInformationModel(None, app, account, community, identity) + homescreen = cls(parent, view, model) + model.setParent(homescreen) + return homescreen + + @classmethod + def open_dialog(cls, parent, app, account, community, identity): + dialog = QDialog() + user_info = cls.create(parent, app, account=account, + community=community, + identity=identity) + user_info.view.setParent(dialog) + user_info.refresh() + dialog.exec() + + @classmethod + def as_widget(cls, parent, app, account, community, identity): + return cls(app, account, community, identity) + + @asyncify + async def refresh(self): + if self.model.identity and self.model.identity.local_state != LocalState.NOT_FOUND: + self.view.show_busy() + self.view.display_uid(self.model.identity.uid) + publish_time, join_date = await self.model.identity_timestamps() + self.view.display_identity_timestamps(self.model.identity.pubkey, publish_time, join_date) + self.view.hide_busy() + path = await self.model.path_to_identity() + self.view.display_path(path) + + def change_community(self, community): + """ + Set community + :param sakia.core.Community community: + """ + self.model.community = community + self.refresh() + + @asyncify + async def search_identity(self, pubkey): + """ + Set identity + :param str pubkey: the pubkey + """ + await self.model.search_identity(pubkey) + self.refresh() + + def change_identity(self, identity): + """ + Set identity + :param sakia.core.registry.Identity identity: + """ + self.model.identity = identity + self.refresh() + + @property + def view(self) -> UserInformationView: + return self._view + + @property + def model(self) -> UserInformationModel: + return self._model \ No newline at end of file diff --git a/src/sakia/gui/user_information/model.py b/src/sakia/gui/user_information/model.py new file mode 100644 index 0000000000000000000000000000000000000000..d75b7b5cd6b5799262fe5d7b292dfb3514760af1 --- /dev/null +++ b/src/sakia/gui/user_information/model.py @@ -0,0 +1,70 @@ +from sakia.gui.component.model import ComponentModel +from sakia.tools.exceptions import MembershipNotFoundError, LookupFailureError, NoPeerAvailable +from sakia.core.graph import WoTGraph +import logging + + +class UserInformationModel(ComponentModel): + """ + The model of HomeScreen component + """ + + def __init__(self, parent, app, account, community, identity): + """ + + :param sakia.gui.user_information.controller.UserInformationController parent: + :param sakia.core.Application app: the app + :param sakia.core.Account account: the account + :param sakia.core.Community community: the community + :param sakia.core.registry.Identity identity: the identity + """ + super().__init__(parent) + self.app = app + self.account = account + self.community = community + self.identity = identity + + async def identity_timestamps(self): + """ + Get identity timestamps + :rtype: tuple + """ + publish_time = None + join_date = None + try: + identity_selfcert = await self.identity.selfcert(self.community) + publish_time = await self.community.time(identity_selfcert.timestamp.number) + + join_date = await self.identity.get_join_date(self.community) + except (MembershipNotFoundError, LookupFailureError, NoPeerAvailable) as e: + logging.debug(str(e)) + + return publish_time, join_date + + async def path_to_identity(self): + """ + Get the path to a given identity + :rtype: list[str] + """ + # calculate path to account member + graph = WoTGraph(self.app, self.community) + identities = [] + # if selected member is not the account member... + if self.identity.pubkey != self.account.pubkey: + # add path from us to him + account_identity = await self.account.identity(self.community) + path = await graph.get_shortest_path_to_identity(self.identity, + account_identity) + nodes = graph.nx_graph.nodes(data=True) + if path: + for node_id in path: + node = [n for n in nodes if n[0] == node_id][0] + identities.append(node[1]['text']) + return identities + + async def search_identity(self, pubkey): + """ + Set the identity starting by a pubkey + :param str pubkey: + """ + self.identity = await self.app.identities_registry.future_find(pubkey, self.community) diff --git a/res/ui/member.ui b/src/sakia/gui/user_information/user_information.ui similarity index 86% rename from res/ui/member.ui rename to src/sakia/gui/user_information/user_information.ui index 23bb9d1769f46c84eca8ca91a172ae5612de9dce..b7aa85477487eaa90d1ad37f283857503996d91a 100644 --- a/res/ui/member.ui +++ b/src/sakia/gui/user_information/user_information.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>MemberView</class> - <widget class="QWidget" name="MemberView"> + <class>UserInformationWidget</class> + <widget class="QWidget" name="UserInformationWidget"> <property name="geometry"> <rect> <x>0</x> @@ -15,7 +15,7 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QGroupBox" name="groupbox_member"> + <widget class="QGroupBox" name="groupbox_user"> <property name="styleSheet"> <string notr="true">QGroupBox { border: 1px solid gray; @@ -31,7 +31,7 @@ QGroupBox::title { }</string> </property> <property name="title"> - <string>Member</string> + <string>User</string> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="1"> @@ -52,7 +52,7 @@ QGroupBox::title { <string/> </property> <property name="pixmap"> - <pixmap resource="../icons/icons.qrc">:/icons/member_icon</pixmap> + <pixmap resource="../../../../res/icons/icons.qrc">:/icons/member_icon</pixmap> </property> <property name="scaledContents"> <bool>true</bool> @@ -95,7 +95,8 @@ QGroupBox::title { </layout> </widget> <resources> - <include location="../icons/icons.qrc"/> + <include location="../../../../res/icons/icons.qrc"/> + <include location="../../../../res/icons/icons.qrc"/> </resources> <connections/> </ui> diff --git a/src/sakia/gui/user_information/view.py b/src/sakia/gui/user_information/view.py new file mode 100644 index 0000000000000000000000000000000000000000..90013359a34aabc0e68b4adf3720940b1508b68f --- /dev/null +++ b/src/sakia/gui/user_information/view.py @@ -0,0 +1,100 @@ +from PyQt5.QtCore import QLocale, QDateTime +from PyQt5.QtWidgets import QWidget +from .user_information_uic import Ui_UserInformationWidget +from ..widgets.busy import Busy + + +class UserInformationView(QWidget, Ui_UserInformationWidget): + """ + User information view + """ + + def __init__(self, parent): + """ + Constructor + """ + super().__init__(parent) + self.setupUi(self) + self.busy = Busy(self) + self.busy.hide() + + def display_identity_timestamps(self, pubkey, publish_time, join_date): + """ + Display identity timestamps in localized format + :param str pubkey: + :param int publish_time: + :param int join_date: + :return: + """ + if join_date: + localized_join_date = QLocale.toString( + QLocale(), + QDateTime.fromTime_t(join_date), + QLocale.dateTimeFormat(QLocale(), QLocale.ShortFormat) + ) + else: + localized_join_date = "###" + + if publish_time: + localized_publish_date = QLocale.toString( + QLocale(), + QDateTime.fromTime_t(publish_time), + QLocale.dateTimeFormat(QLocale(), QLocale.ShortFormat) + ) + else: + localized_publish_date = "###" + + text = self.tr(""" + <table cellpadding="5"> + <tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr> + <tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr> + <tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr> + """).format( + self.tr('Public key'), + pubkey, + self.tr('UID Published on'), + localized_publish_date, + self.tr('Join date'), + localized_join_date + ) + # close html text + text += "</table>" + + # set text in label + self.label_properties.setText(text) + + def display_uid(self, uid): + """ + Display the uid in the label + :param str uid: + """ + self.label_uid.setText(uid) + + def display_path(self, path): + """ + Display path to identity + :param list[str] path: + """ + + text = """<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>"""\ + .format(self.tr('Distance'), len(path)) + if len(path) > 1: + for index, uid in enumerate(path): + if index == 0: + text += self.tr("""<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""") \ + .format(self.tr('Path'), uid) + else: + text += self.tr("""<tr><td align="right"><b>{:}</b></div></td><td>{:}</td></tr>""") \ + .format('', uid) + + self.label_path.setText(text) + + def show_busy(self): + self.busy.show() + + def hide_busy(self): + self.busy.hide() + + def resizeEvent(self, event): + self.busy.resize(event.size()) + super().resizeEvent(event) \ No newline at end of file diff --git a/src/sakia/gui/widgets/context_menu.py b/src/sakia/gui/widgets/context_menu.py index 5124c826abd2e433a1ce5016e8a3541e87e7884f..f2b668fb561f2abdf68ea893bb5d67ef51599e9f 100644 --- a/src/sakia/gui/widgets/context_menu.py +++ b/src/sakia/gui/widgets/context_menu.py @@ -3,7 +3,7 @@ from PyQt5.QtCore import QObject, pyqtSignal from duniterpy.documents import Block, Membership import logging -from ..member import MemberDialog +from ..user_information.controller import UserInformationController from ..contact import ConfigureContactDialog from ..transfer import TransferMoneyDialog from ..certification.controller import CertificationController @@ -135,7 +135,7 @@ class ContextMenu(QObject): clipboard.setText(identity.pubkey) def informations(self, identity): - MemberDialog.open_dialog(self._app, self._account, self._community, identity) + UserInformationController.open_dialog(None, self._app, self._account, self._community, identity) def add_as_contact(self, identity): dialog = ConfigureContactDialog.from_identity(self._app, self.parent(), self._account, identity)