Package smartcard :: Package wx :: Module CardAndReaderTreePanel
[hide private]
[frames] | no frames]

Source Code for Module smartcard.wx.CardAndReaderTreePanel

  1  """wxPython panel display cards/readers as a TreeCtrl. 
  2   
  3  __author__ = "gemalto http://www.gemalto.com" 
  4   
  5  Copyright 2001-2011 gemalto 
  6  Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 
  7   
  8  This file is part of pyscard. 
  9   
 10  pyscard is free software; you can redistribute it and/or modify 
 11  it under the terms of the GNU Lesser General Public License as published by 
 12  the Free Software Foundation; either version 2.1 of the License, or 
 13  (at your option) any later version. 
 14   
 15  pyscard is distributed in the hope that it will be useful, 
 16  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  GNU Lesser General Public License for more details. 
 19   
 20  You should have received a copy of the GNU Lesser General Public License 
 21  along with pyscard; if not, write to the Free Software 
 22  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 23  """ 
 24   
 25  # smartcard imports 
 26  from threading import RLock 
 27  from smartcard.Exceptions import CardConnectionException, NoCardException 
 28  from smartcard.ReaderMonitoring import ReaderMonitor, ReaderObserver 
 29  from smartcard.CardMonitoring import CardMonitor, CardObserver 
 30  from smartcard.util import toHexString 
 31   
 32  import smartcard.wx.SimpleSCardApp 
 33  from smartcard.wx import ICO_SMARTCARD, ICO_READER 
 34   
 35  # wxPython GUI modules (http://www.wxpython.org) 
 36  import wx 
 37   
 38   
