"""Simple wxpython frame for smart card application.
__author__ = "gemalto http://www.gemalto.com"
__date__ = "November 2006"
__version__ = "1.4.0"
Copyright 2001-2010 gemalto
Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
This file is part of pyscard.
pyscard is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
pyscard is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with pyscard; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
import os.path
import wx
import smartcard.wx
import APDUTracerPanel
import CardAndReaderTreePanel
import ReaderToolbar
import smartcard
from smartcard.wx.SimpleSCardAppEventObserver import SimpleSCardAppEventObserver
[
wxID_SIMPLESCARDAPP_FRAME,
] = map( lambda x: wx.NewId(), range(1) )
class BlankPanel( wx.Panel, SimpleSCardAppEventObserver ):
'''A blank panel in case no panel is provided to SimpleSCardApp.'''
def __init__( self, parent ):
wx.Panel.__init__( self, parent, -1 )
sizer = wx.GridSizer( 1, 1 )
self.SetSizer(sizer)
self.SetAutoLayout(True)
class TreeAndUserPanelPanel( wx.Panel ):
'''The panel that contains the Card/Reader TreeCtrl and the user provided Panel.'''
def __init__( self, parent, apppanelclass, appstyle ):
"""
Constructor. Creates the panel with two panels:
the left-hand panel is holding the smartcard and/or reader tree
the right-hand panel is holding the application dialog
apppanelclass: the class of the panel to instantiate in the SimpleSCardAppFrame
appstyle: a combination of the following styles (bitwise or | )
TR_SMARTCARD: display a smartcard tree panel
TR_READER: display a reader tree panel
TB_SMARTCARD: display a smartcard toolbar
TB_SMARTCARD: display a reader toolbar
default is TR_DEFAULT = TR_SMARTCARD
"""
wx.Panel.__init__( self, parent, -1 )
self.parent = parent
self.selectedcard = None
boxsizer = wx.BoxSizer( wx.HORIZONTAL )
# create user dialog
if None!=apppanelclass:
self.dialogpanel=apppanelclass( self )
else:
self.dialogpanel=BlankPanel( self )
# create card/reader tree control
if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD or \
appstyle & smartcard.wx.SimpleSCardApp.TR_READER:
self.readertreepanel = CardAndReaderTreePanel.CardAndReaderTreePanel(
self, appstyle, self.dialogpanel )
boxsizer.Add( self.readertreepanel, 1, wx.EXPAND|wx.ALL, 5 )
boxsizer.Add( self.dialogpanel, 2, wx.EXPAND | wx.ALL )
if appstyle & smartcard.wx.SimpleSCardApp.TR_READER:
self.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateReader, self.readertreepanel.readertreectrl )
self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnSelectReader, self.readertreepanel.readertreectrl )
self.Bind( wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnReaderRightClick, self.readertreepanel.readertreectrl )
self.Bind( wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.readertreepanel.readertreectrl )
if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD:
self.Bind( wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivateCard, self.readertreepanel.cardtreectrl )
self.Bind( wx.EVT_TREE_SEL_CHANGED, self.OnSelectCard, self.readertreepanel.cardtreectrl )
self.Bind( wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnCardRightClick, self.readertreepanel.cardtreectrl )
self.SetSizer( boxsizer )
self.SetAutoLayout( True )
def ActivateCard( self, card ):
"""Activate a card."""
if not hasattr( card, 'connection' ):
card.connection = card.createConnection()
if None!=self.parent.apdutracerpanel:
card.connection.addObserver( self.parent.apdutracerpanel )
card.connection.connect()
self.dialogpanel.OnActivateCard( card )
def DeactivateCard( self, card ):
"""Deactivate a card."""
if hasattr( card, 'connection' ):
card.connection.disconnect()
if None!=self.parent.apdutracerpanel:
card.connection.deleteObserver( self.parent.apdutracerpanel )
delattr( card, 'connection' )
self.dialogpanel.OnDeactivateCard( card )
def OnActivateCard( self, event ):
"""Called when the user activates a card in the tree."""
item = event.GetItem()
if item:
itemdata = self.readertreepanel.cardtreectrl.GetItemPyData( item )
if isinstance( itemdata, smartcard.Card.Card ):
self.ActivateCard( itemdata )
else:
self.dialogpanel.OnDeselectCard( itemdata )
def OnActivateReader( self, event ):
"""Called when the user activates a reader in the tree."""
item = event.GetItem()
if item:
itemdata = self.readertreepanel.readertreectrl.GetItemPyData( item )
if isinstance( itemdata, smartcard.Card.Card ):
self.ActivateCard( itemdata )
elif isinstance( itemdata, smartcard.reader.Reader.Reader ):
self.dialogpanel.OnActivateReader( itemdata )
event.Skip()
def OnItemCollapsed( self, event ):
item = event.GetItem()
self.readertreepanel.readertreectrl.Expand( item )
def OnCardRightClick( self, event ):
"""Called when the user right-clicks a node in the card tree control."""
item = event.GetItem()
if item:
itemdata = self.readertreepanel.cardtreectrl.GetItemPyData( item )
if isinstance( itemdata, smartcard.Card.Card ):
self.selectedcard = itemdata
if not hasattr(self, "connectID"):
self.connectID = wx.NewId()
self.disconnectID = wx.NewId()
self.Bind( wx.EVT_MENU, self.OnConnect, id=self.connectID )
self.Bind( wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID )
menu = wx.Menu()
if not hasattr( self.selectedcard, 'connection' ):
menu.Append( self.connectID, "Connect" )
else:
menu.Append( self.disconnectID, "Disconnect" )
self.PopupMenu( menu )
menu.Destroy()
def OnReaderRightClick( self, event ):
"""Called when the user right-clicks a node in the reader tree control."""
item = event.GetItem()
if item:
itemdata = self.readertreepanel.readertreectrl.GetItemPyData( item )
if isinstance( itemdata, smartcard.Card.Card ):
self.selectedcard = itemdata
if not hasattr(self, "connectID"):
self.connectID = wx.NewId()
self.disconnectID = wx.NewId()
self.Bind( wx.EVT_MENU, self.OnConnect, id=self.connectID )
self.Bind( wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID )
menu = wx.Menu()
if not hasattr( self.selectedcard, 'connection' ):
menu.Append( self.connectID, "Connect" )
else:
menu.Append( self.disconnectID, "Disconnect" )
self.PopupMenu( menu )
menu.Destroy()
def OnConnect( self, event ):
if isinstance( self.selectedcard, smartcard.Card.Card ):
self.ActivateCard( self.selectedcard )
def OnDisconnect( self, event ):
if isinstance( self.selectedcard, smartcard.Card.Card ):
self.DeactivateCard( self.selectedcard )
def OnSelectCard( self, event ):
"""Called when the user selects a card in the tree."""
item = event.GetItem()
if item:
itemdata = self.readertreepanel.cardtreectrl.GetItemPyData( item )
if isinstance( itemdata, smartcard.Card.Card ):
self.dialogpanel.OnSelectCard( itemdata )
else:
self.dialogpanel.OnDeselectCard( itemdata )
def OnSelectReader( self, event ):
"""Called when the user selects a reader in the tree."""
item = event.GetItem()
if item:
itemdata = self.readertreepanel.readertreectrl.GetItemPyData( item )
if isinstance( itemdata, smartcard.Card.Card ):
self.dialogpanel.OnSelectCard( itemdata )
elif isinstance( itemdata, smartcard.reader.Reader.Reader ):
self.dialogpanel.OnSelectReader( itemdata )
else:
self.dialogpanel.OnDeselectCard( itemdata )
class SimpleSCardAppFrame(wx.Frame):
"""The main frame of the simple smartcard application."""
def __init__( self,
appname,
apppanelclass,
appstyle,
appicon,
pos=(-1,-1),
size=(-1,-1),
):
"""
Constructor. Creates the frame with two panels:
the left-hand panel is holding the smartcard and/or reader tree
the right-hand panel is holding the application dialog
appname: name of the application
apppanelclass: the class of the panel to instantiate in the SimpleSCardAppFrame
appstyle: a combination of the following styles (bitwise or | )
TR_SMARTCARD: display a smartcard tree panel
TR_READER: display a reader tree panel
TB_SMARTCARD: display a smartcard toolbar
TB_SMARTCARD: display a reader toolbar
PANEL_APDUTRACER: display an APDU tracer panel
default is TR_DEFAULT = TR_SMARTCARD
pos: the application position as a (x,y) tupple; default is (-1,-1)
size: the application window size as a (x,y) tuple; default is (-1,-1)
style: the frame wx.Frame style
"""
wx.Frame.__init__( self,
None,
wxID_SIMPLESCARDAPP_FRAME,
appname,
pos=pos,
size=size,
style=wx.DEFAULT_FRAME_STYLE )
if appicon:
_icon = wx.Icon( appicon, wx.BITMAP_TYPE_ICO )
self.SetIcon(_icon)
elif os.path.exists( smartcard.wx.ICO_SMARTCARD ):
_icon = wx.Icon( smartcard.wx.ICO_SMARTCARD, wx.BITMAP_TYPE_ICO )
self.SetIcon(_icon)
boxsizer = wx.BoxSizer( wx.VERTICAL )
self.treeuserpanel = TreeAndUserPanelPanel( self, apppanelclass, appstyle )
boxsizer.Add( self.treeuserpanel, 3, wx.EXPAND | wx.ALL )
# create a toolbar if required
if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD:
self.toolbar = ReaderToolbar.ReaderToolbar( self )
self.SetToolBar( self.toolbar )
else:
self.toolbar=None
# create an apdu tracer console if required
if appstyle & smartcard.wx.SimpleSCardApp.PANEL_APDUTRACER:
self.apdutracerpanel = APDUTracerPanel.APDUTracerPanel( self )
boxsizer.Add( self.apdutracerpanel, 1, wx.EXPAND | wx.ALL )
else:
self.apdutracerpanel=None
self.SetSizer( boxsizer )
self.SetAutoLayout( True )
self.Bind( wx.EVT_CLOSE, self.OnCloseFrame )
if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD:
self.Bind( wx.EVT_COMBOBOX, self.OnReaderComboBox, self.toolbar.readercombobox )
def OnCloseFrame(self, evt):
"""Called when frame is closed, i.e. on wx.EVT_CLOSE"""
evt.Skip()
def OnExit(self, evt):
"""Called when frame application exits."""
self.Close(True)
evt.Skip()
def OnReaderComboBox( self, event ):
"""Called when the user activates a reader in the toolbar combo box."""
cb = event.GetEventObject()
reader = cb.GetClientData(cb.GetSelection())
if isinstance( reader, smartcard.reader.Reader.Reader ):
self.treeuserpanel.dialogpanel.OnActivateReader( reader )
|