From 3d7e55f13a743534bf6c040d413ca7aa12c5307c Mon Sep 17 00:00:00 2001 From: Inso <insomniak.fr@gmail.com> Date: Sun, 16 Feb 2014 23:15:30 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20fenetre=20pour=20cr=C3=A9er?= =?UTF-8?q?=20son=20dividend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .directory | 6 ++ Makefile | 2 +- README.md | 29 ++++++- res/ui/communityTabWidget.ui | 31 +++++++- res/ui/issuanceDialog.ui | 87 ++++++++++++++++++++ src/cutecoin/core/config.py | 4 + src/cutecoin/gui/addAccountDialog.py | 1 + src/cutecoin/gui/communityTabWidget.py | 12 +++ src/cutecoin/gui/issuanceDialog.py | 88 +++++++++++++++++++++ src/cutecoin/gui/mainWindow.py | 1 + src/cutecoin/models/account/__init__.py | 14 ++++ src/cutecoin/models/account/factory.py | 5 +- src/cutecoin/models/community/__init__.py | 15 ++++ src/cutecoin/models/transaction/__init__.py | 3 + 14 files changed, 293 insertions(+), 5 deletions(-) create mode 100644 .directory create mode 100644 res/ui/issuanceDialog.ui create mode 100644 src/cutecoin/gui/issuanceDialog.py diff --git a/.directory b/.directory new file mode 100644 index 00000000..de51075e --- /dev/null +++ b/.directory @@ -0,0 +1,6 @@ +[Dolphin] +Timestamp=2014,2,16,12,25,25 +Version=3 + +[Settings] +HiddenFilesShown=true diff --git a/Makefile b/Makefile index 15d694eb..4afec396 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ RESOURCE_DIR = res/ui COMPILED_DIR = src/cutecoin/gen_resources #UI files to compile -UI_FILES = mainwindow.ui addAccountDialog.ui addCommunityDialog.ui communityTabWidget.ui +UI_FILES = mainwindow.ui addAccountDialog.ui addCommunityDialog.ui communityTabWidget.ui issuanceDialog.ui #Qt resource files to compile RESOURCES = diff --git a/README.md b/README.md index 9f0c9a4c..7787c391 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,31 @@ cutecoin ======== -Qt Client for Ucoin project +Qt Client for [Ucoin](http://www.ucoin.io) project. + + +## Goal features + * Ucoin account management via wallets and communities + * Multi-currency + * Multi-community + * Multi-wallets + * Contacts messaging + * User-friendly coins transfer + * On-the-fly and automatic coins fusion and divisions for transactions + * Coins issuance policies : minimal space, minimal changes + * Community membership management via a voting interface + +## Current state +### Done (master branch) + * Accounts management + * Communities viewing + +### Work in progress (dev branch) + * Wallets viewing + +### Todo + * Transfer + * Coins issuance + * Coins issuance policies + * Contacts and messaging + * Voting \ No newline at end of file diff --git a/res/ui/communityTabWidget.ui b/res/ui/communityTabWidget.ui index 41c59598..2c499cdb 100644 --- a/res/ui/communityTabWidget.ui +++ b/res/ui/communityTabWidget.ui @@ -33,7 +33,14 @@ <item> <widget class="QLabel" name="label_2"> <property name="text"> - <string>Last issuance</string> + <string>Last issuances</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="issuanceButton"> + <property name="text"> + <string>Issue money</string> </property> </widget> </item> @@ -45,5 +52,25 @@ </layout> </widget> <resources/> - <connections/> + <connections> + <connection> + <sender>issuanceButton</sender> + <signal>clicked()</signal> + <receiver>CommunityTabWidget</receiver> + <slot>openIssuanceDialog()</slot> + <hints> + <hint type="sourcelabel"> + <x>296</x> + <y>42</y> + </hint> + <hint type="destinationlabel"> + <x>199</x> + <y>149</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <slot>openIssuanceDialog()</slot> + </slots> </ui> diff --git a/res/ui/issuanceDialog.ui b/res/ui/issuanceDialog.ui new file mode 100644 index 00000000..f139380c --- /dev/null +++ b/res/ui/issuanceDialog.ui @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>IssuanceDialog</class> + <widget class="QDialog" name="IssuanceDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="totalLabel"> + <property name="text"> + <string>Total : </string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>IssuanceDialog</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>buttonBox</sender> + <signal>rejected()</signal> + <receiver>IssuanceDialog</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> + </connections> +</ui> diff --git a/src/cutecoin/core/config.py b/src/cutecoin/core/config.py index 7efb38bd..177904f9 100644 --- a/src/cutecoin/core/config.py +++ b/src/cutecoin/core/config.py @@ -7,6 +7,7 @@ Created on 7 févr. 2014 import logging from optparse import OptionParser import os.path +import gnupg home = os.path.expanduser("~") @@ -38,6 +39,9 @@ def parseArguments(argv): else: logging.getLogger().propagate = False + logger = logging.getLogger("gnupg") + logger.setLevel(logging.INFO) + parameters['home'] = options.home pass \ No newline at end of file diff --git a/src/cutecoin/gui/addAccountDialog.py b/src/cutecoin/gui/addAccountDialog.py index 9c5a6b7e..32e04eee 100644 --- a/src/cutecoin/gui/addAccountDialog.py +++ b/src/cutecoin/gui/addAccountDialog.py @@ -34,6 +34,7 @@ class AddAccountDialog(QDialog, Ui_AddAccountDialog): def setData(self): gpg = gnupg.GPG() + self.pgpKeysList.clear() availableKeys = gpg.list_keys(True) for key in availableKeys: self.pgpKeysList.addItem(key['uids'][0]) diff --git a/src/cutecoin/gui/communityTabWidget.py b/src/cutecoin/gui/communityTabWidget.py index 2b178c8f..3925f9ea 100644 --- a/src/cutecoin/gui/communityTabWidget.py +++ b/src/cutecoin/gui/communityTabWidget.py @@ -3,9 +3,12 @@ Created on 2 févr. 2014 @author: inso ''' + +import logging from PyQt5.QtWidgets import QWidget from cutecoin.models.community.membersListModel import MembersListModel from cutecoin.models.transaction.issuancesListModel import IssuancesListModel +from cutecoin.gui.issuanceDialog import IssuanceDialog from cutecoin.gen_resources.communityTabWidget_uic import Ui_CommunityTabWidget class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): @@ -19,8 +22,17 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget): super(CommunityTabWidget, self).__init__() self.setupUi(self) self.community = community + self.account = account self.communityMembersList.setModel(MembersListModel(community)) self.issuancesList.setModel(IssuancesListModel(account, community)) + if self.account.issuedLastDividend(community): + self.issuanceButton.setEnabled(False) + else: + self.issuanceButton.setEnabled(True) + def openIssuanceDialog(self): + logging.debug("Display dialog") + issuanceDialog = IssuanceDialog(self.account, self.community) + issuanceDialog.exec_() diff --git a/src/cutecoin/gui/issuanceDialog.py b/src/cutecoin/gui/issuanceDialog.py new file mode 100644 index 00000000..a786e9f0 --- /dev/null +++ b/src/cutecoin/gui/issuanceDialog.py @@ -0,0 +1,88 @@ +''' +Created on 2 févr. 2014 + +@author: inso +''' +import logging +from math import pow + +from PyQt5.QtWidgets import QDialog, QVBoxLayout, QFrame, QSlider, QLabel, QDialogButtonBox +from PyQt5.QtCore import Qt, QSignalMapper + +from cutecoin.gen_resources.issuanceDialog_uic import Ui_IssuanceDialog + +class IssuanceDialog(QDialog, Ui_IssuanceDialog): + ''' + classdocs + ''' + + + def __init__(self, issuer, community): + ''' + Constructor + ''' + super(IssuanceDialog, self).__init__() + self.setupUi(self) + self.issuer = issuer + self.community = community + self.dividend = self.community.dividend() + self.coinMinimalPower = self.community.coinMinimalPower() + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + + self.sliders = [] + self.slidersLabels = [] + maxCoinPower = 1 + nMax = 0 + # We look for the power of 10 which is directly higher than the dividend + while maxCoinPower < self.dividend: + maxCoinPower = pow(10, nMax) + nMax += 1 + + # N max is the power just before the one we found + + logging.debug("Pow max : " + str(nMax)) + + for i in range(self.coinMinimalPower, nMax): + self.generateSliderFrame(i) + + def generateSliderFrame(self, n): + frame = QFrame(self) + frame.setLayout(QVBoxLayout()) + + label = QLabel(frame) + frame.layout().addWidget(label) + + slider = QSlider(Qt.Horizontal, frame) + slider.setMinimum(0) + slider.setMaximum(9) + slider.valueChanged.connect(self.refreshTotal) + + frame.layout().addWidget(slider) + + label.setText("0 coins of " + str(pow(10, n))) + + + self.slidersLabels.append(label) + self.sliders.append(slider) + + self.layout().insertWidget(n, frame) + + def refreshTotal(self): + n = 0 + total = 0 + for slider in self.sliders: + self.slidersLabels[n].setText(str(slider.value()) + " coins of " + str(pow(10, n))) + self.totalLabel.setText("Total : " + str(total)) + total += slider.value()*pow(10, n) + n += 1 + self.totalLabel.setText("Total : " + str(total)) + if total != self.dividend: + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + else: + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) + + + + + + diff --git a/src/cutecoin/gui/mainWindow.py b/src/cutecoin/gui/mainWindow.py index c11c4f09..c56edffb 100644 --- a/src/cutecoin/gui/mainWindow.py +++ b/src/cutecoin/gui/mainWindow.py @@ -78,6 +78,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.accountNameLabel.setText("Current account : " + self.core.currentAccount.name) self.walletsList.setModel(WalletsListModel(self.core.currentAccount)) self.walletContent.setModel(WalletListModel(self.core.currentAccount.wallets.walletsList[0])) + self.communitiesTab.clear() for community in self.core.currentAccount.communities.communitiesList: communityTab = CommunityTabWidget(self.core.currentAccount, community) self.communitiesTab.addTab(communityTab, community.name()) diff --git a/src/cutecoin/models/account/__init__.py b/src/cutecoin/models/account/__init__.py index 22bf3c8c..9211f74e 100644 --- a/src/cutecoin/models/account/__init__.py +++ b/src/cutecoin/models/account/__init__.py @@ -66,6 +66,20 @@ class Account(object): issuances.append(trxFactory.createTransaction(issuance['sender'], issuance['number'])) return issuances + def issuedLastDividend(self, community): + currentAmendmentNumber = community.amendmentNumber() + + if community in self.communities.communitiesList: + dividendsData = community.ucoinRequest(ucoin.hdc.transactions.sender.issuance.Dividend(self.keyFingerprint(), currentAmendmentNumber)) + for dividend in dividendsData: + # Small bug in ucoinpy library + if not isinstance(dividend, str): + return True + + return False + + + def jsonify(self): data = {'name' : self.name, 'pgpKeyId' : self.pgpKeyId, diff --git a/src/cutecoin/models/account/factory.py b/src/cutecoin/models/account/factory.py index ba2c91fd..85971dfc 100644 --- a/src/cutecoin/models/account/factory.py +++ b/src/cutecoin/models/account/factory.py @@ -3,12 +3,16 @@ Created on 11 févr. 2014 @author: inso ''' + +import logging + from cutecoin.models.account import Account from cutecoin.models.account.wallets import Wallets from cutecoin.models.account.communities import Communities from cutecoin.models.wallet import factory as walletFactory from cutecoin.models.community import factory as communityFactory + def createAccount(pgpKeyId, name, communities): ''' Constructor @@ -29,7 +33,6 @@ def loadAccount(jsonData): account.name = jsonData['name'] account.communities = Communities() account.wallets = Wallets() - for communityData in jsonData['communities']: account.communities.communitiesList.append(communityFactory.loadCommunity(communityData, account)) return account \ No newline at end of file diff --git a/src/cutecoin/models/community/__init__.py b/src/cutecoin/models/community/__init__.py index 2825d08f..98b37e21 100644 --- a/src/cutecoin/models/community/__init__.py +++ b/src/cutecoin/models/community/__init__.py @@ -61,6 +61,21 @@ class Community(object): def name(self): return self.currency + def dividend(self): + currentAmendment = self.ucoinRequest(ucoin.hdc.amendments.Current()) + return currentAmendment['dividend'] + + def coinMinimalPower(self): + currentAmendment = self.ucoinRequest(ucoin.hdc.amendments.Current()) + if 'coinMinimalPower' in currentAmendment.keys(): + return currentAmendment['coinMinimalPower'] + else: + return 0 + + def amendmentNumber(self): + currentAmendment = self.ucoinRequest(ucoin.hdc.amendments.Current()) + return currentAmendment['number'] + def jsonifyNodesList(self): data = [] for node in self.knownNodes: diff --git a/src/cutecoin/models/transaction/__init__.py b/src/cutecoin/models/transaction/__init__.py index 171cf526..cec0028b 100644 --- a/src/cutecoin/models/transaction/__init__.py +++ b/src/cutecoin/models/transaction/__init__.py @@ -56,6 +56,9 @@ class Issuance(Transaction): ''' def __init__(self): super(Issuance).__init__() + + def amendmentNumber(self): + self.community.ucoinRequest(ucoin.hdc.transactions.View(self.sender.pgpFingerprint + "-" + self.increment)) def getText(self): return str(self.value) + " " + self.currency -- GitLab