39 -class BaseCardTreeCtrl(wx.TreeCtrl):
40 """Base class for the smart card and reader tree controls.""" 41
42 - def __init__(self, 43 parent, 44 ID=wx.NewId(), 45 pos=wx.DefaultPosition, 46 size=wx.DefaultSize, 47 style=0, 48 clientpanel=None):
49 """Constructor. Initializes a smartcard or reader tree control.""" 50 wx.TreeCtrl.__init__(self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS) 51 52 self.clientpanel = clientpanel 53 self.parent = parent 54 55 isz = (16, 16) 56 il = wx.ImageList(isz[0], isz[1]) 57 self.capindex = il.Add(wx.ArtProvider_GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, isz)) 58 self.fldrindex = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) 59 self.fldropenindex = il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) 60 if None != ICO_SMARTCARD: 61 self.cardimageindex = il.Add(wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO)) 62 if None != ICO_READER: 63 self.readerimageindex = il.Add(wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO)) 64 self.il = il 65 self.SetImageList(self.il)
66
67 - def Repaint(self):
68 self.Refresh() 69 wx.PostEvent(self, wx.PaintEvent())
70 71
72 -class CardTreeCtrl(BaseCardTreeCtrl):
73 """The CardTreeCtrl monitors inserted cards and notifies the 74 application client dialog of any card activation.""" 75
76 - def __init__(self, 77 parent, 78 ID=wx.NewId(), 79 pos=wx.DefaultPosition, 80 size=wx.DefaultSize, 81 style=0, 82 clientpanel=None):
83 """Constructor. Create a smartcard tree control.""" 84 BaseCardTreeCtrl.__init__(self, parent, ID, pos, size, 85 wx.TR_SINGLE | wx.TR_NO_BUTTONS, 86 clientpanel) 87 88 self.root = self.AddRoot("Smartcards") 89 self.SetPyData(self.root, None) 90 self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal) 91 self.SetItemImage(self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) 92 self.Expand(self.root)
93
94 - def OnAddCards(self, addedcards):
95 """Called when a card is inserted. 96 Adds a smart card to the smartcards tree.""" 97 parentnode = self.root 98 for cardtoadd in addedcards: 99 childCard = self.AppendItem(parentnode, toHexString(cardtoadd.atr)) 100 self.SetItemText(childCard, toHexString(cardtoadd.atr)) 101 self.SetPyData(childCard, cardtoadd) 102 self.SetItemImage(childCard, self.cardimageindex, wx.TreeItemIcon_Normal) 103 self.SetItemImage(childCard, self.cardimageindex, wx.TreeItemIcon_Expanded) 104 self.Expand(childCard) 105 self.Expand(self.root) 106 self.EnsureVisible(self.root) 107 self.Repaint()
108
109 - def OnRemoveCards(self, removedcards):
110 """Called when a card is removed. 111 Removes a card from the tree.""" 112 parentnode = self.root 113 for cardtoremove in removedcards: 114 (childCard, cookie) = self.GetFirstChild(parentnode) 115 while childCard.IsOk(): 116 if self.GetItemText(childCard) == toHexString(cardtoremove.atr): 117 self.Delete(childCard) 118 (childCard, cookie) = self.GetNextChild(parentnode, cookie) 119 self.Expand(self.root) 120 self.EnsureVisible(self.root) 121 self.Repaint()
122 123
124 -class ReaderTreeCtrl(BaseCardTreeCtrl):
125 """The ReaderTreeCtrl monitors inserted cards and readers and notifies the 126 application client dialog of any card activation.""" 127
128 - def __init__(self, 129 parent, 130 ID=wx.NewId(), 131 pos=wx.DefaultPosition, 132 size=wx.DefaultSize, 133 style=0, 134 clientpanel=None):
135 """Constructor. Create a reader tree control.""" 136 137 BaseCardTreeCtrl.__init__(self, parent, ID, pos, size, 138 wx.TR_SINGLE | wx.TR_NO_BUTTONS, clientpanel) 139 140 self.mutex = RLock() 141 142 self.root = self.AddRoot("Smartcard Readers") 143 self.SetPyData(self.root, None) 144 self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal) 145 self.SetItemImage(self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) 146 self.Expand(self.root)
147
148 - def AddATR(self, readernode, atr):
149 """Add an ATR to a reader node.""" 150 capchild = self.AppendItem(readernode, atr) 151 self.SetPyData(capchild, None) 152 self.SetItemImage(capchild, self.cardimageindex, wx.TreeItemIcon_Normal) 153 self.SetItemImage(capchild, self.cardimageindex, wx.TreeItemIcon_Expanded) 154 self.Expand(capchild) 155 return capchild
156
157 - def GetATR(self, reader):
158 """Return the ATR of the card inserted into the reader.""" 159 atr = "no card inserted" 160 try: 161 if not type(reader) is str: 162 connection = reader.createConnection() 163 connection.connect() 164 atr = toHexString(connection.getATR()) 165 connection.disconnect() 166 except NoCardException: 167 pass 168 except CardConnectionException: 169 pass 170 return atr
171
172 - def OnAddCards(self, addedcards):
173 """Called when a card is inserted. 174 Adds the smart card child to the reader node.""" 175 self.mutex.acquire() 176 try: 177 parentnode = self.root 178 for cardtoadd in addedcards: 179 (childReader, cookie) = self.GetFirstChild(parentnode) 180 found = False 181 while childReader.IsOk() and not found: 182 if self.GetItemText(childReader) == str(cardtoadd.reader): 183 (childCard, cookie2) = self.GetFirstChild(childReader) 184 self.SetItemText(childCard, toHexString(cardtoadd.atr)) 185 self.SetPyData(childCard, cardtoadd) 186 found = True 187 else: 188 (childReader, cookie) = self.GetNextChild(parentnode, cookie) 189 190 # reader was not found, add reader node 191 # this happens when card monitoring thread signals 192 # added cards before reader monitoring thread signals 193 # added readers 194 if not found: 195 childReader = self.AppendItem(parentnode, str(cardtoadd.reader)) 196 self.SetPyData(childReader, cardtoadd.reader) 197 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Normal) 198 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Expanded) 199 childCard = self.AddATR(childReader, toHexString(cardtoadd.atr)) 200 self.SetPyData(childCard, cardtoadd) 201 self.Expand(childReader) 202 203 self.Expand(self.root) 204 finally: 205 self.mutex.release() 206 self.EnsureVisible(self.root) 207 self.Repaint()
208
209 - def OnAddReaders(self, addedreaders):
210 """Called when a reader is inserted. 211 Adds the smart card reader to the smartcard readers tree.""" 212 self.mutex.acquire() 213 214 try: 215 parentnode = self.root 216 for readertoadd in addedreaders: 217 # is the reader already here? 218 found = False 219 (childReader, cookie) = self.GetFirstChild(parentnode) 220 while childReader.IsOk() and not found: 221 if self.GetItemText(childReader) == str(readertoadd): 222 found = True 223 else: 224 (childReader, cookie) = self.GetNextChild(parentnode, cookie) 225 if not found: 226 childReader = self.AppendItem(parentnode, str(readertoadd)) 227 self.SetPyData(childReader, readertoadd) 228 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Normal) 229 self.SetItemImage(childReader, self.readerimageindex, wx.TreeItemIcon_Expanded) 230 self.AddATR(childReader, self.GetATR(readertoadd)) 231 self.Expand(childReader) 232 self.Expand(self.root) 233 finally: 234 self.mutex.release() 235 self.EnsureVisible(self.root) 236 self.Repaint()
237
238 - def OnRemoveCards(self, removedcards):
239 """Called when a card is removed. 240 Removes the card from the tree.""" 241 self.mutex.acquire() 242 try: 243 parentnode = self.root 244 for cardtoremove in removedcards: 245 (childReader, cookie) = self.GetFirstChild(parentnode) 246 found = False 247 while childReader.IsOk() and not found: 248 if self.GetItemText(childReader) == str(cardtoremove.reader): 249 (childCard, cookie2) = self.GetFirstChild(childReader) 250 self.SetItemText(childCard, 'no card inserted') 251 found = True 252 else: 253 (childReader, cookie) = self.GetNextChild(parentnode, cookie) 254 self.Expand(self.root) 255 finally: 256 self.mutex.release() 257 self.EnsureVisible(self.root) 258 self.Repaint()
259
260 - def OnRemoveReaders(self, removedreaders):
261 """Called when a reader is removed. 262 Removes the reader from the smartcard readers tree.""" 263 self.mutex.acquire() 264 try: 265 parentnode = self.root 266 for readertoremove in removedreaders: 267 (childReader, cookie) = self.GetFirstChild(parentnode) 268 while childReader.IsOk(): 269 if self.GetItemText(childReader) == str(readertoremove): 270 self.Delete(childReader) 271 else: 272 (childReader, cookie) = self.GetNextChild(parentnode, cookie) 273 self.Expand(self.root) 274 finally: 275 self.mutex.release() 276 self.EnsureVisible(self.root) 277 self.Repaint()
278 279
280 -class CardAndReaderTreePanel(wx.Panel):
281 """Panel containing the smart card and reader tree controls.""" 282
283 - class _CardObserver(CardObserver):
284 """Inner CardObserver. Gets notified of card insertion 285 removal by the CardMonitor.""" 286
287 - def __init__(self, cardtreectrl):
288 self.cardtreectrl = cardtreectrl
289
290 - def update(self, observable, (addedcards, removedcards)):
291 """CardObserver callback that is notified when cards are added or removed.""" 292 self.cardtreectrl.OnRemoveCards(removedcards) 293 self.cardtreectrl.OnAddCards(addedcards)
294
295 - class _ReaderObserver(ReaderObserver):
296 """Inner ReaderObserver. Gets notified of reader insertion/removal 297 by the ReaderMonitor.""" 298
299 - def __init__(self, readertreectrl):
300 self.readertreectrl = readertreectrl
301
302 - def update(self, observable, (addedreaders, removedreaders)):
303 """ReaderObserver callback that is notified when readers are added or removed.""" 304 self.readertreectrl.OnRemoveReaders(removedreaders) 305 self.readertreectrl.OnAddReaders(addedreaders)
306
307 - def __init__(self, parent, appstyle, clientpanel):
308 """Constructor. Create a smartcard and reader tree control on the 309 left-hand side of the application main frame. 310 parent: the tree panel parent 311 appstyle: a combination of the following styles (bitwise or |) 312 TR_SMARTCARD: display a smartcard tree panel 313 TR_READER: display a reader tree panel 314 default is TR_DEFAULT = TR_SMARTCARD 315 clientpanel: the client panel to notify of smartcard and reader events 316 """ 317 wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS) 318 319 sizer = wx.BoxSizer(wx.VERTICAL) 320 321 # create the smartcard tree 322 if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD: 323 self.cardtreectrl = CardTreeCtrl(self, clientpanel=clientpanel) 324 325 # create the smartcard insertion observer 326 self.cardtreecardobserver = self._CardObserver(self.cardtreectrl) 327 328 # register as a CardObserver; we will ge notified of added/removed cards 329 self.cardmonitor = CardMonitor() 330 self.cardmonitor.addObserver(self.cardtreecardobserver) 331 332 sizer.Add(self.cardtreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) 333 334 # create the reader tree 335 if appstyle & smartcard.wx.SimpleSCardApp.TR_READER: 336 self.readertreectrl = ReaderTreeCtrl(self, clientpanel=clientpanel) 337 338 # create the reader insertion observer 339 self.readertreereaderobserver = self._ReaderObserver(self.readertreectrl) 340 341 # register as a ReaderObserver; we will ge notified of added/removed readers 342 self.readermonitor = ReaderMonitor() 343 self.readermonitor.addObserver(self.readertreereaderobserver) 344 345 # create the smartcard insertion observer 346 self.readertreecardobserver = self._CardObserver(self.readertreectrl) 347 348 # register as a CardObserver; we will ge notified of added/removed cards 349 self.cardmonitor = CardMonitor() 350 self.cardmonitor.addObserver(self.readertreecardobserver) 351 352 sizer.Add(self.readertreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) 353 354 self.SetSizer(sizer) 355 self.SetAutoLayout(True)
356
357 - def OnDestroy(self, event):
358 """Called on panel destruction.""" 359 # deregister observers 360 if hasattr(self, cardmonitor): 361 self.cardmonitor.deleteObserver(self.cardtreecardobserver) 362 if hasattr(self, readermonitor): 363 self.readermonitor.deleteObserver(self.readertreereaderobserver) 364 self.cardmonitor.deleteObserver(self.readertreecardobserver) 365 event.Skip()
366