From 01965574f43e4775edb89d48219bd0faf0bd284b Mon Sep 17 00:00:00 2001 From: Inso <insomniak.fr@gmail.com> Date: Wed, 28 May 2014 11:34:25 +0200 Subject: [PATCH] Managing multiple wallets Pushing only changed WHT --- res/ui/accountConfigurationDialog.ui | 10 +- res/ui/communityConfigurationDialog.ui | 3 +- res/ui/createWalletDialog.ui | 325 ++++++++++++++++++ res/ui/generateKeyDialog.ui | 12 +- ...yDialog.py => generateAccountKeyDialog.py} | 17 +- src/cutecoin/gui/generateWalletKeyDialog.py | 95 +++++ src/cutecoin/gui/processConfigureAccount.py | 6 +- src/cutecoin/gui/processConfigureCommunity.py | 42 ++- src/cutecoin/gui/processCreateWallet.py | 200 +++++++++++ .../models/account/wallets/__init__.py | 4 +- src/cutecoin/models/community/__init__.py | 7 +- src/cutecoin/models/node/__init__.py | 8 +- src/cutecoin/models/wallet/__init__.py | 4 +- 13 files changed, 695 insertions(+), 38 deletions(-) create mode 100644 res/ui/createWalletDialog.ui rename src/cutecoin/gui/{generateKeyDialog.py => generateAccountKeyDialog.py} (90%) create mode 100644 src/cutecoin/gui/generateWalletKeyDialog.py create mode 100644 src/cutecoin/gui/processCreateWallet.py diff --git a/res/ui/accountConfigurationDialog.ui b/res/ui/accountConfigurationDialog.ui index 522ac215..28fa7b47 100644 --- a/res/ui/accountConfigurationDialog.ui +++ b/res/ui/accountConfigurationDialog.ui @@ -104,7 +104,11 @@ <item> <layout class="QHBoxLayout" name="horizontalLayout_5"> <item> - <widget class="QLineEdit" name="edit_secretkey_path"/> + <widget class="QLineEdit" name="edit_secretkey_path"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> </item> <item> <widget class="QPushButton" name="button_import"> @@ -346,7 +350,7 @@ <sender>button_generate</sender> <signal>clicked()</signal> <receiver>AccountConfigurationDialog</receiver> - <slot>open_generate_key()</slot> + <slot>open_generate_account_key()</slot> <hints> <hint type="sourcelabel"> <x>224</x> @@ -367,6 +371,6 @@ <slot>next()</slot> <slot>previous()</slot> <slot>open_import_key()</slot> - <slot>open_generate_key()</slot> + <slot>open_generate_account_key()</slot> </slots> </ui> diff --git a/res/ui/communityConfigurationDialog.ui b/res/ui/communityConfigurationDialog.ui index 2e440ce6..0dd697af 100644 --- a/res/ui/communityConfigurationDialog.ui +++ b/res/ui/communityConfigurationDialog.ui @@ -23,7 +23,7 @@ <item> <widget class="QStackedWidget" name="stacked_pages"> <property name="currentIndex"> - <number>0</number> + <number>1</number> </property> <widget class="QWidget" name="page_init"> <layout class="QVBoxLayout" name="verticalLayout_4"> @@ -271,5 +271,6 @@ <slot>check()</slot> <slot>next()</slot> <slot>previous()</slot> + <slot>current_wallet_changed(int)</slot> </slots> </ui> diff --git a/res/ui/createWalletDialog.ui b/res/ui/createWalletDialog.ui new file mode 100644 index 00000000..c1e75a8b --- /dev/null +++ b/res/ui/createWalletDialog.ui @@ -0,0 +1,325 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CreateWalletDialog</class> + <widget class="QDialog" name="CreateWalletDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>234</height> + </rect> + </property> + <property name="windowTitle"> + <string>Create a new wallet</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QStackedWidget" name="stacked_pages"> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="page_wallet"> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Wallet name :</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edit_name"/> + </item> + </layout> + </item> + </layout> + </widget> + <widget class="QWidget" name="page_key"> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Private key</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLineEdit" name="edit_secretkey_path"/> + </item> + <item> + <widget class="QPushButton" name="button_import"> + <property name="text"> + <string>Import a secret key</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>OR</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_fingerprint"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="button_generate"> + <property name="text"> + <string>Generate a secret key</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="page_node"> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <property name="topMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Main node :</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="edit_address"/> + </item> + <item> + <widget class="QSpinBox" name="spinbox_port"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>65535</number> + </property> + <property name="value"> + <number>8881</number> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QLabel" name="label_error"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>2</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPushButton" name="button_previous"> + <property name="text"> + <string>Previous</string> + </property> + </widget> + </item> + <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_next"> + <property name="text"> + <string>Next</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>button_import</sender> + <signal>clicked()</signal> + <receiver>CreateWalletDialog</receiver> + <slot>open_import_key()</slot> + <hints> + <hint type="sourcelabel"> + <x>333</x> + <y>54</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>86</y> + </hint> + </hints> + </connection> + <connection> + <sender>button_generate</sender> + <signal>clicked()</signal> + <receiver>CreateWalletDialog</receiver> + <slot>open_generate_key()</slot> + <hints> + <hint type="sourcelabel"> + <x>295</x> + <y>110</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>86</y> + </hint> + </hints> + </connection> + <connection> + <sender>edit_address</sender> + <signal>textChanged(QString)</signal> + <receiver>CreateWalletDialog</receiver> + <slot>check()</slot> + <hints> + <hint type="sourcelabel"> + <x>200</x> + <y>83</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>134</y> + </hint> + </hints> + </connection> + <connection> + <sender>spinbox_port</sender> + <signal>valueChanged(int)</signal> + <receiver>CreateWalletDialog</receiver> + <slot>check()</slot> + <hints> + <hint type="sourcelabel"> + <x>357</x> + <y>83</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>134</y> + </hint> + </hints> + </connection> + <connection> + <sender>edit_name</sender> + <signal>textChanged(QString)</signal> + <receiver>CreateWalletDialog</receiver> + <slot>check()</slot> + <hints> + <hint type="sourcelabel"> + <x>238</x> + <y>91</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>116</y> + </hint> + </hints> + </connection> + <connection> + <sender>button_next</sender> + <signal>clicked()</signal> + <receiver>CreateWalletDialog</receiver> + <slot>next()</slot> + <hints> + <hint type="sourcelabel"> + <x>349</x> + <y>212</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>116</y> + </hint> + </hints> + </connection> + <connection> + <sender>button_previous</sender> + <signal>clicked()</signal> + <receiver>CreateWalletDialog</receiver> + <slot>previous()</slot> + <hints> + <hint type="sourcelabel"> + <x>49</x> + <y>212</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>116</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <slot>open_import_key()</slot> + <slot>open_generate_key()</slot> + <slot>check()</slot> + <slot>next()</slot> + <slot>previous()</slot> + </slots> +</ui> diff --git a/res/ui/generateKeyDialog.ui b/res/ui/generateKeyDialog.ui index 5d5baf26..ac6266fd 100644 --- a/res/ui/generateKeyDialog.ui +++ b/res/ui/generateKeyDialog.ui @@ -22,9 +22,9 @@ </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> + <layout class="QHBoxLayout" name="layout_name"> <item> - <widget class="QLabel" name="label_3"> + <widget class="QLabel" name="label_name"> <property name="text"> <string>Your name</string> </property> @@ -46,9 +46,9 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> + <layout class="QHBoxLayout" name="layout_password"> <item> - <widget class="QLabel" name="label_4"> + <widget class="QLabel" name="label_password"> <property name="text"> <string>Passphrase</string> </property> @@ -64,9 +64,9 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="layout_password_bis"> <item> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="label_password_bis"> <property name="text"> <string>Type it again</string> </property> diff --git a/src/cutecoin/gui/generateKeyDialog.py b/src/cutecoin/gui/generateAccountKeyDialog.py similarity index 90% rename from src/cutecoin/gui/generateKeyDialog.py rename to src/cutecoin/gui/generateAccountKeyDialog.py index add210b4..05cbe961 100644 --- a/src/cutecoin/gui/generateKeyDialog.py +++ b/src/cutecoin/gui/generateAccountKeyDialog.py @@ -4,15 +4,13 @@ Created on 22 mai 2014 @author: inso ''' import re +import logging from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox, QProgressDialog from PyQt5.QtCore import QThread, pyqtSignal -from cutecoin.models.person import Person - from cutecoin.gen_resources.generateKeyDialog_uic import Ui_GenerateKeyDialog - class TaskGenKey(QThread): taskFinished = pyqtSignal() @@ -20,7 +18,8 @@ class TaskGenKey(QThread): self.key = self.account.gpg.gen_key(self.input_data) self.taskFinished.emit() -class GenerateKeyDialog(QDialog, Ui_GenerateKeyDialog): + +class GenerateAccountKeyDialog(QDialog, Ui_GenerateKeyDialog): ''' classdocs @@ -30,9 +29,10 @@ class GenerateKeyDialog(QDialog, Ui_GenerateKeyDialog): ''' Constructor ''' - super(GenerateKeyDialog, self).__init__() + super(GenerateAccountKeyDialog, self).__init__() self.setupUi(self) self.account = account + self.main_window = parent self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) @@ -40,14 +40,15 @@ class GenerateKeyDialog(QDialog, Ui_GenerateKeyDialog): name = self.edit_name.text() passphrase = self.edit_password.text() input_data = self.account.gpg.gen_key_input(key_type="RSA", key_length=2048, - name_real=name, passphrase=passphrase) + name_real=name, passphrase=passphrase, + name_comment="Account generated by cutecoin") self.progress_dialog = QProgressDialog(self) self.progress_dialog.setLabelText("Generating key...") self.progress_dialog.setMinimum(0) self.progress_dialog.setMaximum(0) self.progress_dialog.setCancelButton(None) - self.progress_dialog.setValue(-1) # As set in Designer + self.progress_dialog.setValue(-1) self.progress_dialog.show() self.gen_task = TaskGenKey() self.gen_task.input_data = input_data @@ -66,7 +67,7 @@ class GenerateKeyDialog(QDialog, Ui_GenerateKeyDialog): if k['fingerprint'] == key.fingerprint: self.account.keyid = k['keyid'] - print(self.account.keyid) + logging.debug("Key generated : " + self.account.keyid) QMessageBox.information(self, "Key generation", "Key " + key.fingerprint + " has been generated", diff --git a/src/cutecoin/gui/generateWalletKeyDialog.py b/src/cutecoin/gui/generateWalletKeyDialog.py new file mode 100644 index 00000000..01e1a158 --- /dev/null +++ b/src/cutecoin/gui/generateWalletKeyDialog.py @@ -0,0 +1,95 @@ +''' +Created on 22 mai 2014 + +@author: inso +''' +import re +import logging +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox, QProgressDialog +from PyQt5.QtCore import QThread, pyqtSignal + +from cutecoin.gen_resources.generateKeyDialog_uic import Ui_GenerateKeyDialog + + +class TaskGenKey(QThread): + taskFinished = pyqtSignal() + + def run(self): + self.key = self.account.gpg.gen_key(self.input_data) + self.taskFinished.emit() + + +class GenerateWalletKeyDialog(QDialog, Ui_GenerateKeyDialog): + + ''' + classdocs + ''' + + def __init__(self, account, keyname): + ''' + Constructor + ''' + super(GenerateWalletKeyDialog, self).__init__() + self.setupUi(self) + self.account = account + self.keyname = keyname + self.edit_name.setText("Wallet %s owned by %s" % + (self.keyname, account.name)) + self.edit_name.setEnabled(False) + self.keyid = '' + self.fingerprint = '' + self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) + + def accept(self): + passphrase = self.edit_password.text() + input_data = self.account.gpg.gen_key_input(key_type="RSA", + key_length=2048, + name_real="Wallet %s owned by %s" % + (self.keyname, self.account.name), + passphrase=passphrase, + name_comment="Wallet generated by cutecoin") + + self.progress_dialog = QProgressDialog(self) + self.progress_dialog.setLabelText("Generating key...") + self.progress_dialog.setMinimum(0) + self.progress_dialog.setMaximum(0) + self.progress_dialog.setCancelButton(None) + self.progress_dialog.setValue(-1) + self.progress_dialog.show() + self.gen_task = TaskGenKey() + self.gen_task.input_data = input_data + self.gen_task.account = self.account + self.gen_task.taskFinished.connect(self.gen_finished) + self.gen_task.run() + + def gen_finished(self): + self.progress_dialog.close() + + key = self.gen_task.key + secret_keys = self.account.gpg.list_keys(True) + for k in secret_keys: + if k['fingerprint'] == key.fingerprint: + self.keyid = k['keyid'] + self.fingerprint = k['fingerprint'] + + logging.debug("Key generated : %s" % self.keyid) + + QMessageBox.information(self, "Key generation", "Key " + + key.fingerprint + " has been generated", + QMessageBox.Ok) + + self.accepted.emit() + self.close() + + def check(self): + if len(self.edit_password.text()) < 8: + self.label_errors.setText("Please enter a password with more than 8 characters") + self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) + return + elif self.edit_password.text() != self.edit_password_bis.text(): + self.label_errors.setText("Passphrases do not match") + self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) + return + + self.label_errors.setText("") + self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) diff --git a/src/cutecoin/gui/processConfigureAccount.py b/src/cutecoin/gui/processConfigureAccount.py index 343f5024..6e1cbeb0 100644 --- a/src/cutecoin/gui/processConfigureAccount.py +++ b/src/cutecoin/gui/processConfigureAccount.py @@ -4,7 +4,7 @@ Created on 6 mars 2014 @author: inso ''' from cutecoin.gen_resources.accountConfigurationDialog_uic import Ui_AccountConfigurationDialog -from cutecoin.gui.generateKeyDialog import GenerateKeyDialog +from cutecoin.gui.generateAccountKeyDialog import GenerateAccountKeyDialog from cutecoin.gui.processConfigureCommunity import ProcessConfigureCommunity from cutecoin.models.account.communities.listModel import CommunitiesListModel from cutecoin.tools.exceptions import KeyAlreadyUsed, Error @@ -151,8 +151,8 @@ class ProcessConfigureAccount(QDialog, Ui_AccountConfigurationDialog): dialog.accepted.connect(self.action_edit_community) dialog.exec_() - def open_generate_key(self): - dialog = GenerateKeyDialog(self.account, self) + def open_generate_account_key(self): + dialog = GenerateAccountKeyDialog(self.account, self) dialog.exec_() def open_import_key(self): diff --git a/src/cutecoin/gui/processConfigureCommunity.py b/src/cutecoin/gui/processConfigureCommunity.py index 8b5e4cf5..9ea87a89 100644 --- a/src/cutecoin/gui/processConfigureCommunity.py +++ b/src/cutecoin/gui/processConfigureCommunity.py @@ -5,7 +5,9 @@ Created on 8 mars 2014 ''' import ucoin from cutecoin.gen_resources.communityConfigurationDialog_uic import Ui_CommunityConfigurationDialog -from PyQt5.QtWidgets import QDialog, QMenu, QMessageBox +from PyQt5.QtWidgets import QDialog, QMenu, QMessageBox, QWidget, QAction +from PyQt5.QtCore import QSignalMapper +from cutecoin.gui.processCreateWallet import ProcessCreateWallet from cutecoin.models.node.treeModel import NodesTreeModel from cutecoin.models.wallet.trustsTreeModel import TrustsTreeModel from cutecoin.models.node import Node @@ -92,16 +94,25 @@ class StepPageSetWallets(Step): def display_page(self): self.config_dialog.tabs_wallets.clear() + signal_mapper = QSignalMapper(self.config_dialog) for wallet in self.config_dialog.account.wallets: wallet_tab = WalletTabWidget(self.config_dialog.account, self.config_dialog.community) self.config_dialog.tabs_wallets.addTab(wallet_tab, wallet.name) tree_model = TrustsTreeModel(wallet, self.config_dialog.community.name()) + signal_mapper.setMapping(tree_model, wallet.name) + tree_model.dataChanged.connect(signal_mapper.map) wallet_tab.trusts_tree_view.setModel(tree_model) + wallet_tab.spinbox_trusts.setValue(wallet.required_trusts) + wallet_tab.spinbox_trusts.valueChanged.connect(self.config_dialog.required_trusts_changed) + + self.config_dialog.tabs_wallets.addTab(QWidget(), "+") self.config_dialog.button_previous.setEnabled(True) self.config_dialog.button_next.setText("Ok") + changed_slot = self.config_dialog.current_wallet_changed + self.config_dialog.tabs_wallets.currentChanged.connect(changed_slot) def process_next(self): pass @@ -122,6 +133,10 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog): self.account = account self.step = None self.nodes = [] + self.wallet_edit = {} + + for w in self.account.wallets: + self.wallet_edit[w.name] = False step_init = StepPageInit(self) step_add_nodes = StepPageAddNodes(self) @@ -171,8 +186,21 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog): self.tree_nodes.setModel(NodesTreeModel(self.community, self.nodes)) + def current_wallet_changed(self, index): + if index == (self.tabs_wallets.count() - 1): + wallet_parameters = ProcessCreateWallet(self.account, + self.community) + wallet_parameters.accepted.connect(self.add_wallet) + wallet_parameters.exec_() + + def add_wallet(self): + self.wallet_edit[self.account.wallets[-1].name] = True + self.tabs_wallets.disconnect() + self.step.display_page() + def required_trusts_changed(self, value): wallet = self.account.wallets[self.tabs_wallets.currentIndex()] + self.wallet_edit[self.account.wallets[-1].name] = True wallet.required_trusts = value def showContextMenu(self, point): @@ -184,6 +212,9 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog): action.setEnabled(False) menu.exec_(self.mapToGlobal(point)) + def wallet_edited(self, name): + self.wallet_edit[name] = True + def accept(self): result = self.account.send_pubkey(self.community) if result: @@ -192,10 +223,11 @@ class ProcessConfigureCommunity(QDialog, Ui_CommunityConfigurationDialog): #TODO: Push wht only if changed for wallet in self.account.wallets: - result = wallet.push_wht(self.account.gpg) - if result: - QMessageBox.critical(self, "Wallet publishing error", - result) + if self.wallet_edit[wallet.name]: + result = wallet.push_wht(self.account.gpg) + if result: + QMessageBox.critical(self, "Wallet publishing error", + result) self.accepted.emit() self.close() diff --git a/src/cutecoin/gui/processCreateWallet.py b/src/cutecoin/gui/processCreateWallet.py new file mode 100644 index 00000000..9d35e98e --- /dev/null +++ b/src/cutecoin/gui/processCreateWallet.py @@ -0,0 +1,200 @@ +''' +Created on 22 mai 2014 + +@author: inso +''' +import re +from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox, QErrorMessage, QFileDialog + +from cutecoin.models.node import Node +from cutecoin.tools.exceptions import Error +from cutecoin.gen_resources.createWalletDialog_uic import Ui_CreateWalletDialog +from cutecoin.gui.generateWalletKeyDialog import GenerateWalletKeyDialog + + +class Step(): + def __init__(self, config_dialog, previous_step=None, next_step=None): + self.previous_step = previous_step + self.next_step = next_step + self.config_dialog = config_dialog + + +class StepPageInit(Step): + ''' + First step when adding a community + ''' + def __init__(self, config_dialog): + super().__init__(config_dialog) + + def is_valid(self): + name = self.config_dialog.edit_name.text() + if name == "": + return False + wallets = self.config_dialog.account.wallets + currency = self.config_dialog.community.currency + for w in wallets.community_wallets(currency): + if w.name == name: + return False + return True + + def process_next(self): + self.config_dialog.keyname = self.config_dialog.edit_name.text() + + def display_page(self): + self.config_dialog.button_previous.setEnabled(False) + self.config_dialog.button_next.setEnabled(False) + + +class StepPageKey(Step): + ''' + The step where the user set its key + ''' + def __init__(self, config_dialog): + super().__init__(config_dialog) + + #TODO: Check page validity + def is_valid(self): + return self.config_dialog.keyid != '' + + def process_next(self): + pass + + def display_page(self): + self.config_dialog.button_next.setEnabled(False) + + +class StepPageNode(Step): + ''' + The step where the user set default node + ''' + def __init__(self, config_dialog): + super().__init__(config_dialog) + + #TODO: Check page validity + def is_valid(self): + address = self.config_dialog.edit_address.text() + port = self.config_dialog.spinbox_port.value() + try: + peering = Node.create(address, port).peering() + except ValueError as e: + self.config_dialog.label_error.setText("Cannot access node : %s" + str(e)) + return False + except ConnectionError as e: + self.config_dialog.label_error.setText("Cannot access node : %s" + str(e)) + return False + + if "currency" in peering: + if (peering['currency'] != self.config_dialog.community.currency): + self.config_dialog.label_error.setText("This node doesn't use currency %s" + % self.config_dialog.community.currency) + return False + else: + self.config_dialog.label_error.setText("Not a ucoin node") + return False + return True + + def process_next(self): + pass + + def display_page(self): + self.config_dialog.button_previous.setEnabled(False) + self.config_dialog.button_next.setEnabled(False) + + +class ProcessCreateWallet(QDialog, Ui_CreateWalletDialog): + + ''' + classdocs + ''' + + def __init__(self, account, community): + ''' + Constructor + ''' + super(ProcessCreateWallet, self).__init__() + self.setupUi(self) + self.keyid = '' + self.account = account + self.community = community + self.keygen_dialog = None + self.keyname = "" + self.step = StepPageInit(self) + step_key = StepPageKey(self) + step_node = StepPageNode(self) + self.step.next_step = step_key + step_key.next_step = step_node + self.step.display_page() + + def accept(self): + address = self.edit_address.text() + port = self.spinbox_port.value() + + self.account.wallets.add_wallet(self.account.gpg, + self.keyid, + self.community.currency, + Node.create(address, port), + name=self.edit_name.text()) + self.accepted.emit() + self.close() + + def open_generate_key(self): + self.keygen_dialog = GenerateWalletKeyDialog(self.account, + self.keyname) + self.keygen_dialog.accepted.connect(self.key_generated) + self.keygen_dialog.exec_() + + def key_generated(self): + if self.keyid is not '': + self.account.gpg.delete_keys(self.keyid) + + self.keyid = self.keygen_dialog.keyid + self.label_fingerprint.setText(self.keygen_dialog.fingerprint) + self.check() + + def open_import_key(self): + keyfile = QFileDialog.getOpenFileName(self, + "Choose a secret key", + "", + "All key files (*.asc);; Any file (*)") + keyfile = keyfile[0] + key = open(keyfile).read() + result = self.account.gpg.import_keys(key) + if result.count == 0: + QErrorMessage(self).showMessage("Bad key file") + else: + QMessageBox.information(self, "Key import", "Key " + + result.fingerprints[0] + " has been imported", + QMessageBox.Ok) + if self.keyid is not '': + self.account.gpg.delete_keys(self.account.keyid) + + secret_keys = self.account.gpg.list_keys(True) + for k in secret_keys: + if k['fingerprint'] == result.fingerprints[0]: + self.keyid = k['keyid'] + + self.label_fingerprint.setText("Key : " + result.fingerprints[0]) + self.edit_secretkey_path.setText(keyfile) + self.check() + + def next(self): + if self.step.next_step is not None: + if self.step.is_valid(): + self.step.process_next() + self.step = self.step.next_step + next_index = self.stacked_pages.currentIndex() + 1 + self.stacked_pages.setCurrentIndex(next_index) + self.step.display_page() + else: + self.accept() + + def previous(self): + if self.step.previous_step is not None: + self.step = self.step.previous_step + previous_index = self.stacked_pages.currentIndex() - 1 + self.stacked_pages.setCurrentIndex(previous_index) + self.step.display_page() + + def check(self): + if self.step.is_valid(): + self.button_next.setEnabled(True) diff --git a/src/cutecoin/models/account/wallets/__init__.py b/src/cutecoin/models/account/wallets/__init__.py index aa5f370a..5dfb0df2 100644 --- a/src/cutecoin/models/account/wallets/__init__.py +++ b/src/cutecoin/models/account/wallets/__init__.py @@ -46,12 +46,12 @@ class Wallets(object): def __getitem__(self, key): return self._wallets_list[key] - def add_wallet(self, gpg, keyid, community, node, + def add_wallet(self, gpg, keyid, currency, node, required_trusts=1, name="Main Wallet"): ''' Create a new wallet of a specific currency. ''' - wallet = Wallet.create(keyid, community, node, + wallet = Wallet.create(keyid, currency, node, required_trusts, name) # We try to add already present nodes to the wallet present_nodes = wallet.get_nodes_in_peering(wallet.pull_wht(gpg)) diff --git a/src/cutecoin/models/community/__init__.py b/src/cutecoin/models/community/__init__.py index 8da67b58..5336fd23 100644 --- a/src/cutecoin/models/community/__init__.py +++ b/src/cutecoin/models/community/__init__.py @@ -76,13 +76,10 @@ class Community(object): def send_pubkey(self, account, wallets): ascii_key = account.gpg.export_keys(account.keyid) ascii_key = ascii_key.replace("\n", "\r\n") - signature = account.gpg.sign(ascii_key, keyid=account.keyid, detach=True) - print(ascii_key) - print(signature) + #signature = account.gpg.sign(ascii_key, keyid=account.keyid, detach=True) try: wallets.post(ucoin.pks.Add(), - {'keytext': ascii_key, - 'keysign': signature}) + {'keytext': ascii_key}) except ValueError as e: return str(e) diff --git a/src/cutecoin/models/node/__init__.py b/src/cutecoin/models/node/__init__.py index eaae103b..c4b1d3ce 100644 --- a/src/cutecoin/models/node/__init__.py +++ b/src/cutecoin/models/node/__init__.py @@ -46,9 +46,11 @@ class Node(object): return cls(server, port, trust, hoster) def __eq__(self, other): - hash = ucoin.network.Peering(self.server, self.port).get()['fingerprint'] - other_hash = ucoin.network.Peering(other.server, other.port).get()['fingerprint'] - return (self.hash == other.hash) + hash = ucoin.network.Peering(server=self.server, + port=self.port).get()['fingerprint'] + other_hash = ucoin.network.Peering(server=other.server, + port=other.port).get()['fingerprint'] + return (hash == other_hash) def get_text(self): return self.server + ":" + str(self.port) diff --git a/src/cutecoin/models/wallet/__init__.py b/src/cutecoin/models/wallet/__init__.py index 8d6e6997..1af9a279 100644 --- a/src/cutecoin/models/wallet/__init__.py +++ b/src/cutecoin/models/wallet/__init__.py @@ -58,15 +58,15 @@ class Wallet(object): return cls(keyid, currency, nodes, required_trusts, name) def __eq__(self, other): - return (self.community == other.community) + return (self.keyid == other.keyid) + #TODO: Relative and quantitative value def value(self): value = 0 for coin in self.coins: value += coin.value(self) return value - #TODO: Enhance this code. Loading the amendment each time we load a coin is bad def refresh_coins(self, gpg): self.coins = [] coins_list_request = ucoin.hdc.coins.List(self.fingerprint(gpg)) -- GitLab