1 """GNUmed Horst-space inner-frame layout manager.
2
3 This implements the simple wx.Notebook based layout as
4 originally suggested by Horst Herb.
5
6 copyright: authors
7 """
8
9 __version__ = "$Revision: 1.47 $"
10 __author__ = "H. Herb <hherb@gnumed.net>,\
11 K. Hilbert <Karsten.Hilbert@gmx.net>,\
12 I. Haywood <i.haywood@ugrad.unimelb.edu.au>"
13 __license__ = 'GPL v2 or later (details at http://www.gnu.org)'
14
15 import os.path, os, sys, logging
16
17
18 import wx
19
20
21 from Gnumed.pycommon import gmGuiBroker, gmI18N, gmDispatcher, gmCfg
22 from Gnumed.wxpython import gmPlugin, gmTopPanel, gmGuiHelpers
23 from Gnumed.business import gmPerson, gmPraxis
24
25
26 _log = logging.getLogger('gm.ui')
27 _log.info(__version__)
28
29
31 """GNUmed inner-frame layout manager.
32
33 This implements a Horst-space notebook-only
34 "inner-frame" layout manager.
35 """
37
38 wx.Panel.__init__(
39 self,
40 parent = parent,
41 id = id,
42 pos = wx.DefaultPosition,
43 size = wx.DefaultSize,
44 style = wx.NO_BORDER,
45 name = 'HorstSpace.LayoutMgrPnl'
46 )
47
48 self.nb = wx.Notebook (
49 parent=self,
50 id = -1,
51 size = wx.Size(320,240),
52 style = wx.NB_BOTTOM
53 )
54
55 self.__gb = gmGuiBroker.GuiBroker()
56 self.__gb['horstspace.notebook'] = self.nb
57
58
59
60
61
62
63 self.top_panel = gmTopPanel.cTopPnl(self, -1)
64 self.__gb['horstspace.top_panel'] = self.top_panel
65 self.__load_plugins()
66
67
68 self.main_szr = wx.BoxSizer(wx.VERTICAL)
69 self.main_szr.Add(self.top_panel, 0, wx.EXPAND)
70 self.main_szr.Add(self.nb, 1, wx.EXPAND)
71 self.SetSizer(self.main_szr)
72
73
74
75
76 self.__register_events()
77
78
79
81
82 self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self._on_notebook_page_changing)
83
84 self.nb.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self._on_notebook_page_changed)
85
86 wx.EVT_RIGHT_UP(self.nb, self._on_right_click)
87
88 gmDispatcher.connect(self._on_post_patient_selection, u'post_patient_selection')
89
91
92 plugin_list = gmPlugin.GetPluginLoadList (
93 option = 'horstspace.notebook.plugin_load_order',
94 plugin_dir = 'gui',
95 defaults = ['gmProviderInboxPlugin']
96 )
97
98 nr_plugins = len(plugin_list)
99 wx.BeginBusyCursor()
100
101
102 progress_bar = gmPlugin.cLoadProgressBar(nr_plugins)
103
104
105 prev_plugin = ""
106 first_plugin = None
107 plugin = None
108 result = -1
109 for idx in range(nr_plugins):
110 curr_plugin = plugin_list[idx]
111 progress_bar.Update(result, curr_plugin)
112 try:
113 plugin = gmPlugin.instantiate_plugin('gui', curr_plugin)
114 if plugin:
115 plugin.register()
116 result = 1
117 else:
118 _log.error("plugin [%s] not loaded, see errors above", curr_plugin)
119 result = 1
120 except:
121 _log.exception('failed to load plugin %s', curr_plugin)
122 result = 0
123
124 if first_plugin is None:
125 first_plugin = plugin
126 prev_plugin = curr_plugin
127
128 progress_bar.Destroy()
129 wx.EndBusyCursor()
130
131
132 page = self.nb.GetPage(0)
133 page.Refresh()
134
135 return True
136
137
138
140 db_cfg = gmCfg.cCfgSQL()
141 default_plugin = db_cfg.get2 (
142 option = u'patient_search.plugin_to_raise_after_search',
143 workplace = gmPraxis.gmCurrentPraxisBranch().active_workplace,
144 bias = u'user',
145 default = u'gmPatientOverviewPlugin'
146 )
147 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = default_plugin)
148
150 """Called before notebook page change is processed."""
151
152 _log.debug('just before switching notebook tabs')
153
154 self.__new_page_already_checked = False
155
156 self.__id_nb_page_before_switch = self.nb.GetSelection()
157 self.__id_evt_page_before_switch = event.GetOldSelection()
158 __id_evt_page_after_switch = event.GetSelection()
159
160 _log.debug('event.GetOldSelection()=%s* -> event.GetSelection()=%s', self.__id_evt_page_before_switch, __id_evt_page_after_switch)
161
162 if self.__id_evt_page_before_switch != self.__id_nb_page_before_switch:
163 _log.debug('the following two should match but do not:')
164 _log.debug(' event.GetOldSelection(): %s', self.__id_evt_page_before_switch)
165 _log.debug(' notebook.GetSelection(): %s', self.__id_nb_page_before_switch)
166
167
168 if __id_evt_page_after_switch == self.__id_evt_page_before_switch:
169
170
171
172 _log.debug('this system is: sys: [%s] wx: [%s]', sys.platform, wx.Platform)
173 _log.debug('it seems to be one of those platforms that have no clue which notebook page they are switching to')
174 _log.debug('(Windows is documented to return the old page from both evt.GetOldSelection() and evt.GetSelection())')
175 _log.debug('current notebook page : %s', self.__id_nb_page_before_switch)
176 _log.debug('source page from event: %s', self.__id_evt_page_before_switch)
177 _log.debug('target page from event: %s', __id_evt_page_after_switch)
178 _log.info('cannot check whether notebook page change needs to be vetoed')
179
180 pat = gmPerson.gmCurrentPatient()
181 if not pat.connected:
182 gmDispatcher.send(signal = 'statustext', msg =_('Cannot change notebook tabs. No active patient.'))
183 event.Veto()
184 return
185
186 event.Allow()
187 event.Skip()
188 return
189
190
191 new_page = self.__gb['horstspace.notebook.pages'][__id_evt_page_after_switch]
192 if not new_page.can_receive_focus():
193 _log.debug('veto()ing page change')
194 event.Veto()
195 return
196
197
198 self.__new_page_already_checked = True
199 event.Allow()
200 event.Skip()
201 return
202
204 """Called when notebook page changes."""
205
206 _log.debug('just after switching notebook tabs')
207
208 id_evt_page_before_switch = event.GetOldSelection()
209 id_evt_page_after_switch = event.GetSelection()
210 id_nb_page_after_switch = self.nb.GetSelection()
211
212 _log.debug('event.GetOldSelection()=%s -> event.GetSelection()=%s*', id_evt_page_before_switch, id_evt_page_after_switch)
213
214 if self.__id_nb_page_before_switch != id_evt_page_before_switch:
215 _log.debug('those two really *should* match:')
216 _log.debug(' wx.Notebook.GetSelection() (before switch) : %s' % self.__id_nb_page_before_switch)
217 _log.debug(' EVT_NOTEBOOK_PAGE_CHANGED.GetOldSelection(): %s' % id_evt_page_before_switch)
218
219 new_page = self.__gb['horstspace.notebook.pages'][id_evt_page_after_switch]
220
221
222 if self.__new_page_already_checked:
223 new_page.receive_focus()
224
225
226 self.__new_page_already_checked = False
227 event.Skip()
228 return
229
230
231 _log.debug('target page not checked for focussability yet')
232 _log.debug('EVT_NOTEBOOK_PAGE_CHANGED.GetOldSelection(): %s' % id_evt_page_before_switch)
233 _log.debug('EVT_NOTEBOOK_PAGE_CHANGED.GetSelection() : %s' % id_evt_page_after_switch)
234 _log.debug('wx.Notebook.GetSelection() (after switch) : %s' % id_nb_page_after_switch)
235
236
237 if new_page.can_receive_focus():
238 _log.debug('we are lucky: new page *can* receive focus')
239 new_page.receive_focus()
240
241
242 event.Skip()
243 return
244
245 _log.warning('new page cannot receive focus but too late for veto')
246 event.Skip()
247 return
248
250 evt.Skip()
251 return
252
253 load_menu = wx.Menu()
254 any_loadable = 0
255 plugin_list = gmPlugin.GetPluginLoadList('gui')
256 plugin = None
257 for plugin_name in plugin_list:
258 try:
259 plugin = gmPlugin.instantiate_plugin('gui', plugin_name)
260 except StandardError:
261 continue
262
263 if not isinstance(plugin, gmPlugin.cNotebookPlugin):
264 plugin = None
265 continue
266
267 if plugin.__class__.__name__ in self.guibroker['horstspace.notebook.gui'].keys():
268 plugin = None
269 continue
270
271 nid = wx.NewId()
272 load_menu.AppendItem(wx.MenuItem(load_menu, nid, plugin.name()))
273 wx.EVT_MENU(load_menu, nid, plugin.on_load)
274 any_loadable = 1
275
276 menu = wx.Menu()
277 ID_LOAD = wx.NewId()
278 ID_DROP = wx.NewId()
279 if any_loadable:
280 menu.AppendMenu(ID_LOAD, _('add plugin ...'), load_menu)
281 plugins = self.guibroker['horstspace.notebook.gui']
282 raised_plugin = plugins[self.nb.GetSelection()].name()
283 menu.AppendItem(wx.MenuItem(menu, ID_DROP, "drop [%s]" % raised_plugin))
284 wx.EVT_MENU (menu, ID_DROP, self._on_drop_plugin)
285 self.PopupMenu(menu, evt.GetPosition())
286 menu.Destroy()
287 evt.Skip()
288
290 """Unload plugin and drop from load list."""
291 pages = self.guibroker['horstspace.notebook.pages']
292 page = pages[self.nb.GetSelection()]
293 page.unregister()
294 self.nb.AdvanceSelection()
295
296
298 """Unload plugin but don't touch configuration."""
299
300 pages = self.guibroker['horstspace.notebook.pages']
301 page = pages[self.nb.GetSelection()]
302 page.unregister()
303
304 if __name__ == '__main__':
305 wx.InitAllImageHandlers()
306 pgbar = gmPluginLoadProgressBar(3)
307
308
309