From 9edc3b199b25cd1a33630bc413fa76a7af7bda95 Mon Sep 17 00:00:00 2001
From: Inso <insomniak.fr@gmail.com>
Date: Sun, 9 Feb 2014 21:54:04 +0100
Subject: [PATCH] Enhancements of communities management

---
 res/ui/communityTabWidget.ui                  |  4 +-
 src/cutecoin/core/config.py                   | 29 +++++++++++++-
 src/cutecoin/core/exceptions.py               | 25 ++++++++++++
 src/cutecoin/gui/addAccountDialog.py          | 10 ++---
 src/cutecoin/gui/addCommunityDialog.py        | 15 ++++++--
 src/cutecoin/gui/communityTabWidget.py        |  5 +++
 src/cutecoin/gui/mainWindow.py                | 12 +++---
 src/cutecoin/models/account/__init__.py       |  5 ++-
 .../models/account/communities/__init__.py    | 16 ++++----
 src/cutecoin/models/community/__init__.py     | 11 ++++--
 .../models/community/issuancesListModel.py    | 33 ++++++++++++++++
 .../models/community/membersListModel.py      | 38 +++++++++++++++++++
 src/cutecoin/models/community/treeModel.py    |  8 ++--
 13 files changed, 175 insertions(+), 36 deletions(-)
 create mode 100644 src/cutecoin/core/exceptions.py
 create mode 100644 src/cutecoin/models/community/issuancesListModel.py
 create mode 100644 src/cutecoin/models/community/membersListModel.py

diff --git a/res/ui/communityTabWidget.ui b/res/ui/communityTabWidget.ui
index acee98be..41c59598 100644
--- a/res/ui/communityTabWidget.ui
+++ b/res/ui/communityTabWidget.ui
@@ -24,7 +24,7 @@
       </widget>
      </item>
      <item>
-      <widget class="QListView" name="communityMembers_2"/>
+      <widget class="QListView" name="communityMembersList"/>
      </item>
     </layout>
    </item>
@@ -38,7 +38,7 @@
       </widget>
      </item>
      <item>
-      <widget class="QListView" name="listView"/>
+      <widget class="QListView" name="issuancesList"/>
      </item>
     </layout>
    </item>
diff --git a/src/cutecoin/core/config.py b/src/cutecoin/core/config.py
index ca1ce159..74b13d1f 100644
--- a/src/cutecoin/core/config.py
+++ b/src/cutecoin/core/config.py
@@ -4,9 +4,34 @@ Created on 7 févr. 2014
 @author: inso
 '''
 
-
+import logging
+from optparse import OptionParser
 data = { 'home' : '~/.cutecoin'}
 
 def parseArguments(argv):
-    #TODO: Parsing d'arguments
+    parser = OptionParser()
+
+    parser.add_option("-v", "--verbose",
+                      action="store_true", dest="verbose", default=False,
+                      help="Print INFO messages to stdout")
+
+    parser.add_option("-d", "--debug",
+                  action="store_true", dest="debug", default=False,
+                  help="Print DEBUG messages to stdout")
+
+
+    parser.add_option("--home", dest="home", default="~/.cutecoin",
+                  help="Set another home for cutecoin.")
+
+    (options, args) = parser.parse_args(argv)
+
+    if options.debug == True:
+        logging.basicConfig(format='%(levelname)s:%(module)s:%(message)s', level=logging.DEBUG)
+    elif options.verbose == True:
+        logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
+    else:
+        logging.getLogger().propagate = False
+
+    data['home'] = options.home
+
     pass
\ No newline at end of file
diff --git a/src/cutecoin/core/exceptions.py b/src/cutecoin/core/exceptions.py
new file mode 100644
index 00000000..40e712bc
--- /dev/null
+++ b/src/cutecoin/core/exceptions.py
@@ -0,0 +1,25 @@
+'''
+Created on 9 févr. 2014
+
+@author: inso
+'''
+
+class Error(Exception):
+    def __init__(self, message):
+        '''
+        Constructor
+        '''
+        self.message = "Error : " + message
+
+
+class NotMemberOfCommunityError(Error):
+    '''
+    Exception raised for error in the input
+    '''
+
+
+    def __init__(self, account, community):
+        '''
+        Constructor
+        '''
+        super(NotMemberOfCommunityError, self).__init__(account + " is not a member of " + community)
diff --git a/src/cutecoin/gui/addAccountDialog.py b/src/cutecoin/gui/addAccountDialog.py
index 00c2caec..e4fdc2c2 100644
--- a/src/cutecoin/gui/addAccountDialog.py
+++ b/src/cutecoin/gui/addAccountDialog.py
@@ -26,7 +26,6 @@ class AddAccountDialog(QDialog, Ui_AddAccountDialog):
         # Set up the user interface from Designer.
         super(AddAccountDialog, self).__init__()
         self.setupUi(self)
-        self.dialog = AddCommunityDialog(self)
         self.mainWindow = mainWindow
 
         self.buttonBox.accepted.connect(self.mainWindow.actionAddAccount)
@@ -40,15 +39,16 @@ class AddAccountDialog(QDialog, Ui_AddAccountDialog):
             self.gpgKeysList.addItem(key['uids'][0])
 
         self.account = Account(availableKeys[0]['keyid'], "", Communities())
-        self.gpgKeysList.setEnabled()
+        self.gpgKeysList.setEnabled(True)
         self.gpgKeysList.currentIndexChanged[int].connect(self.keyChanged)
+        self.communityDialog = AddCommunityDialog(self)
 
     def openAddCommunityDialog(self):
-        self.dialog.setAccount(self.account)
-        self.dialog.exec_()
+        self.communityDialog.setAccount(self.account)
+        self.communityDialog.exec_()
 
     def actionAddCommunity(self):
-        self.gpgKeysList.setDisabled()
+        self.gpgKeysList.setEnabled(False)
         self.gpgKeysList.disconnect()
         self.communitiesList.setModel(CommunitiesListModel(self.account))
 
diff --git a/src/cutecoin/gui/addCommunityDialog.py b/src/cutecoin/gui/addCommunityDialog.py
index ad77ba71..9c37f280 100644
--- a/src/cutecoin/gui/addCommunityDialog.py
+++ b/src/cutecoin/gui/addCommunityDialog.py
@@ -4,9 +4,10 @@ Created on 2 févr. 2014
 @author: inso
 '''
 from cutecoin.gen_resources.addCommunityDialog_uic import Ui_AddCommunityDialog
