diff --git a/sakia.spec b/sakia.spec index c036561a441b76ae38e5044dbf22271594766b93..1af9d334abf4df7f8d187e883370b49019afafff 100644 --- a/sakia.spec +++ b/sakia.spec @@ -40,10 +40,12 @@ if is_linux: a.binaries = a.binaries + TOC([('libsodium.so', libsodium_path, 'BINARY')]) a.datas = a.datas + [('sakia/root_servers.yml', 'src/sakia/root_servers.yml', 'DATA')] + a.datas = a.datas + [('sakia/g1_licence.html', 'src/sakia/g1_licence.html', 'DATA')] if is_win: a.binaries = a.binaries + TOC([('libsodium.dll', ctypes.util.find_library('libsodium.dll'), 'BINARY')]) - a.datas = a.datas + [('sakia\\root_servers.yml', 'src\\/sakia\\root_servers.yml', 'DATA')] + a.datas = a.datas + [('sakia\\root_servers.yml', 'src\\sakia\\root_servers.yml', 'DATA')] + a.datas = a.datas + [('sakia\\g1_licence.html', 'src\\sakia\\g1_licence.html', 'DATA')] for file in os.listdir(os.path.join("src", "sakia", "data", "repositories")): if file.endswith(".sql"): diff --git a/src/sakia/constants.py b/src/sakia/constants.py index 6daa2dd68856eb25e50a7aaf29b21f3570b99ba2..c1ad2befb4a8f09d84f1644608f495c4ad9ac098 100644 --- a/src/sakia/constants.py +++ b/src/sakia/constants.py @@ -5,3 +5,6 @@ MAX_CONFIRMATIONS = 6 with open(os.path.join(os.path.dirname(__file__), "root_servers.yml"), 'r') as stream: ROOT_SERVERS = yaml.load(stream) + +with open(os.path.join(os.path.dirname(__file__), "g1_licence.html"), 'r') as stream: + G1_LICENCE = stream.read() diff --git a/src/sakia/g1_licence.html b/src/sakia/g1_licence.html new file mode 100644 index 0000000000000000000000000000000000000000..4cedfcbfe0ea3c7a1e182a3fbf6c1a650d7225a5 --- /dev/null +++ b/src/sakia/g1_licence.html @@ -0,0 +1,105 @@ +<H1> License Ğ1 - v0.2 </H1> +<H2> Money licensing and liability commitment. </H2> + +<P>Any certification operation of a new member of Ğ1 +must first be accompanied by the transmission of this + license of the currency Ğ1 whose certifier must ensure + that it has been studied, understood and accepted by the + person who will be certified. +</P> +<H4> Production of Units Ğ1 </h4> +<P> Ğ1 occurs via a Universal Dividend (DU) for any human member, which is of the form: </ p> +<Ul> +<Li> 1 DU per person per day </ li> +</Ul> +<div> +<P> The amount of DU is identical each day until the next equinox, +where the DU will then be reevaluated according to the formula: </p> +</div> +<div> +<ul> +<li> DU <sub> day </sub> (the following equinox) = DU <day> (equinox) + c² (M / N) (equinox) / (15778800 seconds) +</Ul> +</div> +<div> +<P> With as parameters: </p> +</div> +<div> +<Ul> +<Li> c = 4.88% / equinox </li> +<Li> UD (0) = 10.00 Ğ1 </li> +</Ul> +</div> +<div> +<P> And as variables: </p> +</div> +<div> +<Ul> +<Li> <em> M </em> the total monetary mass at the equinox </li> +<Li> <em> N </em> the number of members at the equinox </li> +</Ul> +<div> +<H4>Web of Trust</H4> +</div> +<div> +<P> <strong> Warning: </strong> Certifying is not just about making sure you've met the person, +it's ensuring that the community Ğ1 knows the certified person well enough and Duplicate account +made by a person certified by you, or other types of problems (disappearance ...), +by cross-checking that will reveal the problem if necessary. </P> +</div> +<div> +<P> When you are a member of Ğ1 and you are about to certify a new account: </p> +</div> +<div> +<P> <strong> You are assured: </strong> </p> +</div> +<div> +<P> 1 °) The person who declares to manage this public key (new account) and to +have personally checked with him that this is the public key is sufficiently well known + (not only to know this person visually) that you are about to certify. + </P> +<P> 2a °) To meet her physically to make sure that it is this person you know who manages this public key. </P> +<P> 2b °) Remotely verify the public person / key link by contacting the person via several different means of communication, +such as social network + forum + mail + video conference + phone (acknowledge voice). </P> +<P> Because if you can hack an email account or a forum account, it will be much harder to imagine hacking four distinct + means of communication, and mimic the appearance (video) as well as the voice of the person . </P> +<P> However, the 2 °) is preferable to 3 °, whereas the 1 °) is always indispensable in all cases. </P> +<p> 3 °) To have verified with the person concerned that he has indeed generated his Duniter account revocation document, +which will enable him, if necessary, to cancel his account (in case of account theft, +ID, an incorrectly created account, etc.).</p> +</div> +<h4>Abbreviated Web of Trust rules</h4> +<div><p> +Each member has a stock of 100 possible certifications, +which can only be issued at the rate of 1 certification / 5 days.</p> + +<p>Valid for 2 months, certification for a new member is definitively adopted only if the certified has + at least 4 other certifications after these 2 months, otherwise the entry process will have to be relaunched. +</p> + +<p>To become a new member of TOC Ğ1 therefore 5 certifications +must be obtained at a distance> 5 of 80% of the TOC sentinels.</p> + +<p>A member of the TdC Ğ1 is sentinel when he has received and issued at least Y [N] certifications +where N is the number of members of the TdC and Y [N] = ceiling N ^ (1/5). Examples:</p> + +<ul> +<li>For 1024 < N ≤ 3125 we have Y [N] = 5</li> +<li>For 7776 < N ≤ 16807 we have Y [N] = 7</li> +<li>For 59049 < N ≤ 100 000 we have Y [N] = 10</li> +</ul> + +<p>Once the new member is part of the TOC Ğ1 his certifications remain valid for 2 years.</p> + +<p>To remain a member, you must renew your agreement regularly with your private key (every 12 months) +and make sure you have at least 5 certifications valid after 2 years.</p> + +<h4>Software Ğ1 and license Ğ1</h4> + +<p>The software Ğ1 allowing users to manage their use of Ğ1 must transmit this license with the software +and all the technical parameters of the currency Ğ1 and TdC Ğ1 which are entered in block 0 of Ğ1.</p> + +<p>For more details in the technical details it is possible to consult directly the code of Duniter +which is a free software and also the data of the blockchain Ğ1 by retrieving it via a Duniter instance or node Ğ1.</p> + +More information on the Duniter Team website <a href="https://www.duniter.org">https://www.duniter.org</a> \ No newline at end of file diff --git a/src/sakia/gui/dialogs/connection_cfg/view.py b/src/sakia/gui/dialogs/connection_cfg/view.py index 9f9ba0f5369005a7a66cfceec6eb806b7d843f3b..3961ea3a9fecce8e6196c9a0a02041acb3a0d3df 100644 --- a/src/sakia/gui/dialogs/connection_cfg/view.py +++ b/src/sakia/gui/dialogs/connection_cfg/view.py @@ -7,7 +7,7 @@ from math import ceil, log from sakia.gui.widgets import toast from sakia.helpers import timestamp_to_dhms from sakia.gui.widgets.dialogs import dialog_async_exec, QAsyncMessageBox -from sakia.constants import ROOT_SERVERS +from sakia.constants import ROOT_SERVERS, G1_LICENCE class ConnectionConfigView(QDialog, Ui_ConnectionConfigurationDialog): @@ -60,113 +60,7 @@ class ConnectionConfigView(QDialog, Ui_ConnectionConfigurationDialog): self.spin_p.blockSignals(False) def set_license(self, currency): - license_text = self.tr(""" -<H1> License Ğ1 - v0.2 </H1> -<H2> Money licensing and liability commitment. </H2> - -<P>Any certification operation of a new member of Ğ1 -must first be accompanied by the transmission of this - license of the currency Ğ1 whose certifier must ensure - that it has been studied, understood and accepted by the - person who will be certified. -</P> -<H4> Production of Units Ğ1 </h4> -<P> Ğ1 occurs via a Universal Dividend (DU) for any human member, which is of the form: </ p> -<Ul> -<Li> 1 DU per person per day </ li> -</Ul> -<div> -<P> The amount of DU is identical each day until the next equinox, -where the DU will then be reevaluated according to the formula: </p> -</div> -<div> -<ul> -<li> DU <sub> day </sub> (the following equinox) = DU <day> (equinox) + c² (M / N) (equinox) / (15778800 seconds) -</Ul> -</div> -<div> -<P> With as parameters: </p> -</div> -<div> -<Ul> -<Li> c = 4.88% / equinox </li> -<Li> UD (0) = 10.00 Ğ1 </li> -</Ul> -</div> -<div> -<P> And as variables: </p> -</div> -<div> -<Ul> -<Li> <em> M </em> the total monetary mass at the equinox </li> -<Li> <em> N </em> the number of members at the equinox </li> -</Ul> -<div> -<H4>Web of Trust</H4> -</div> -<div> -<P> <strong> Warning: </strong> Certifying is not just about making sure you've met the person, -it's ensuring that the community Ğ1 knows the certified person well enough and Duplicate account -made by a person certified by you, or other types of problems (disappearance ...), -by cross-checking that will reveal the problem if necessary. </P> -</div> -<div> -<P> When you are a member of Ğ1 and you are about to certify a new account: </p> -</div> -<div> -<P> <strong> You are assured: </strong> </p> -</div> -<div> -<P> 1 °) The person who declares to manage this public key (new account) and to -have personally checked with him that this is the public key is sufficiently well known - (not only to know this person visually) that you are about to certify. - </P> -<P> 2a °) To meet her physically to make sure that it is this person you know who manages this public key. </P> -<P> 2b °) Remotely verify the public person / key link by contacting the person via several different means of communication, -such as social network + forum + mail + video conference + phone (acknowledge voice). </P> -<P> Because if you can hack an email account or a forum account, it will be much harder to imagine hacking four distinct - means of communication, and mimic the appearance (video) as well as the voice of the person . </P> -<P> However, the 2 °) is preferable to 3 °, whereas the 1 °) is always indispensable in all cases. </P> -<p> 3 °) To have verified with the person concerned that he has indeed generated his Duniter account revocation document, -which will enable him, if necessary, to cancel his account (in case of account theft, -ID, an incorrectly created account, etc.).</p> -</div> -<h4>Abbreviated Web of Trust rules</h4> -<div><p> -Each member has a stock of 100 possible certifications, -which can only be issued at the rate of 1 certification / 5 days.</p> - -<p>Valid for 2 months, certification for a new member is definitively adopted only if the certified has - at least 4 other certifications after these 2 months, otherwise the entry process will have to be relaunched. -</p> - -<p>To become a new member of TOC Ğ1 therefore 5 certifications -must be obtained at a distance> 5 of 80% of the TOC sentinels.</p> - -<p>A member of the TdC Ğ1 is sentinel when he has received and issued at least Y [N] certifications -where N is the number of members of the TdC and Y [N] = ceiling N ^ (1/5). Examples:</p> - -<ul> -<li>For 1024 < N ≤ 3125 we have Y [N] = 5</li> -<li>For 7776 < N ≤ 16807 we have Y [N] = 7</li> -<li>For 59049 < N ≤ 100 000 we have Y [N] = 10</li> -</ul> - -<p>Once the new member is part of the TOC Ğ1 his certifications remain valid for 2 years.</p> - -<p>To remain a member, you must renew your agreement regularly with your private key (every 12 months) -and make sure you have at least 5 certifications valid after 2 years.</p> - -<h4>Software Ğ1 and license Ğ1</h4> - -<p>The software Ğ1 allowing users to manage their use of Ğ1 must transmit this license with the software -and all the technical parameters of the currency Ğ1 and TdC Ğ1 which are entered in block 0 of Ğ1.</p> - -<p>For more details in the technical details it is possible to consult directly the code of Duniter -which is a free software and also the data of the blockchain Ğ1 by retrieving it via a Duniter instance or node Ğ1.</p> - -More information on the Duniter Team website <a href="https://www.duniter.org">https://www.duniter.org</a> -""") + license_text = self.tr(G1_LICENCE) self.text_license.setText(license_text) def handle_n_change(self, value): diff --git a/src/sakia/gui/navigation/identity/view.py b/src/sakia/gui/navigation/identity/view.py index a9585d05e5ed8925899d4c7506083ab750a4ef69..055b635bcde475bc1eec4253767f4d9e846743ea 100644 --- a/src/sakia/gui/navigation/identity/view.py +++ b/src/sakia/gui/navigation/identity/view.py @@ -72,22 +72,6 @@ class IdentityView(QWidget, Ui_IdentityWidget): mstime_remaining_text = self.tr("Expired or never published") status_color = '#00AA00' if data['membership_state'] else self.tr('#FF0000') - description_currency = """<html> -<body> - <p> - <span style=" font-size:16pt; font-weight:600;">{currency}</span> - </p> - <p>{nb_members} {members_label}</p> - <p><span style="font-weight:600;">{monetary_mass_label}</span> : {monetary_mass}</p> - <p><span style="font-weight:600;">{balance_label}</span> : {balance}</p> -</body> -</html>""".format(currency=data['currency'], - nb_members=data['members_count'], - members_label=self.tr("members"), - monetary_mass_label=self.tr("Monetary mass"), - monetary_mass=data['mass'], - balance_label=self.tr("Balance"), - balance=data['amount']) description_membership = """<html> <body> @@ -110,8 +94,6 @@ class IdentityView(QWidget, Ui_IdentityWidget): mstime_remaining_label=self.tr("Membership"), mstime_remaining=mstime_remaining_text) - self.label_currency.setText(description_currency) - if data['is_identity']: self.label_membership.setText(description_membership) self.label_identity.setText(description_identity) diff --git a/src/sakia/gui/sub/certification/certification.ui b/src/sakia/gui/sub/certification/certification.ui index 626e4130ab3229feaae6b4ac4457431793cc524a..46a5719ffc606136ac2e68e9e70c3f516e3008df 100644 --- a/src/sakia/gui/sub/certification/certification.ui +++ b/src/sakia/gui/sub/certification/certification.ui @@ -15,108 +15,178 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QGroupBox" name="groupbox_identity"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="currentIndex"> + <number>0</number> </property> - <property name="title"> - <string>Select your identity</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QComboBox" name="combo_connections"/> - </item> - <item> - <widget class="QGroupBox" name="groupBox_3"> - <property name="title"> - <string>Certifications stock</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> + <widget class="QWidget" name="page"> + <layout class="QVBoxLayout" name="verticalLayout_7"> + <item> + <widget class="QGroupBox" name="groupbox_identity"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Select your identity</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QComboBox" name="combo_connections"/> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Certifications stock</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QLabel" name="label_cert_stock"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupbox_certified"> + <property name="title"> + <string>Certify user</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="identity_select_layout"> + <item> + <widget class="QPushButton" name="button_import_identity"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Import identity document</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> <item> - <widget class="QLabel" name="label_cert_stock"> + <widget class="QPushButton" name="button_process"> <property name="text"> - <string/> + <string>Process certification</string> </property> </widget> </item> </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupbox_certified"> - <property name="title"> - <string>Certify user</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="button_import_identity"> - <property name="text"> - <string>Import identity document</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QLabel" name="label_confirm"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>label_confirm</string> - </property> - </widget> - </item> - <item> - <widget class="QGroupBox" name="group_box_password"> - <property name="title"> - <string>Secret Key / Password</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <item> - <layout class="QVBoxLayout" name="layout_password_input"/> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="button_box"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> + </item> + </layout> + </widget> + <widget class="QWidget" name="page_2"> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Licence</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <widget class="QTextEdit" name="text_licence"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_confirm"> + <property name="text"> + <string>By going throught the process of creating a wallet, you accept the license above.</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="button_accept"> + <property name="text"> + <string>I accept the above licence</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="page_3"> + <layout class="QVBoxLayout" name="verticalLayout_9"> + <item> + <widget class="QGroupBox" name="group_box_password"> + <property name="title"> + <string>Secret Key / Password</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_6"> + <item> + <layout class="QVBoxLayout" name="layout_password_input"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="button_box"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> diff --git a/src/sakia/gui/sub/certification/controller.py b/src/sakia/gui/sub/certification/controller.py index c658a9a0ebd7580d8d7f6a2a862651e1122bb910..3c08a575cb0a2968854071da0c1da719b8308992 100644 --- a/src/sakia/gui/sub/certification/controller.py +++ b/src/sakia/gui/sub/certification/controller.py @@ -159,6 +159,9 @@ using cross checking which will help to reveal the problem if needs to be.</br>" if result[0]: QApplication.restoreOverrideCursor() await self.view.show_success(self.model.notification()) + self.search_user.clear() + self.user_information.clear() + self.view.clear() self.accepted.emit() else: await self.view.show_error(self.model.notification(), result[1]) @@ -166,6 +169,9 @@ using cross checking which will help to reveal the problem if needs to be.</br>" self.view.button_box.setEnabled(True) def reject(self): + self.search_user.clear() + self.user_information.clear() + self.view.clear() self.rejected.emit() def refresh(self): @@ -176,24 +182,25 @@ using cross checking which will help to reveal the problem if needs to be.</br>" if self.model.could_certify(): if written < stock or stock == 0: - if self.password_input.valid(): - if not self.user_information.model.identity: - self.view.set_button_box(CertificationView.ButtonBoxState.SELECT_IDENTITY) - elif days+hours+minutes > 0: - if days > 0: - remaining_localized = self.tr("{days} days").format(days=days) - else: - remaining_localized = self.tr("{hours}h {min}min").format(hours=hours, min=minutes) - self.view.set_button_box(CertificationView.ButtonBoxState.REMAINING_TIME_BEFORE_VALIDATION, - remaining=remaining_localized) + if not self.user_information.model.identity: + self.view.set_button_process(CertificationView.ButtonsState.SELECT_IDENTITY) + elif days+hours+minutes > 0: + if days > 0: + remaining_localized = self.tr("{days} days").format(days=days) else: - self.view.set_button_box(CertificationView.ButtonBoxState.OK) + remaining_localized = self.tr("{hours}h {min}min").format(hours=hours, min=minutes) + self.view.set_button_process(CertificationView.ButtonsState.REMAINING_TIME_BEFORE_VALIDATION, + remaining=remaining_localized) else: - self.view.set_button_box(CertificationView.ButtonBoxState.WRONG_PASSWORD) + self.view.set_button_process(CertificationView.ButtonsState.OK) + if self.password_input.valid(): + self.view.set_button_box(CertificationView.ButtonsState.OK) + else: + self.view.set_button_box(CertificationView.ButtonsState.WRONG_PASSWORD) else: - self.view.set_button_box(CertificationView.ButtonBoxState.NO_MORE_CERTIFICATION) + self.view.set_button_process(CertificationView.ButtonsState.NO_MORE_CERTIFICATION) else: - self.view.set_button_box(CertificationView.ButtonBoxState.NOT_A_MEMBER) + self.view.set_button_process(CertificationView.ButtonsState.NOT_A_MEMBER) def load_identity_document(self, identity_doc): """ diff --git a/src/sakia/gui/sub/certification/view.py b/src/sakia/gui/sub/certification/view.py index 0c6ceaa9dab94be90d2ffe0df0496ddf727a220d..cdcf7b795ea987aa86bc1dbc00140037dfcf231b 100644 --- a/src/sakia/gui/sub/certification/view.py +++ b/src/sakia/gui/sub/certification/view.py @@ -3,7 +3,7 @@ from PyQt5.QtCore import QT_TRANSLATE_NOOP, Qt, pyqtSignal from .certification_uic import Ui_CertificationWidget from sakia.gui.widgets import toast from sakia.gui.widgets.dialogs import QAsyncMessageBox -from sakia.constants import ROOT_SERVERS +from sakia.constants import ROOT_SERVERS, G1_LICENCE from duniterpy.documents import Identity, MalformedDocumentError from enum import Enum @@ -13,7 +13,7 @@ class CertificationView(QWidget, Ui_CertificationWidget): The view of the certification component """ - class ButtonBoxState(Enum): + class ButtonsState(Enum): NO_MORE_CERTIFICATION = 0 NOT_A_MEMBER = 1 REMAINING_TIME_BEFORE_VALIDATION = 2 @@ -21,16 +21,20 @@ class CertificationView(QWidget, Ui_CertificationWidget): SELECT_IDENTITY = 4 WRONG_PASSWORD = 5 - _button_box_values = { - ButtonBoxState.NO_MORE_CERTIFICATION: (False, - QT_TRANSLATE_NOOP("CertificationView", "No more certifications")), - ButtonBoxState.NOT_A_MEMBER: (False, QT_TRANSLATE_NOOP("CertificationView", "Not a member")), - ButtonBoxState.SELECT_IDENTITY: (False, QT_TRANSLATE_NOOP("CertificationView", "Please select an identity")), - ButtonBoxState.REMAINING_TIME_BEFORE_VALIDATION: (True, - QT_TRANSLATE_NOOP("CertificationView", + _button_process_values = { + ButtonsState.NO_MORE_CERTIFICATION: (False, + QT_TRANSLATE_NOOP("CertificationView", "No more certifications")), + ButtonsState.NOT_A_MEMBER: (False, QT_TRANSLATE_NOOP("CertificationView", "Not a member")), + ButtonsState.SELECT_IDENTITY: (False, QT_TRANSLATE_NOOP("CertificationView", "Please select an identity")), + ButtonsState.REMAINING_TIME_BEFORE_VALIDATION: (True, + QT_TRANSLATE_NOOP("CertificationView", "&Ok (Not validated before {remaining})")), - ButtonBoxState.OK: (True, QT_TRANSLATE_NOOP("CertificationView", "&Ok")), - ButtonBoxState.WRONG_PASSWORD: (False, QT_TRANSLATE_NOOP("CertificationView", "Please enter correct password")) + ButtonsState.OK: (True, QT_TRANSLATE_NOOP("CertificationView", "&Process Certification")), + } + + _button_box_values = { + ButtonsState.OK: (True, QT_TRANSLATE_NOOP("CertificationView", "&Ok")), + ButtonsState.WRONG_PASSWORD: (False, QT_TRANSLATE_NOOP("CertificationView", "Please enter correct password")) } identity_document_imported = pyqtSignal(Identity) @@ -49,11 +53,20 @@ class CertificationView(QWidget, Ui_CertificationWidget): self.search_user_view = search_user_view self.user_information_view = user_information_view self.password_input_view = password_input_view - self.groupbox_certified.layout().addWidget(search_user_view) + self.identity_select_layout.insertWidget(0, search_user_view) self.search_user_view.button_reset.hide() self.layout_password_input.addWidget(password_input_view) self.groupbox_certified.layout().addWidget(user_information_view) self.button_import_identity.clicked.connect(self.import_identity_document) + self.button_process.clicked.connect(lambda c: self.stackedWidget.setCurrentIndex(1)) + self.button_accept.clicked.connect(lambda c: self.stackedWidget.setCurrentIndex(2)) + + licence_text = self.tr(G1_LICENCE) + self.text_licence.setText(licence_text) + + def clear(self): + self.stackedWidget.setCurrentIndex(0) + self.set_button_process(CertificationView.ButtonsState.SELECT_IDENTITY) def set_keys(self, connections): self.combo_connections.clear() @@ -87,8 +100,7 @@ class CertificationView(QWidget, Ui_CertificationWidget): def set_label_confirm(self, currency): self.label_confirm.setTextFormat(Qt.RichText) self.label_confirm.setText("""<b>Vous confirmez engager votre responsabilité envers la communauté Duniter {:} - et acceptez de certifier le compte Duniter {:} ci-dessus.<br/><br/> -Pour confirmer votre certification veuillez confirmer votre signature :</b>""".format(ROOT_SERVERS[currency]["display"], + et acceptez de certifier le compte Duniter {:} sélectionné.<br/><br/>""".format(ROOT_SERVERS[currency]["display"], ROOT_SERVERS[currency]["display"])) async def show_success(self, notification): @@ -145,3 +157,14 @@ Pour confirmer votre certification veuillez confirmer votre signature :</b>""".f button_box_state = CertificationView._button_box_values[state] self.button_box.button(QDialogButtonBox.Ok).setEnabled(button_box_state[0]) self.button_box.button(QDialogButtonBox.Ok).setText(button_box_state[1].format(**kwargs)) + + def set_button_process(self, state, **kwargs): + """ + Set button box state + :param sakia.gui.certification.view.CertificationView.ButtonBoxState state: the state of te button box + :param dict kwargs: the values to replace from the text in the state + :return: + """ + button_process_state = CertificationView._button_process_values[state] + self.button_process.setEnabled(button_process_state[0]) + self.button_process.setText(button_process_state[1].format(**kwargs)) diff --git a/src/sakia/gui/sub/search_user/controller.py b/src/sakia/gui/sub/search_user/controller.py index 67649e7e893e23ce84fece8e246f49383a33cf68..7973c67607e85ec7fe5a0733b6eed33f7444d103 100644 --- a/src/sakia/gui/sub/search_user/controller.py +++ b/src/sakia/gui/sub/search_user/controller.py @@ -59,3 +59,6 @@ class SearchUserController(QObject): if self.model.select_identity(index): self.identity_selected.emit(self.model.identity()) + def clear(self): + self.model.clear() + self.view.clear() \ No newline at end of file diff --git a/src/sakia/gui/sub/search_user/model.py b/src/sakia/gui/sub/search_user/model.py index 8839788c3d2fcd81db68ca02b0b77ebd291af558..2afcabe9bf9865f7e9439bdf60bebc083fca113e 100644 --- a/src/sakia/gui/sub/search_user/model.py +++ b/src/sakia/gui/sub/search_user/model.py @@ -69,4 +69,8 @@ class SearchUserModel(QObject): self._current_identity = None return False self._current_identity = self._nodes[index] - return True \ No newline at end of file + return True + + def clear(self): + self._current_identity = None + self._nodes = list() \ No newline at end of file diff --git a/src/sakia/gui/sub/search_user/view.py b/src/sakia/gui/sub/search_user/view.py index 8f8c42053c124e81fadff07de4f3da73f90f950f..58636e22fc725f5b34b6057de4518c682b98a793 100644 --- a/src/sakia/gui/sub/search_user/view.py +++ b/src/sakia/gui/sub/search_user/view.py @@ -29,6 +29,10 @@ class SearchUserView(QWidget, Ui_SearchUserWidget): self.combobox_search.setInsertPolicy(QComboBox.NoInsert) self.combobox_search.activated.connect(self.node_selected) + def clear(self): + self.combobox_search.clear() + self.combobox_search.lineEdit().setPlaceholderText(self.tr(SearchUserView._search_placeholder)) + def search(self, text=""): """ Search nodes when return is pressed in combobox lineEdit diff --git a/src/sakia/gui/sub/user_information/controller.py b/src/sakia/gui/sub/user_information/controller.py index 1e6f3264cad6c8bd27a4fb7f50ad35763196fc0d..a54de72ea9752d862a1eb3a47640f67484bd02a9 100644 --- a/src/sakia/gui/sub/user_information/controller.py +++ b/src/sakia/gui/sub/user_information/controller.py @@ -89,6 +89,10 @@ class UserInformationController(QObject): self.refresh() self.view.hide_busy() + def clear(self): + self.model.clear() + self.view.clear() + def change_identity(self, identity): """ Set identity diff --git a/src/sakia/gui/sub/user_information/model.py b/src/sakia/gui/sub/user_information/model.py index a8ee2aea5d560117aa245446869f08da3ed4dba8..982903ef6ae0f4245fd5124ae454f52026d51f69 100644 --- a/src/sakia/gui/sub/user_information/model.py +++ b/src/sakia/gui/sub/user_information/model.py @@ -21,9 +21,9 @@ class UserInformationModel(QObject): self.app = app self.identity = identity self.identities_service = self.app.identities_service - if identity: - self.certs_sent = self._certifications_processor.certifications_sent(identity.currency, identity.pubkey) - self.certs_received = self._certifications_processor.certifications_received(identity.currency, identity.pubkey) + + def clear(self): + self.identity = None async def load_identity(self, identity): """ diff --git a/src/sakia/gui/sub/user_information/view.py b/src/sakia/gui/sub/user_information/view.py index 8a0ccbc2756a36fc17fd065946be25062c05b826..c6d1acdc72545d3ed8ea278abbe57464d05e5efd 100644 --- a/src/sakia/gui/sub/user_information/view.py +++ b/src/sakia/gui/sub/user_information/view.py @@ -102,6 +102,10 @@ class UserInformationView(QWidget, Ui_UserInformationWidget): def hide_busy(self): self.busy.hide() + def clear(self): + self.label_properties.setText("") + self.label_uid.setText("") + def resizeEvent(self, event): self.busy.resize(event.size()) super().resizeEvent(event) \ No newline at end of file diff --git a/src/sakia/root_servers.yml b/src/sakia/root_servers.yml index 7f7d8b0283558ae916cae39c31eb8b739216d345..91cab01df8bd80a79801fbf967fb7d59f3d7b1c1 100644 --- a/src/sakia/root_servers.yml +++ b/src/sakia/root_servers.yml @@ -1,8 +1,3 @@ -fakenet: - display: fakenet - nodes: - HnFcSms8jzwngtVomTTnzudZx7SHUQY8sVE1y8yBmULk: - - "BASIC_MERKLED_API fakenet.cgeek.fr 10900" gtest: display: ğtest nodes: @@ -13,4 +8,4 @@ g1: nodes: 4aCqwikTaTPBRQLGiLHohuoJLPmLephy9eDtgCWLMwBk: - "BMAS g1.duniter.org 443" - - "BMA_ENDPOINT_API g1.duniter.org 80" + - "BMA_ENDPOINT_API g1.duniter.org 10901"