1 """Simple wxpython frame for smart card application.
2
3 __author__ = "gemalto http://www.gemalto.com"
4 __date__ = "November 2006"
5 __version__ = "1.4.0"
6
7 Copyright 2001-2012 gemalto
8 Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
9
10 This file is part of pyscard.
11
12 pyscard is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published by
14 the Free Software Foundation; either version 2.1 of the License, or
15 (at your option) any later version.
16
17 pyscard is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU Lesser General Public License for more details.
21
22 You should have received a copy of the GNU Lesser General Public License
23 along with pyscard; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 """
26
27 import os.path
28 import wx
29
30 import smartcard.wx
31 from smartcard.wx import APDUTracerPanel
32 from smartcard.wx import CardAndReaderTreePanel
33 from smartcard.wx import ReaderToolbar
34
35 import smartcard
36 from smartcard.wx.SimpleSCardAppEventObserver import \
37 SimpleSCardAppEventObserver
38
39 [
40 wxID_SIMPLESCARDAPP_FRAME,
41 ] = [wx.NewId() for x in range(1)]
42
43
44 -class BlankPanel(wx.Panel, SimpleSCardAppEventObserver):
45 '''A blank panel in case no panel is provided to SimpleSCardApp.'''
46
48 wx.Panel.__init__(self, parent, -1)
49 sizer = wx.GridSizer(1, 1)
50 self.SetSizer(sizer)
51 self.SetAutoLayout(True)
52
53
55 '''The panel that contains the Card/Reader TreeCtrl
56 and the user provided Panel.'''
57
58 - def __init__(self, parent, apppanelclass, appstyle):
59 """
60 Constructor. Creates the panel with two panels:
61 - the left-hand panel is holding the smartcard and/or reader tree
62 - the right-hand panel is holding the application dialog
63
64 @param apppanelclass: the class of the panel to instantiate in the
65 L{SimpleSCardAppFrame}
66 @param appstyle: a combination of the following styles (bitwise or |)
67 - TR_SMARTCARD: display a smartcard tree panel
68 - TR_READER: display a reader tree panel
69 - TB_SMARTCARD: display a smartcard toolbar
70 - TB_SMARTCARD: display a reader toolbar
71 - default is TR_DEFAULT = TR_SMARTCARD
72 """
73 wx.Panel.__init__(self, parent, -1)
74
75 self.parent = parent
76 self.selectedcard = None
77
78 boxsizer = wx.BoxSizer(wx.HORIZONTAL)
79
80
81 if None != apppanelclass:
82 self.dialogpanel = apppanelclass(self)
83 else:
84 self.dialogpanel = BlankPanel(self)
85
86
87 if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD or \
88 appstyle & smartcard.wx.SimpleSCardApp.TR_READER:
89 self.readertreepanel = \
90 CardAndReaderTreePanel.CardAndReaderTreePanel(
91 self, appstyle, self.dialogpanel)
92 boxsizer.Add(self.readertreepanel, 1, wx.EXPAND | wx.ALL, 5)
93
94 boxsizer.Add(self.dialogpanel, 2, wx.EXPAND | wx.ALL)
95
96 if appstyle & smartcard.wx.SimpleSCardApp.TR_READER:
97 self.Bind(
98 wx.EVT_TREE_ITEM_ACTIVATED,
99 self.OnActivateReader,
100 self.readertreepanel.readertreectrl)
101 self.Bind(
102 wx.EVT_TREE_SEL_CHANGED,
103 self.OnSelectReader,
104 self.readertreepanel.readertreectrl)
105 self.Bind(
106 wx.EVT_TREE_ITEM_RIGHT_CLICK,
107 self.OnReaderRightClick,
108 self.readertreepanel.readertreectrl)
109 self.Bind(
110 wx.EVT_TREE_ITEM_COLLAPSED,
111 self.OnItemCollapsed,
112 self.readertreepanel.readertreectrl)
113
114 if appstyle & smartcard.wx.SimpleSCardApp.TR_SMARTCARD:
115 self.Bind(
116 wx.EVT_TREE_ITEM_ACTIVATED,
117 self.OnActivateCard,
118 self.readertreepanel.cardtreectrl)
119 self.Bind(
120 wx.EVT_TREE_SEL_CHANGED,
121 self.OnSelectCard,
122 self.readertreepanel.cardtreectrl)
123 self.Bind(
124 wx.EVT_TREE_ITEM_RIGHT_CLICK,
125 self.OnCardRightClick,
126 self.readertreepanel.cardtreectrl)
127
128 self.SetSizer(boxsizer)
129 self.SetAutoLayout(True)
130
132 """Activate a card."""
133 if not hasattr(card, 'connection'):
134 card.connection = card.createConnection()
135 if None != self.parent.apdutracerpanel:
136 card.connection.addObserver(self.parent.apdutracerpanel)
137 card.connection.connect()
138 self.dialogpanel.OnActivateCard(card)
139
141 """Deactivate a card."""
142 if hasattr(card, 'connection'):
143 card.connection.disconnect()
144 if None != self.parent.apdutracerpanel:
145 card.connection.deleteObserver(self.parent.apdutracerpanel)
146 delattr(card, 'connection')
147 self.dialogpanel.OnDeactivateCard(card)
148
150 """Called when the user activates a card in the tree."""
151 item = event.GetItem()
152 if item:
153 itemdata = self.readertreepanel.cardtreectrl.GetItemPyData(item)
154 if isinstance(itemdata, smartcard.Card.Card):
155 self.ActivateCard(itemdata)
156 else:
157 self.dialogpanel.OnDeselectCard(itemdata)
158
160 """Called when the user activates a reader in the tree."""
161 item = event.GetItem()
162 if item:
163 itemdata = self.readertreepanel.readertreectrl.GetItemPyData(item)
164 if isinstance(itemdata, smartcard.Card.Card):
165 self.ActivateCard(itemdata)
166 elif isinstance(itemdata, smartcard.reader.Reader.Reader):
167 self.dialogpanel.OnActivateReader(itemdata)
168 event.Skip()
169
171 item = event.GetItem()
172 self.readertreepanel.readertreectrl.Expand(item)
173
175 """Called when user right-clicks a node in the card tree control."""
176 item = event.GetItem()
177 if item:
178 itemdata = self.readertreepanel.cardtreectrl.GetItemPyData(item)
179 if isinstance(itemdata, smartcard.Card.Card):
180 self.selectedcard = itemdata
181 if not hasattr(self, "connectID"):
182 self.connectID = wx.NewId()
183 self.disconnectID = wx.NewId()
184
185 self.Bind(wx.EVT_MENU, self.OnConnect, id=self.connectID)
186 self.Bind(
187 wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID)
188
189 menu = wx.Menu()
190 if not hasattr(self.selectedcard, 'connection'):
191 menu.Append(self.connectID, "Connect")
192 else:
193 menu.Append(self.disconnectID, "Disconnect")
194 self.PopupMenu(menu)
195 menu.Destroy()
196
198 """Called when user right-clicks a node in the reader tree control."""
199 item = event.GetItem()
200 if item:
201 itemdata = self.readertreepanel.readertreectrl.GetItemPyData(item)
202 if isinstance(itemdata, smartcard.Card.Card):
203 self.selectedcard = itemdata
204 if not hasattr(self, "connectID"):
205 self.connectID = wx.NewId()
206 self.disconnectID = wx.NewId()
207
208 self.Bind(wx.EVT_MENU, self.OnConnect, id=self.connectID)
209 self.Bind(
210 wx.EVT_MENU, self.OnDisconnect, id=self.disconnectID)
211
212 menu = wx.Menu()
213 if not hasattr(self.selectedcard, 'connection'):
214 menu.Append(self.connectID, "Connect")
215 else:
216 menu.Append(self.disconnectID, "Disconnect")
217 self.PopupMenu(menu)
218 menu.Destroy()
219
223
227
229 """Called when the user selects a card in the tree."""
230 item = event.GetItem()
231 if item:
232 itemdata = self.readertreepanel.cardtreectrl.GetItemPyData(item)
233 if isinstance(itemdata, smartcard.Card.Card):
234 self.dialogpanel.OnSelectCard(itemdata)
235 else:
236 self.dialogpanel.OnDeselectCard(itemdata)
237
239 """Called when the user selects a reader in the tree."""
240 item = event.GetItem()
241 if item:
242 itemdata = self.readertreepanel.readertreectrl.GetItemPyData(item)
243 if isinstance(itemdata, smartcard.Card.Card):
244 self.dialogpanel.OnSelectCard(itemdata)
245 elif isinstance(itemdata, smartcard.reader.Reader.Reader):
246 self.dialogpanel.OnSelectReader(itemdata)
247 else:
248 self.dialogpanel.OnDeselectCard(itemdata)
249
250
252 """The main frame of the simple smartcard application."""
253
254 - def __init__(self,
255 appname,
256 apppanelclass,
257 appstyle,
258 appicon,
259 pos=(-1, -1),
260 size=(-1, -1),
261 ):
262 """
263 Constructor. Creates the frame with two panels:
264 - the left-hand panel is holding the smartcard and/or reader tree
265 - the right-hand panel is holding the application dialog
266
267 @param appname: name of the application
268 @param apppanelclass: the class of the panel to instantiate in the
269 L{SimpleSCardAppFrame}
270 @param appstyle: a combination of the following styles (bitwise or |)
271 - TR_SMARTCARD: display a smartcard tree panel
272 - TR_READER: display a reader tree panel
273 - TB_SMARTCARD: display a smartcard toolbar
274 - TB_SMARTCARD: display a reader toolbar
275 - PANEL_APDUTRACER: display an APDU tracer panel
276 - default is TR_DEFAULT = TR_SMARTCARD
277 @param pos: the application position as a (x,y) tupple; default is (-1,-1)
278 @param size: the application window size as a (x,y) tuple; default is (-1,-1)
279 """
280 wx.Frame.__init__(self,
281 None,
282 wxID_SIMPLESCARDAPP_FRAME,
283 appname,
284 pos=pos,
285 size=size,
286 style=wx.DEFAULT_FRAME_STYLE)
287
288 if appicon:
289 _icon = wx.Icon(appicon, wx.BITMAP_TYPE_ICO)
290 self.SetIcon(_icon)
291 elif os.path.exists(smartcard.wx.ICO_SMARTCARD):
292 _icon = wx.Icon(smartcard.wx.ICO_SMARTCARD, wx.BITMAP_TYPE_ICO)
293 self.SetIcon(_icon)
294
295 boxsizer = wx.BoxSizer(wx.VERTICAL)
296 self.treeuserpanel = TreeAndUserPanelPanel(
297 self, apppanelclass, appstyle)
298 boxsizer.Add(self.treeuserpanel, 3, wx.EXPAND | wx.ALL)
299
300
301 if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD:
302 self.toolbar = ReaderToolbar.ReaderToolbar(self)
303 self.SetToolBar(self.toolbar)
304 else:
305 self.toolbar = None
306
307
308 if appstyle & smartcard.wx.SimpleSCardApp.PANEL_APDUTRACER:
309 self.apdutracerpanel = APDUTracerPanel.APDUTracerPanel(self)
310 boxsizer.Add(self.apdutracerpanel, 1, wx.EXPAND | wx.ALL)
311 else:
312 self.apdutracerpanel = None
313
314 self.SetSizer(boxsizer)
315 self.SetAutoLayout(True)
316
317 self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
318 if appstyle & smartcard.wx.SimpleSCardApp.TB_SMARTCARD:
319 self.Bind(
320 wx.EVT_COMBOBOX,
321 self.OnReaderComboBox,
322 self.toolbar.readercombobox)
323
325 """Called when frame is closed, i.e. on wx.EVT_CLOSE"""
326 evt.Skip()
327
329 """Called when frame application exits."""
330 self.Close(True)
331 evt.Skip()
332
339