-from PyQt5.QtWidgets import QDialog
+from PyQt5.QtWidgets import QDialog, QErrorMessage
 from cutecoin.models.community.treeModel import CommunityTreeModel
 from cutecoin.models.node import MainNode
+from cutecoin.core.exceptions import NotMemberOfCommunityError
 
 class AddCommunityDialog(QDialog, Ui_AddCommunityDialog):
     '''
@@ -32,8 +33,14 @@ class AddCommunityDialog(QDialog, Ui_AddCommunityDialog):
         '''
         server = self.serverEdit.text()
         port = self.portBox.value()
-        community = self.account.communities.addCommunity(MainNode(server, port), self.account.keyFingerprint())
-        self.account.wallets.addWallet(community.currency)
-        self.communityView.setModel( CommunityTreeModel(community) )
+        #TODO: Manage case where account is not member of the community
+        #An error must be displayed and the community must not be added
+        try:
+            community = self.account.communities.addCommunity(MainNode(server, port), self.account.keyFingerprint())
+            self.account.wallets.addWallet(community.currency)
+            self.communityView.setModel( CommunityTreeModel(community) )
+        except NotMemberOfCommunityError as e:
+            QErrorMessage(self).showMessage(e.message)
+
 
 
diff --git a/src/cutecoin/gui/communityTabWidget.py b/src/cutecoin/gui/communityTabWidget.py
index ffd81cd3..a87dfc38 100644
--- a/src/cutecoin/gui/communityTabWidget.py
+++ b/src/cutecoin/gui/communityTabWidget.py
@@ -4,6 +4,8 @@ Created on 2 févr. 2014
 @author: inso
 '''
 from PyQt5.QtWidgets import QWidget
+from cutecoin.models.community.membersListModel import MembersListModel
+from cutecoin.models.community.issuancesListModel import IssuancesListModel
 from cutecoin.gen_resources.communityTabWidget_uic import Ui_CommunityTabWidget
 
 class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
@@ -17,5 +19,8 @@ class CommunityTabWidget(QWidget, Ui_CommunityTabWidget):
         super(CommunityTabWidget, self).__init__()
         self.setupUi(self)
         self.community = community
+        self.communityMembersList.setModel(MembersListModel(community))
+        self.issuancesList.setModel(IssuancesListModel(community))
+
 
 
diff --git a/src/cutecoin/gui/mainWindow.py b/src/cutecoin/gui/mainWindow.py
index 1c3bb62a..f6722673 100644
--- a/src/cutecoin/gui/mainWindow.py
+++ b/src/cutecoin/gui/mainWindow.py
@@ -26,13 +26,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
         self.core = core
 
     def openAddAccountDialog(self):
-        self.dialog = AddAccountDialog(self)
-        self.dialog.setData()
-        self.dialog.exec_()
+        self.addAccountDialog = AddAccountDialog(self)
+        self.addAccountDialog.setData()
+        self.addAccountDialog.exec_()
 
     def actionAddAccount(self):
-        self.dialog.account.name = self.dialog.accountName.text()
-        self.core.addAccount(self.dialog.account)
+        self.addAccountDialog.account.name = self.addAccountDialog.accountName.text()
+        self.core.addAccount(self.addAccountDialog.account)
         self.refreshMainWindow()
 
     '''
