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-2012 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__( 51 self, parent, ID, pos, size, wx.TR_SINGLE | wx.TR_NO_BUTTONS) 52 53 self.clientpanel = clientpanel 54 self.parent = parent 55 56 isz = (16, 16) 57 il = wx.ImageList(isz[0], isz[1]) 58 self.capindex = il.Add( 59 wx.ArtProvider_GetBitmap(wx.ART_HELP_BOOK, wx.ART_OTHER, isz)) 60 self.fldrindex = il.Add( 61 wx.ArtProvider_GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)) 62 self.fldropenindex = il.Add( 63 wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)) 64 if None != ICO_SMARTCARD: 65 self.cardimageindex = il.Add( 66 wx.Bitmap(ICO_SMARTCARD, wx.BITMAP_TYPE_ICO)) 67 if None != ICO_READER: 68 self.readerimageindex = il.Add( 69 wx.Bitmap(ICO_READER, wx.BITMAP_TYPE_ICO)) 70 self.il = il 71 self.SetImageList(self.il)
72
73 - def Repaint(self):
74 self.Refresh() 75 wx.PostEvent(self, wx.PaintEvent())
76 77
78 -class CardTreeCtrl(BaseCardTreeCtrl):
79 """The CardTreeCtrl monitors inserted cards and notifies the 80 application client dialog of any card activation.""" 81
82 - def __init__(self, 83 parent, 84 ID=wx.NewId(), 85 pos=wx.DefaultPosition, 86 size=wx.DefaultSize, 87 style=0, 88 clientpanel=None):
89 """Constructor. Create a smartcard tree control.""" 90 BaseCardTreeCtrl.__init__(self, parent, ID, pos, size, 91 wx.TR_SINGLE | wx.TR_NO_BUTTONS, 92 clientpanel) 93 94 self.root = self.AddRoot("Smartcards") 95 self.SetPyData(self.root, None) 96 self.SetItemImage(self.root, self.fldrindex, wx.TreeItemIcon_Normal) 97 self.SetItemImage( 98 self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) 99 self.Expand(self.root)
100
101 - def OnAddCards(self, addedcards):
102 """Called when a card is inserted. 103 Adds a smart card to the smartcards tree.""" 104 parentnode = self.root 105 for cardtoadd in addedcards: 106 childCard = self.AppendItem(parentnode, toHexString(cardtoadd.atr)) 107 self.SetItemText(childCard, toHexString(cardtoadd.atr)) 108 self.SetPyData(childCard, cardtoadd) 109 self.SetItemImage( 110 childCard, self.cardimageindex, wx.TreeItemIcon_Normal) 111 self.SetItemImage( 112 childCard, self.cardimageindex, wx.TreeItemIcon_Expanded) 113 self.Expand(childCard) 114 self.Expand(self.root) 115 self.EnsureVisible(self.root) 116 self.Repaint()
117
118 - def OnRemoveCards(self, removedcards):
119 """Called when a card is removed. 120 Removes a card from the tree.""" 121 parentnode = self.root 122 for cardtoremove in removedcards: 123 (childCard, cookie) = self.GetFirstChild(parentnode) 124 while childCard.IsOk(): 125 if self.GetItemText(childCard) == \ 126 toHexString(cardtoremove.atr): 127 self.Delete(childCard) 128 (childCard, cookie) = self.GetNextChild(parentnode, cookie) 129 self.Expand(self.root) 130 self.EnsureVisible(self.root) 131 self.Repaint()
132 133
134 -class ReaderTreeCtrl(BaseCardTreeCtrl):
135 """The ReaderTreeCtrl monitors inserted cards and readers and notifies the 136 application client dialog of any card activation.""" 137
138 - def __init__(self, 139 parent, 140 ID=wx.NewId(), 141 pos=wx.DefaultPosition, 142 size=wx.DefaultSize, 143 style=0, 144 clientpanel=None):
145 """Constructor. Create a reader tree control.""" 146 147 BaseCardTreeCtrl.__init__( 148 self, 149 parent, 150 ID, 151 pos, 152 size, 153 wx.TR_SINGLE | wx.TR_NO_BUTTONS, 154 clientpanel) 155 156 self.mutex = RLock() 157 158 self.root = self.AddRoot("Smartcard Readers") 159 self.SetPyData(self.root, None) 160 self.SetItemImage( 161 self.root, self.fldrindex, wx.TreeItemIcon_Normal) 162 self.SetItemImage( 163 self.root, self.fldropenindex, wx.TreeItemIcon_Expanded) 164 self.Expand(self.root)
165
166 - def AddATR(self, readernode, atr):
167 """Add an ATR to a reader node.""" 168 capchild = self.AppendItem(readernode, atr) 169 self.SetPyData(capchild, None) 170 self.SetItemImage( 171 capchild, self.cardimageindex, wx.TreeItemIcon_Normal) 172 self.SetItemImage( 173 capchild, self.cardimageindex, wx.TreeItemIcon_Expanded) 174 self.Expand(capchild) 175 return capchild
176
177 - def GetATR(self, reader):
178 """Return the ATR of the card inserted into the reader.""" 179 atr = "no card inserted" 180 try: 181 if not type(reader) is str: 182 connection = reader.createConnection() 183 connection.connect() 184 atr = toHexString(connection.getATR()) 185 connection.disconnect() 186 except NoCardException: 187 pass 188 except CardConnectionException: 189 pass 190 return atr
191
192 - def OnAddCards(self, addedcards):
193 """Called when a card is inserted. 194 Adds the smart card child to the reader node.""" 195 self.mutex.acquire() 196 try: 197 parentnode = self.root 198 for cardtoadd in addedcards: 199 (childReader, cookie) = self.GetFirstChild(parentnode) 200 found = False 201 while childReader.IsOk() and not found: 202 if self.GetItemText(childReader) == str(cardtoadd.reader): 203 (childCard, cookie2) = self.GetFirstChild(childReader) 204 self.SetItemText(childCard, toHexString(cardtoadd.atr)) 205 self.SetPyData(childCard, cardtoadd) 206 found = True 207 else: 208 (childReader, cookie) = self.GetNextChild( 209 parentnode, cookie) 210 211 # reader was not found, add reader node 212 # this happens when card monitoring thread signals 213 # added cards before reader monitoring thread signals 214 # added readers 215 if not found: 216 childReader = self.AppendItem( 217 parentnode, str(cardtoadd.reader)) 218 self.SetPyData(childReader, cardtoadd.reader) 219 self.SetItemImage( 220 childReader, 221 self.readerimageindex, 222 wx.TreeItemIcon_Normal) 223 self.SetItemImage( 224 childReader, 225 self.readerimageindex, 226 wx.TreeItemIcon_Expanded) 227 childCard = self.AddATR( 228 childReader, toHexString(cardtoadd.atr)) 229 self.SetPyData(childCard, cardtoadd) 230 self.Expand(childReader) 231 232 self.Expand(self.root) 233 finally: 234 self.mutex.release() 235 self.EnsureVisible(self.root) 236 self.Repaint()
237
238 - def OnAddReaders(self, addedreaders):
239 """Called when a reader is inserted. 240 Adds the smart card reader to the smartcard readers tree.""" 241 self.mutex.acquire() 242 243 try: 244 parentnode = self.root 245 for readertoadd in addedreaders: 246 # is the reader already here? 247 found = False 248 (childReader, cookie) = self.GetFirstChild(parentnode) 249 while childReader.IsOk() and not found: 250 if self.GetItemText(childReader) == str(readertoadd): 251 found = True 252 else: 253 (childReader, cookie) = self.GetNextChild( 254 parentnode, cookie) 255 if not found: 256 childReader = self.AppendItem(parentnode, str(readertoadd)) 257 self.SetPyData(childReader, readertoadd) 258 self.SetItemImage( 259 childReader, 260 self.readerimageindex, 261 wx.TreeItemIcon_Normal) 262 self.SetItemImage( 263 childReader, 264 self.readerimageindex, 265 wx.TreeItemIcon_Expanded) 266 self.AddATR( 267 childReader, 268 self.GetATR(readertoadd)) 269 self.Expand(childReader) 270 self.Expand(self.root) 271 finally: 272 self.mutex.release() 273 self.EnsureVisible(self.root) 274 self.Repaint()
275
276 - def OnRemoveCards(self, removedcards):
277 """Called when a card is removed. 278 Removes the card from the tree.""" 279 self.mutex.acquire() 280 try: 281 parentnode = self.root 282 for cardtoremove in removedcards: 283 (childReader, cookie) = self.GetFirstChild(parentnode) 284 found = False 285 while childReader.IsOk() and not found: 286 if self.GetItemText(childReader) == \ 287 str(cardtoremove.reader): 288 (childCard, cookie2) = self.GetFirstChild(childReader) 289 self.SetItemText(childCard, 'no card inserted') 290 found = True 291 else: 292 (childReader, cookie) = \ 293 self.GetNextChild(parentnode, cookie) 294 self.Expand(self.root) 295 finally: 296 self.mutex.release() 297 self.EnsureVisible(self.root) 298 self.Repaint()
299
300 - def OnRemoveReaders(self, removedreaders):
301 """Called when a reader is removed. 302 Removes the reader from the smartcard readers tree.""" 303 self.mutex.acquire() 304 try: 305 parentnode = self.root 306 for readertoremove in removedreaders: 307 (childReader, cookie) = self.GetFirstChild(parentnode) 308 while childReader.IsOk(): 309 if self.GetItemText(childReader) == str(readertoremove): 310 self.Delete(childReader) 311 else: 312 (childReader, cookie) = \ 313 self.GetNextChild(parentnode, cookie) 314 self.Expand(self.root) 315 finally: 316 self.mutex.release() 317 self.EnsureVisible(self.root) 318 self.Repaint()
319 320
321 -class CardAndReaderTreePanel(wx.Panel):
322 """Panel containing the smart card and reader tree controls.""" 323
324 - class _CardObserver(CardObserver):
325 """Inner CardObserver. Gets notified of card insertion 326 removal by the CardMonitor.""" 327
328 - def __init__(self, cardtreectrl):
329 self.cardtreectrl = cardtreectrl
330
331 - def update(self, observable, handlers):
332 """CardObserver callback that is notified 333 when cards are added or removed.""" 334 addedcards, removedcards = handlers 335 self.cardtreectrl.OnRemoveCards(removedcards) 336 self.cardtreectrl.OnAddCards(addedcards)
337
338 - class _ReaderObserver(ReaderObserver):
339 """Inner ReaderObserver. Gets notified of reader insertion/removal 340 by the ReaderMonitor.""" 341
342 - def __init__(self, readertreectrl):
343 self.readertreectrl = readertreectrl
344
345 - def update(self, observable, handlers):
346 """ReaderObserver callback that is notified when 347 readers are added or removed.""" 348 addedcards, removedcards = handlers 349 self.readertreectrl.OnRemoveReaders(removedreaders) 350 self.readertreectrl.OnAddReaders(addedreaders)
351
352 - def __init__(self, parent, appstyle, clientpanel):
353 """Constructor. Create a smartcard and reader tree control on the 354 left-hand side of the application main frame. 355 @param parent: the tree panel parent 356 @param appstyle: a combination of the following styles (bitwise or |) 357 - TR_SMARTCARD: display a smartcard tree panel 358 - TR_READER: display a reader tree panel 359 - default is TR_DEFAULT = TR_SMARTCARD 360 @param clientpanel: the client panel to notify of smartcard and reader events 361 """ 362 wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS) 363 364 sizer = wx.BoxSizer(wx.VERTICAL) 365 366 # create the smartcard tree 367 if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD: 368 self.cardtreectrl = CardTreeCtrl(self, clientpanel=clientpanel) 369 370 # create the smartcard insertion observer 371 self.cardtreecardobserver = self._CardObserver(self.cardtreectrl) 372 373 # register as a CardObserver; we will ge 374 # notified of added/removed cards 375 self.cardmonitor = CardMonitor() 376 self.cardmonitor.addObserver(self.cardtreecardobserver) 377 378 sizer.Add( 379 self.cardtreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) 380 381 # create the reader tree 382 if appstyle & smartcard.wx.SimpleSCardApp.TR_READER: 383 self.readertreectrl = ReaderTreeCtrl( 384 self, clientpanel=clientpanel) 385 386 # create the reader insertion observer 387 self.readertreereaderobserver = self._ReaderObserver( 388 self.readertreectrl) 389 390 # register as a ReaderObserver; we will ge 391 # notified of added/removed readers 392 self.readermonitor = ReaderMonitor() 393 self.readermonitor.addObserver(self.readertreereaderobserver) 394 395 # create the smartcard insertion observer 396 self.readertreecardobserver = self._CardObserver( 397 self.readertreectrl) 398 399 # register as a CardObserver; we will get 400 # notified of added/removed cards 401 self.cardmonitor = CardMonitor() 402 self.cardmonitor.addObserver(self.readertreecardobserver) 403 404 sizer.Add( 405 self.readertreectrl, flag=wx.EXPAND | wx.ALL, proportion=1) 406 407 self.SetSizer(sizer) 408 self.SetAutoLayout(True)
409
410 - def OnDestroy(self, event):
411 """Called on panel destruction.""" 412 # deregister observers 413 if hasattr(self, 'cardmonitor'): 414 self.cardmonitor.deleteObserver(self.cardtreecardobserver) 415 if hasattr(self, 'readermonitor'): 416 self.readermonitor.deleteObserver(self.readertreereaderobserver) 417 self.cardmonitor.deleteObserver(self.readertreecardobserver) 418 event.Skip()
419