| 1 | #!/usr/bin/python |
|---|
| 2 | # -*- coding: utf-8 -*- |
|---|
| 3 | import sys, string, xml.dom.minidom, os |
|---|
| 4 | import gtk, gobject, protocols |
|---|
| 5 | |
|---|
| 6 | import protocols, retriever |
|---|
| 7 | |
|---|
| 8 | class manage_accounts : |
|---|
| 9 | def __init__(self, gladefile) : |
|---|
| 10 | self.widget = gladefile.get_widget("accounts_dialog") |
|---|
| 11 | self.gladefile = gladefile |
|---|
| 12 | self.accounts = [] |
|---|
| 13 | self.accounts_file = "accounts.xml" |
|---|
| 14 | self.updated_account_bts = None |
|---|
| 15 | |
|---|
| 16 | # Glade sucks, following should be its job :( |
|---|
| 17 | self.accountsTreeV = gladefile.get_widget('treeview1') |
|---|
| 18 | self.accountsViewList = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT) |
|---|
| 19 | self.accountsTreeV.append_column(gtk.TreeViewColumn("Name", gtk.CellRendererText(), text=0)) |
|---|
| 20 | #~ self.accountsTreeV.append_column(gtk.TreeViewColumn("pos", gtk.CellRendererText(), text=1)) |
|---|
| 21 | self.accountsTreeV.set_model(self.accountsViewList) |
|---|
| 22 | self.accountsTreeV.get_selection().set_mode(gtk.SELECTION_SINGLE) |
|---|
| 23 | self.accountsTreeV.get_selection().connect("changed", self.update_display) |
|---|
| 24 | self.accountsTreeV.set_headers_visible(False) |
|---|
| 25 | cell = gtk.CellRendererText() |
|---|
| 26 | model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) |
|---|
| 27 | protos_list = gladefile.get_widget("accounts_protocol") |
|---|
| 28 | protos_list.set_model(model) |
|---|
| 29 | protos_list.pack_start(cell) |
|---|
| 30 | protos_list.set_attributes(cell, text=0) |
|---|
| 31 | |
|---|
| 32 | for proto in protocols.__all__: |
|---|
| 33 | name = getattr(protocols, proto).protocol.Name() |
|---|
| 34 | protos_list.get_model().append((name,proto)) |
|---|
| 35 | |
|---|
| 36 | if os.path.exists(self.accounts_file) : |
|---|
| 37 | f = open(self.accounts_file,mode='r') |
|---|
| 38 | if self.open_file(f) == 0 : |
|---|
| 39 | self.account_error() |
|---|
| 40 | f.close() |
|---|
| 41 | else : |
|---|
| 42 | self.doc = xml.dom.minidom.Document() |
|---|
| 43 | store = self.doc.createElement("store") |
|---|
| 44 | self.doc.appendChild(store) |
|---|
| 45 | self.add_account() |
|---|
| 46 | #then we create the file |
|---|
| 47 | f = open(self.accounts_file, mode='a+') |
|---|
| 48 | f.write(self.doc.toxml().encode("utf-8")) |
|---|
| 49 | f.close() |
|---|
| 50 | |
|---|
| 51 | def __iter__(self): |
|---|
| 52 | return iter(self.accounts) |
|---|
| 53 | |
|---|
| 54 | def __getitem__(self, i): |
|---|
| 55 | return self.accounts[i] |
|---|
| 56 | |
|---|
| 57 | def account_error(self) : |
|---|
| 58 | message = _("Accounts are not in a valid format. \n Please remove the %s file and restart Conseil") %self.accounts_file |
|---|
| 59 | #error_window = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE, message_format=message) |
|---|
| 60 | #error_window.show() |
|---|
| 61 | print message |
|---|
| 62 | |
|---|
| 63 | def open_file(self,f) : |
|---|
| 64 | #programmation défensive needed ici !!! |
|---|
| 65 | # !!!!!!!! |
|---|
| 66 | # sanitize the pretty XML |
|---|
| 67 | stringed = f.read().replace('\n','').replace('\t','') |
|---|
| 68 | try : |
|---|
| 69 | self.doc = xml.dom.minidom.parseString(stringed) |
|---|
| 70 | except : |
|---|
| 71 | return 0 |
|---|
| 72 | if self.doc.hasChildNodes() and self.doc.firstChild.nodeName == "store" : |
|---|
| 73 | if not self.doc.firstChild.hasChildNodes() : |
|---|
| 74 | self.add_account() |
|---|
| 75 | else : |
|---|
| 76 | return 0 |
|---|
| 77 | for account in self.doc.getElementsByTagName("account"): |
|---|
| 78 | self.add_account(bts_info(xml = account)) |
|---|
| 79 | self.select_index(0) |
|---|
| 80 | return 1 |
|---|
| 81 | |
|---|
| 82 | def sync(self) : |
|---|
| 83 | self.f = open(self.accounts_file, mode='w') |
|---|
| 84 | self.f.write(self.doc.toprettyxml().encode("utf-8")) |
|---|
| 85 | self.f.close() |
|---|
| 86 | |
|---|
| 87 | def selected_index(self): |
|---|
| 88 | sel = self.accountsTreeV.get_selection() |
|---|
| 89 | nil, iter = sel.get_selected() |
|---|
| 90 | |
|---|
| 91 | if iter == None or len(self.accounts) == 0: |
|---|
| 92 | return None |
|---|
| 93 | else: |
|---|
| 94 | return self.accountsViewList.get(iter, 1)[0] |
|---|
| 95 | |
|---|
| 96 | def selected_account(self): |
|---|
| 97 | sel = self.selected_index() |
|---|
| 98 | if sel is None: |
|---|
| 99 | return None |
|---|
| 100 | else: |
|---|
| 101 | return self.accounts[sel] |
|---|
| 102 | |
|---|
| 103 | def select_index(self, i): |
|---|
| 104 | for account in self.accountsViewList: |
|---|
| 105 | if account[1] == i: |
|---|
| 106 | self.accountsTreeV.get_selection().select_iter(account.iter) |
|---|
| 107 | |
|---|
| 108 | def add_account(self, account = None) : |
|---|
| 109 | if account is None: # create a new account |
|---|
| 110 | account = bts_info(doc = self.doc) |
|---|
| 111 | |
|---|
| 112 | self.accounts.append(account) |
|---|
| 113 | self.accountsViewList.append((account.friendlyname, len(self.accounts)-1)) |
|---|
| 114 | self.select_index(len(self.accounts)-1) |
|---|
| 115 | |
|---|
| 116 | self.sync() |
|---|
| 117 | self.update_display() |
|---|
| 118 | |
|---|
| 119 | return account |
|---|
| 120 | |
|---|
| 121 | def remove_account(self): |
|---|
| 122 | idx = self.selected_index() |
|---|
| 123 | if idx is None: |
|---|
| 124 | return |
|---|
| 125 | self.accounts[idx].remove() |
|---|
| 126 | self.accounts.remove(self.accounts[idx]) |
|---|
| 127 | for account in self.accountsViewList: |
|---|
| 128 | if account[1] < idx: |
|---|
| 129 | continue |
|---|
| 130 | elif account[1] == idx: |
|---|
| 131 | self.accountsViewList.remove(account.iter) |
|---|
| 132 | else: # account[1] > idx |
|---|
| 133 | account[1] -= 1 |
|---|
| 134 | self.select_index(idx) |
|---|
| 135 | if self.selected_index() is None: |
|---|
| 136 | self.select_index(idx-1) |
|---|
| 137 | self.sync() |
|---|
| 138 | |
|---|
| 139 | def show(self,x) : |
|---|
| 140 | self.widget.show() |
|---|
| 141 | self.update_display() |
|---|
| 142 | |
|---|
| 143 | def hide(self,x) : |
|---|
| 144 | self.widget.hide() |
|---|
| 145 | |
|---|
| 146 | def update_display(self,nil=None) : |
|---|
| 147 | if self.selected_index() is None: |
|---|
| 148 | return |
|---|
| 149 | |
|---|
| 150 | self.gladefile.get_widget("accounts_friendlyname").set_text(self.selected_account().friendlyname) |
|---|
| 151 | self.gladefile.get_widget("accounts_url").set_text(self.selected_account().url) |
|---|
| 152 | self.gladefile.get_widget("accounts_login").set_text(self.selected_account().login) |
|---|
| 153 | self.gladefile.get_widget("accounts_password").set_text(self.selected_account().password) |
|---|
| 154 | |
|---|
| 155 | for proto in self.gladefile.get_widget("accounts_protocol").get_model(): |
|---|
| 156 | if proto[1] == self.selected_account().protocol: |
|---|
| 157 | self.gladefile.get_widget("accounts_protocol").set_active_iter(proto.iter) |
|---|
| 158 | break |
|---|
| 159 | |
|---|
| 160 | def friendlyname_change(self,x) : |
|---|
| 161 | self.selected_account().friendlyname = x.get_text() |
|---|
| 162 | self.sync() |
|---|
| 163 | |
|---|
| 164 | def protocol_change(self,x) : |
|---|
| 165 | self.selected_account().protocol = x.get_model()[x.get_active()][1] |
|---|
| 166 | if old_bts != new_bts and self.updated_account_bts: |
|---|
| 167 | self.updated_account_bts(old_bts, new_bts) |
|---|
| 168 | self.sync() |
|---|
| 169 | |
|---|
| 170 | def url_change(self,x) : |
|---|
| 171 | self.selected_account().url = x.get_text() |
|---|
| 172 | self.sync() |
|---|
| 173 | |
|---|
| 174 | def login_change(self,x) : |
|---|
| 175 | self.selected_account().login = x.get_text() |
|---|
| 176 | self.sync() |
|---|
| 177 | |
|---|
| 178 | def password_change(self,x) : |
|---|
| 179 | self.selected_account().password = x.get_text() |
|---|
| 180 | self.sync() |
|---|
| 181 | |
|---|
| 182 | class bts_info(object) : |
|---|
| 183 | def __init__(self, xml = None, doc = None): |
|---|
| 184 | """ xml = None and doc != None: create a new node under parent |
|---|
| 185 | xml != None and doc = None: read infos from node |
|---|
| 186 | xml = doc: well, you can try, could be funny... (but I'm not responsible ;)) """ |
|---|
| 187 | |
|---|
| 188 | if xml is None: |
|---|
| 189 | self._xml = xml = doc.createElement("account") |
|---|
| 190 | |
|---|
| 191 | # here we can put hardcoded defaults |
|---|
| 192 | friendlyname = "New account" |
|---|
| 193 | protocol = protocols.__all__[0] |
|---|
| 194 | url = "" |
|---|
| 195 | login = "" |
|---|
| 196 | password = "" |
|---|
| 197 | |
|---|
| 198 | xml.setAttribute("friendlyname",friendlyname) |
|---|
| 199 | protocol_node = doc.createElement("protocol") |
|---|
| 200 | protocol_node.appendChild(doc.createTextNode(protocol)) |
|---|
| 201 | url_node = doc.createElement("url") |
|---|
| 202 | url_node.appendChild(doc.createTextNode(url)) |
|---|
| 203 | login_node = doc.createElement("login") |
|---|
| 204 | login_node.appendChild(doc.createTextNode(login)) |
|---|
| 205 | pass_node = doc.createElement("password") |
|---|
| 206 | pass_node.appendChild(doc.createTextNode(password)) |
|---|
| 207 | xml.appendChild(protocol_node) |
|---|
| 208 | xml.appendChild(url_node) |
|---|
| 209 | xml.appendChild(login_node) |
|---|
| 210 | xml.appendChild(pass_node) |
|---|
| 211 | doc.firstChild.appendChild(xml) |
|---|
| 212 | else: |
|---|
| 213 | self._xml = xml |
|---|
| 214 | |
|---|
| 215 | self._bts = getattr(protocols, self.protocol).protocol(self) |
|---|
| 216 | |
|---|
| 217 | def __getattr__(self,name): |
|---|
| 218 | if name == 'friendlyname': |
|---|
| 219 | return self._xml.getAttribute(name) |
|---|
| 220 | elif name in ('protocol', 'url', 'login', 'password'): |
|---|
| 221 | if self._xml.getElementsByTagName(name)[0].hasChildNodes(): |
|---|
| 222 | return self._xml.getElementsByTagName(name)[0].childNodes[0].nodeValue |
|---|
| 223 | else: |
|---|
| 224 | return '' |
|---|
| 225 | else: |
|---|
| 226 | raise AttributeError, name |
|---|
| 227 | |
|---|
| 228 | def __setattr__(self,name,value): |
|---|
| 229 | if name in ('_xml', '_bts'): # a better way must exists ;) |
|---|
| 230 | object.__setattr__(self, name, value) |
|---|
| 231 | elif name == 'friendlyname': |
|---|
| 232 | self._xml.setAttribute(name, value) |
|---|
| 233 | elif name in ('protocol', 'url', 'login', 'password'): |
|---|
| 234 | doc = self._xml.ownerDocument |
|---|
| 235 | old = self._xml.getElementsByTagName(name)[0] |
|---|
| 236 | new = doc.createElement(name) |
|---|
| 237 | new.appendChild(doc.createTextNode(value)) |
|---|
| 238 | self._xml.replaceChild(new,old) |
|---|
| 239 | |
|---|
| 240 | if name == 'protocol': |
|---|
| 241 | self._bts = getattr(protocols, value).protocol(self) |
|---|
| 242 | else: |
|---|
| 243 | raise AttributeError, name |
|---|
| 244 | |
|---|
| 245 | def remove(self): |
|---|
| 246 | self._xml.parentNode.removeChild(self._xml) |
|---|
| 247 | |
|---|
| 248 | def retriever(self, tabs, gladef): |
|---|
| 249 | return retriever.retriever(self.bts(), tabs, gladef) |
|---|
| 250 | |
|---|
| 251 | def bts(self): |
|---|
| 252 | return self._bts |
|---|