@@ -49,7 +49,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
             self.walletsList.setModel(WalletsListModel(self.core.currentAccount))
             self.walletContent.setModel(WalletListModel(self.core.currentAccount.wallets.walletsList[0]))
             for community in self.core.currentAccount.communities.communitiesList:
-                self.communitiesTab.addPage(CommunityTabWidget(community), community.name())
+                self.communitiesTab.addTab(CommunityTabWidget(community), community.name())
             #TODO: self.transactionsReceived.setModel()
             #TODO: self.transactionsSent.setModel()
 
diff --git a/src/cutecoin/models/account/__init__.py b/src/cutecoin/models/account/__init__.py
index 5234def8..64245b78 100644
--- a/src/cutecoin/models/account/__init__.py
+++ b/src/cutecoin/models/account/__init__.py
@@ -6,6 +6,7 @@ Created on 1 févr. 2014
 
 import ucoinpy as ucoin
 import gnupg
+import logging
 from cutecoin.models.account.wallets import Wallets
 
 class Account(object):
@@ -34,9 +35,9 @@ class Account(object):
     def keyFingerprint(self):
         gpg = gnupg.GPG()
         availableKeys = gpg.list_keys()
-        print(self.gpgKey)
+        logging.debug(self.gpgKey)
         for k in availableKeys:
-            print(k)
+            logging.debug(k)
             if k['keyid'] == self.gpgKey:
                 return k['fingerprint']
         return ""
diff --git a/src/cutecoin/models/account/communities/__init__.py b/src/cutecoin/models/account/communities/__init__.py
index 56097ebe..47a5ed06 100644
--- a/src/cutecoin/models/account/communities/__init__.py
+++ b/src/cutecoin/models/account/communities/__init__.py
@@ -5,6 +5,8 @@ Created on 5 févr. 2014
 '''
 import ucoinpy as ucoin
 from cutecoin.models.community import Community
+from cutecoin.core.exceptions import NotMemberOfCommunityError
+import logging
 
 class Communities(object):
     '''
@@ -16,23 +18,23 @@ class Communities(object):
         '''
         self.communitiesList = []
 
-    def getCommunity(self, currency):
+    def getCommunity(self, amendmentId):
         for com in self.communitiesList:
-            #TODO: Compare communities by amendment hash instead of currency
-            if com.currency == currency:
+            if com.currentAmendmentId() == amendmentId:
                 return com
 
-    def addCommunity(self, mainNode, accountFingerprint):
+    def addCommunity(self, mainNode, keyFingerprint):
         community = Community(mainNode)
         self.members = community.ucoinRequest(lambda:ucoin.hdc.amendments.view.Members(community.currentAmendmentId()).get)
 
-        print(accountFingerprint)
+        logging.debug("Account fingerprint : " + keyFingerprint)
         for member in self.members:
-            print(member)
-            if member['value'] == accountFingerprint:
+            logging.debug(member)
+            if member['value'] == keyFingerprint:
                 self.communitiesList.append(community)
                 return community
 
+        raise NotMemberOfCommunityError(keyFingerprint, community.currency + "-" + community.currentAmendmentId())
         return None
 
     #TODO: Jsonify this model
diff --git a/src/cutecoin/models/community/__init__.py b/src/cutecoin/models/community/__init__.py
index 69db60d1..0a4d0784 100644
--- a/src/cutecoin/models/community/__init__.py
+++ b/src/cutecoin/models/community/__init__.py
@@ -7,6 +7,7 @@ Created on 1 févr. 2014
 import ucoinpy as ucoin
 import hashlib
 import json
+import logging
 
 class Community(object):
     '''
@@ -27,7 +28,10 @@ class Community(object):
         '''
         Listing members of a community
         '''
-        members = self.ucoinRequest(lambda : self.ucoinInstance.hdc.amendments.view.Members().get)
+        membersList = self.ucoinRequest(lambda : self.ucoinInstance.hdc.amendments.view.Members(self.currentAmendmentId()).get)
+        members = []
+        for m in membersList:
+            members.append(m['value'])
         return members
 
     def ucoinRequest(self, request):
@@ -35,7 +39,7 @@ class Community(object):
             if node.available == True:
                 self.ucoinInstance.settings['server'] = node.server
                 self.ucoinInstance.settings['port'] = node.port
-                print("Trying to connect to : " + node.getText())
+                logging.debug("Trying to connect to : " + node.getText())
                 return (request())()
 
         raise RuntimeError("Cannot connect to any node")
@@ -45,8 +49,7 @@ class Community(object):
         currentAmendment = self.ucoinRequest(lambda:ucoin.hdc.amendments.Current().get)
         currentAmendmentHash = hashlib.sha1(currentAmendment['raw'].encode('utf-8')).hexdigest().upper()
         amendmentId = str(currentAmendment["number"]) + "-" + currentAmendmentHash
-        #TODO: Distinct debug logging and info logging for a -d parameter
-        print("Amendment : " + amendmentId)
+        logging.debug("Amendment : " + amendmentId)
         return amendmentId
 
     def name(self):
diff --git a/src/cutecoin/models/community/issuancesListModel.py b/src/cutecoin/models/community/issuancesListModel.py
new file mode 100644
index 00000000..b3a52607
--- /dev/null
+++ b/src/cutecoin/models/community/issuancesListModel.py
@@ -0,0 +1,33 @@
+'''
+Created on 5 févr. 2014
+
+@author: inso
+'''
+
+from PyQt5.QtCore import QAbstractListModel, Qt
+
+class IssuancesListModel(QAbstractListModel):
+    '''
+    A Qt abstract item model to display communities in a tree
+    '''
+    def __init__(self, community, parent=None):
+        '''
+        Constructor
+        '''
+        super(IssuancesListModel, self).__init__(parent)
+        #TODO: Manage issuances
+        self.issuances = []
+
+
+    def rowCount(self ,parent):
+        return len(self.issuanes)
+
+    def data(self,index,role):
+
+        if role == Qt.DisplayRole:
+            row=index.row()
+            value = self.issuances[row]
+            return value
+
+    def flags(self,index):
+        return Qt.ItemIsSelectable | Qt.ItemIsEnabled
diff --git a/src/cutecoin/models/community/membersListModel.py b/src/cutecoin/models/community/membersListModel.py
new file mode 100644
index 00000000..06aeba9c
--- /dev/null
+++ b/src/cutecoin/models/community/membersListModel.py
@@ -0,0 +1,38 @@
+'''
+Created on 5 févr. 2014
+
+@author: inso
+'''
+
+import ucoinpy as ucoin
+from PyQt5.QtCore import QAbstractListModel, Qt
+
+class MembersListModel(QAbstractListModel):
+    '''
+    A Qt abstract item model to display communities in a tree
+    '''
+    def __init__(self, community, parent=None):
+        '''
+        Constructor
+        '''
+        super(MembersListModel, self).__init__(parent)
+        fingerprints = community.members()
+        self.members = []
+        '''for f in fingerprints:
+            keys = community.ucoinRequest(lambda : ucoin.pks.Lookup().get)
+            if len(keys) > 0:
+                self.members.append(keys[0]['key']['name'])
+        '''
+
+    def rowCount(self ,parent):
+        return len(self.members)
+
+    def data(self,index,role):
+
+        if role == Qt.DisplayRole:
+            row=index.row()
+            value = self.members[row]
+            return value
+
+    def flags(self,index):
+        return Qt.ItemIsSelectable | Qt.ItemIsEnabled
diff --git a/src/cutecoin/models/community/treeModel.py b/src/cutecoin/models/community/treeModel.py
index 1515fc40..2180564f 100644
--- a/src/cutecoin/models/community/treeModel.py
+++ b/src/cutecoin/models/community/treeModel.py
@@ -7,6 +7,7 @@ Created on 5 févr. 2014
 from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt
 from cutecoin.models.node.itemModel import MainNodeItem, NodeItem
 from cutecoin.models.community.itemModel import CommunityItemModel
+import logging
 
 class CommunityTreeModel(QAbstractItemModel):
     '''
@@ -87,14 +88,13 @@ class CommunityTreeModel(QAbstractItemModel):
 
 
     def refreshTreeNodes(self):
-
-        print("root : " + self.rootItem.data(0))
+        logging.debug("root : " + self.rootItem.data(0))
         for mainNode in self.community.knownNodes:
             mainNodeItem = MainNodeItem(mainNode, self.rootItem)
-            print("mainNode : " + mainNode.getText() + " / " + mainNodeItem.data(0))
+            logging.debug("mainNode : " + mainNode.getText() + " / " + mainNodeItem.data(0))
             self.rootItem.appendChild(mainNodeItem)
             for node in mainNode.downstreamPeers():
                 nodeItem = NodeItem(node, mainNodeItem)
-                print("\t node : " + node.getText()+ " / " + nodeItem.data(0))
+                logging.debug("\t node : " + node.getText()+ " / " + nodeItem.data(0))
                 mainNodeItem.appendChild(nodeItem)
 
-- 
GitLab