| Trees | Indices | Help |
|
|---|
|
|
1 """GNUmed provider inbox handling widgets.
2 """
3 #================================================================
4 # $Source: /cvsroot/gnumed/gnumed/gnumed/client/wxpython/gmProviderInboxWidgets.py,v $
5 # $Id: gmProviderInboxWidgets.py,v 1.48 2010/02/02 13:56:42 ncq Exp $
6 __version__ = "$Revision: 1.48 $"
7 __author__ = "Karsten Hilbert <Karsten.Hilbert@gmx.net>"
8
9 import sys, logging
10
11
12 import wx
13
14
15 if __name__ == '__main__':
16 sys.path.insert(0, '../../')
17 from Gnumed.pycommon import gmI18N, gmDispatcher, gmTools, gmCfg, gmPG2, gmExceptions
18 from Gnumed.business import gmPerson, gmSurgery
19 from Gnumed.wxpython import gmGuiHelpers, gmListWidgets, gmPlugin, gmRegetMixin, gmPhraseWheel, gmEditArea, gmAuthWidgets, gmPatSearchWidgets
20 from Gnumed.wxGladeWidgets import wxgProviderInboxPnl, wxgTextExpansionEditAreaPnl
21
22
23 _log = logging.getLogger('gm.ui')
24 _log.info(__version__)
25
26 _indicator = {
27 -1: '',
28 0: '',
29 1: '!'
30 }
31 #============================================================
33
35
36 try:
37 self.__keyword = kwds['keyword']
38 del kwds['keyword']
39 except KeyError:
40 self.__keyword = None
41
42 wxgTextExpansionEditAreaPnl.wxgTextExpansionEditAreaPnl.__init__(self, *args, **kwds)
43
44 self.__init_ui()
45 self.__register_interests()
46 #--------------------------------------------------------
48 if not self.__valid_for_save():
49 return False
50
51 if self.__keyword is None:
52 result = gmPG2.add_text_expansion (
53 keyword = self._TCTRL_keyword.GetValue().strip(),
54 expansion = self._TCTRL_expansion.GetValue(),
55 public = self._RBTN_public.GetValue()
56 )
57 else:
58 gmPG2.edit_text_expansion (
59 keyword = self._TCTRL_keyword.GetValue().strip(),
60 expansion = self._TCTRL_expansion.GetValue()
61 )
62 result = True
63
64 return result
65 #--------------------------------------------------------
68 # if self.__keyword is not None:
69 # self._TCTRL_expansion.SetValue(u'')
70 #--------------------------------------------------------
71 # event handling
72 #--------------------------------------------------------
75 #--------------------------------------------------------
77 if self._TCTRL_keyword.GetValue().strip() == u'':
78 self._TCTRL_expansion.Enable(False)
79 else:
80 self._TCTRL_expansion.Enable(True)
81 #--------------------------------------------------------
82 # internal API
83 #--------------------------------------------------------
85
86 kwd = self._TCTRL_keyword.GetValue().strip()
87 if kwd == u'':
88 self._TCTRL_keyword.SetBackgroundColour('pink')
89 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without keyword.'), beep = True)
90 return False
91 self._TCTRL_keyword.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
92
93 if self._TCTRL_expansion.GetValue().strip() == u'':
94 self._TCTRL_expansion.SetBackgroundColour('pink')
95 gmDispatcher.send(signal = 'statustext', msg = _('Cannot save text expansion without expansion text.'), beep = True)
96 return False
97 self._TCTRL_expansion.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
98
99 return True
100 #--------------------------------------------------------
102
103 if keyword is not None:
104 self.__keyword = keyword
105
106 if self.__keyword is None:
107 self._TCTRL_keyword.SetValue(u'')
108 self._TCTRL_keyword.Enable(True)
109 self._TCTRL_expansion.SetValue(u'')
110 self._TCTRL_expansion.Enable(False)
111 self._RBTN_public.Enable(True)
112 self._RBTN_private.Enable(True)
113 self._RBTN_public.SetValue(1)
114 else:
115 expansion = gmPG2.expand_keyword(keyword = self.__keyword)
116 self._TCTRL_keyword.SetValue(self.__keyword)
117 self._TCTRL_keyword.Enable(False)
118 self._TCTRL_expansion.SetValue(gmTools.coalesce(expansion, u''))
119 self._TCTRL_expansion.Enable(True)
120 self._RBTN_public.Enable(False)
121 self._RBTN_private.Enable(False)
122 #============================================================
124
125 if parent is None:
126 parent = wx.GetApp().GetTopWindow()
127
128 #----------------------
129 def delete(keyword=None):
130 gmPG2.delete_text_expansion(keyword = keyword)
131 return True
132 #----------------------
133 def edit(keyword=None):
134 # add new keyword
135 ea = cTextExpansionEditAreaPnl(parent, -1, keyword=keyword)
136 dlg = gmEditArea.cGenericEditAreaDlg(parent, -1, edit_area = ea)
137 dlg.SetTitle (
138 gmTools.coalesce(keyword, _('Adding text expansion'), _('Editing text expansion "%s"'))
139 )
140 if dlg.ShowModal() == wx.ID_OK:
141 return True
142
143 return False
144 #----------------------
145 def refresh(lctrl=None):
146 kwds = [ [
147 r[0],
148 gmTools.bool2subst(r[1], gmTools.u_checkmark_thick, u''),
149 gmTools.bool2subst(r[2], gmTools.u_checkmark_thick, u''),
150 r[3]
151 ] for r in gmPG2.get_text_expansion_keywords()
152 ]
153 data = [ r[0] for r in gmPG2.get_text_expansion_keywords() ]
154 lctrl.set_string_items(kwds)
155 lctrl.set_data(data)
156 #----------------------
157
158 gmListWidgets.get_choices_from_list (
159 parent = parent,
160 msg = _('\nSelect the keyword you want to edit !\n'),
161 caption = _('Editing keyword-based text expansions ...'),
162 columns = [_('Keyword'), _('Public'), _('Private'), _('Owner')],
163 single_selection = True,
164 edit_callback = edit,
165 new_callback = edit,
166 delete_callback = delete,
167 refresh_callback = refresh
168 )
169 #============================================================
171
173
174 gmPhraseWheel.cPhraseWheel.__init__ (
175 self,
176 *args,
177 **kwargs
178 )
179 self.matcher = gmPerson.cMatchProvider_Provider()
180 self.SetToolTipString(_('Select a healthcare provider.'))
181 self.selection_only = True
182 #============================================================
183 # practice related widgets
184 #============================================================
185 # FIXME: this should be moved elsewhere !
187
188 if parent is None:
189 parent = wx.GetApp().GetTopWindow()
190
191 #-----------------------------------
192 def delete(workplace):
193
194 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
195 if workplace == curr_workplace:
196 gmDispatcher.send(signal = 'statustext', msg = _('Cannot delete the active workplace.'), beep = True)
197 return False
198
199 dlg = gmGuiHelpers.c2ButtonQuestionDlg (
200 parent,
201 -1,
202 caption = _('Deleting workplace ...'),
203 question = _('Are you sure you want to delete this workplace ?\n\n "%s"\n') % workplace,
204 show_checkbox = True,
205 checkbox_msg = _('delete configuration, too'),
206 checkbox_tooltip = _(
207 'Check this if you want to delete all configuration items\n'
208 'for this workplace along with the workplace itself.'
209 ),
210 button_defs = [
211 {'label': _('Delete'), 'tooltip': _('Yes, delete this workplace.'), 'default': True},
212 {'label': _('Do NOT delete'), 'tooltip': _('No, do NOT delete this workplace'), 'default': False}
213 ]
214 )
215
216 decision = dlg.ShowModal()
217 if decision != wx.ID_YES:
218 dlg.Destroy()
219 return False
220
221 include_cfg = dlg.checkbox_is_checked()
222 dlg.Destroy()
223
224 dbo_conn = gmAuthWidgets.get_dbowner_connection(procedure = _('delete workplace'))
225 if not dbo_conn:
226 return False
227
228 gmSurgery.delete_workplace(workplace = workplace, conn = dbo_conn, delete_config = include_cfg)
229 return True
230 #-----------------------------------
231 def edit(workplace=None):
232
233 available_plugins = gmPlugin.get_installed_plugins(plugin_dir='gui')
234
235 dbcfg = gmCfg.cCfgSQL()
236
237 if workplace is None:
238 dlg = wx.TextEntryDialog (
239 parent = parent,
240 message = _('Enter a descriptive name for the new workplace:'),
241 caption = _('Configuring GNUmed workplaces ...'),
242 defaultValue = u'',
243 style = wx.OK | wx.CENTRE
244 )
245 dlg.ShowModal()
246 workplace = dlg.GetValue().strip()
247 if workplace == u'':
248 gmGuiHelpers.gm_show_error(_('Cannot save a new workplace without a name.'), _('Configuring GNUmed workplaces ...'))
249 return False
250 curr_plugins = []
251 choices = available_plugins
252 else:
253 curr_plugins = gmTools.coalesce(dbcfg.get2 (
254 option = u'horstspace.notebook.plugin_load_order',
255 workplace = workplace,
256 bias = 'workplace'
257 ), []
258 )
259 choices = curr_plugins[:]
260 for p in available_plugins:
261 if p not in choices:
262 choices.append(p)
263
264 sels = range(len(curr_plugins))
265 new_plugins = gmListWidgets.get_choices_from_list (
266 parent = parent,
267 msg = _(
268 '\n'
269 'Select the plugin(s) to be loaded the next time\n'
270 'the client is restarted under the workplace:\n'
271 '\n'
272 ' [%s]'
273 '\n'
274 ) % workplace,
275 caption = _('Configuring GNUmed workplaces ...'),
276 choices = choices,
277 selections = sels,
278 columns = [_('Plugins')],
279 single_selection = False
280 )
281
282 if new_plugins == curr_plugins:
283 return True
284
285 if new_plugins is None:
286 return True
287
288 dbcfg.set (
289 option = u'horstspace.notebook.plugin_load_order',
290 value = new_plugins,
291 workplace = workplace
292 )
293
294 return True
295 #-----------------------------------
296 def refresh(lctrl):
297 workplaces = gmSurgery.gmCurrentPractice().workplaces
298 curr_workplace = gmSurgery.gmCurrentPractice().active_workplace
299 try:
300 sels = [workplaces.index(curr_workplace)]
301 except ValueError:
302 sels = []
303
304 lctrl.set_string_items(workplaces)
305 lctrl.set_selections(selections = sels)
306 #-----------------------------------
307 gmListWidgets.get_choices_from_list (
308 parent = parent,
309 msg = _(
310 '\nSelect the workplace to configure below.\n'
311 '\n'
312 'The currently active workplace is preselected.\n'
313 ),
314 caption = _('Configuring GNUmed workplaces ...'),
315 columns = [_('Workplace')],
316 single_selection = True,
317 refresh_callback = refresh,
318 edit_callback = edit,
319 new_callback = edit,
320 delete_callback = delete
321 )
322 #============================================================
323 -class cProviderInboxPnl(wxgProviderInboxPnl.wxgProviderInboxPnl, gmRegetMixin.cRegetOnPaintMixin):
324
325 _item_handlers = {}
326 _patient_msg_types = ['clinical.review docs', 'clinical.review results']
327 #--------------------------------------------------------
329
330 wxgProviderInboxPnl.wxgProviderInboxPnl.__init__(self, *args, **kwds)
331 gmRegetMixin.cRegetOnPaintMixin.__init__(self)
332
333 self.provider = gmPerson.gmCurrentProvider()
334 self.filter_mode = 'all'
335 self.__init_ui()
336
337 cProviderInboxPnl._item_handlers['clinical.review docs'] = self._goto_doc_review
338 cProviderInboxPnl._item_handlers['clinical.review results'] = self._goto_measurements_review
339
340 self.__register_interests()
341 #--------------------------------------------------------
342 # reget-on-paint API
343 #--------------------------------------------------------
347 #--------------------------------------------------------
348 # internal helpers
349 #--------------------------------------------------------
351 gmDispatcher.connect(signal = u'message_inbox_generic_mod_db', receiver = self._on_message_inbox_mod_db)
352 gmDispatcher.connect(signal = u'message_inbox_mod_db', receiver = self._on_message_inbox_mod_db)
353 # FIXME: listen for results insertion/deletion
354 gmDispatcher.connect(signal = u'reviewed_test_results_mod_db', receiver = self._on_message_inbox_mod_db)
355 # FIXME: listen for doc insertion/deletion
356 # FIXME: listen for doc reviews
357 gmDispatcher.connect(signal = u'post_patient_selection', receiver = self._on_post_patient_selection)
358 #--------------------------------------------------------
360 self._LCTRL_provider_inbox.set_columns([u'', _('date'), _('category'), _('type'), _('message')])
361
362 msg = _('\n Inbox of %(title)s %(lname)s.\n') % {
363 'title': gmTools.coalesce (
364 self.provider['title'],
365 gmPerson.map_gender2salutation(self.provider['gender'])
366 ),
367 'lname': self.provider['lastnames']
368 }
369
370 self._msg_welcome.SetLabel(msg)
371
372 if gmPerson.gmCurrentPatient().connected:
373 self._RBTN_active_patient.Enable()
374 #--------------------------------------------------------
376
377 """Fill UI with data."""
378 self.__msgs = self.provider.inbox.messages
379
380 if self.filter_mode == 'active':
381 if gmPerson.gmCurrentPatient().connected:
382 curr_pat_id = gmPerson.gmCurrentPatient().ID
383 self.__msgs = [ m for m in self.__msgs if m['pk_patient'] == curr_pat_id ]
384 else:
385 self.__msgs = []
386
387 items = [
388 [
389 _indicator[m['importance']],
390 m['received_when'].strftime('%Y-%m-%d'),
391 m['l10n_category'],
392 m['l10n_type'],
393 m['comment']
394 ] for m in self.__msgs
395 ]
396 self._LCTRL_provider_inbox.set_string_items(items = items)
397 self._LCTRL_provider_inbox.set_data(data = self.__msgs)
398 self._LCTRL_provider_inbox.set_column_widths()
399 #--------------------------------------------------------
400 # event handlers
401 #--------------------------------------------------------
405 #--------------------------------------------------------
407 wx.CallAfter(self._schedule_data_reget)
408 gmDispatcher.send(signal = u'request_user_attention', msg = _('Please check your GNUmed Inbox !'))
409 #--------------------------------------------------------
411 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
412 if msg is None:
413 return
414
415 handler_key = '%s.%s' % (msg['category'], msg['type'])
416 try:
417 handle_item = cProviderInboxPnl._item_handlers[handler_key]
418 except KeyError:
419 gmGuiHelpers.gm_show_warning (
420 _(
421 """No double-click action pre-programmed into
422 GNUmed for message category and type:
423
424 [%s]
425 """
426 ) % handler_key,
427 _('handling provider inbox item')
428 )
429 return False
430
431 if not handle_item(pk_context = msg['pk_context'], pk_patient = msg['pk_patient']):
432 _log.error('item handler returned "false"')
433 _log.error('handler key: [%s]', handler_key)
434 _log.error('message: %s', str(msg))
435 return False
436
437 return True
438 #--------------------------------------------------------
441 #--------------------------------------------------------
443 msg = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
444 if msg is None:
445 return
446
447 if msg['data'] is None:
448 tmp = _('Message: %s') % msg['comment']
449 else:
450 tmp = _('Message: %s\nData: %s') % (msg['comment'], msg['data'])
451
452 self._TXT_inbox_item_comment.SetValue(tmp)
453 #--------------------------------------------------------
455 tmp = self._LCTRL_provider_inbox.get_selected_item_data(only_one = True)
456 if tmp is None:
457 return
458 self.__focussed_msg = tmp
459
460 # build menu
461 menu = wx.Menu(title = _('Inbox Message menu'))
462 # - delete message
463 if not self.__focussed_msg['is_virtual']:
464 ID = wx.NewId()
465 menu.AppendItem(wx.MenuItem(menu, ID, _('delete message')))
466 wx.EVT_MENU(menu, ID, self._on_delete_focussed_msg)
467
468 # show menu
469 self.PopupMenu(menu, wx.DefaultPosition)
470 menu.Destroy()
471 #--------------------------------------------------------
476 #--------------------------------------------------------
481 #--------------------------------------------------------
482 # item handlers
483 #--------------------------------------------------------
485 if self.__focussed_msg['is_virtual']:
486 gmDispatcher.send(signal = 'statustext', msg = _('You must deal with the reason for this message to remove it from your inbox.'), beep = True)
487 return False
488
489 if not self.provider.inbox.delete_message(self.__focussed_msg['pk_message_inbox']):
490 gmDispatcher.send(signal='statustext', msg=_('Problem removing message from Inbox.'))
491 return False
492 return True
493 #--------------------------------------------------------
495 wx.BeginBusyCursor()
496
497 try:
498 pat = gmPerson.cIdentity(aPK_obj = pk_patient)
499 except gmExceptions.ConstructorError:
500 wx.EndBusyCursor()
501 _log.exception('patient [%s] not found', pk_patient)
502 gmGuiHelpers.gm_show_error (
503 _('Supposedly there are unreviewed documents\n'
504 'for patient [%s]. However, I cannot find\n'
505 'that patient in the GNUmed database.'
506 ) % pk_patient,
507 _('handling provider inbox item')
508 )
509 return False
510
511 success = gmPatSearchWidgets.set_active_patient(patient = pat)
512
513 wx.EndBusyCursor()
514
515 if not success:
516 gmGuiHelpers.gm_show_error (
517 _('Supposedly there are unreviewed documents\n'
518 'for patient [%s]. However, I cannot find\n'
519 'that patient in the GNUmed database.'
520 ) % pk_patient,
521 _('handling provider inbox item')
522 )
523 return False
524
525 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmShowMedDocs', sort_mode = 'review')
526 return True
527 #--------------------------------------------------------
529 wx.BeginBusyCursor()
530 success = gmPatSearchWidgets.set_active_patient(patient=gmPerson.cIdentity(aPK_obj=pk_patient))
531 wx.EndBusyCursor()
532 if not success:
533 gmGuiHelpers.gm_show_error (
534 _('Supposedly there are unreviewed results\n'
535 'for patient [%s]. However, I cannot find\n'
536 'that patient in the GNUmed database.'
537 ) % pk_patient,
538 _('handling provider inbox item')
539 )
540 return False
541
542 wx.CallAfter(gmDispatcher.send, signal = 'display_widget', name = 'gmMeasurementsGridPlugin')
543 return True
544 #============================================================
545 if __name__ == '__main__':
546
547 gmI18N.activate_locale()
548 gmI18N.install_domain(domain = 'gnumed')
549
553
555 app = wx.PyWidgetTester(size = (800, 600))
556 app.SetWidget(cProviderInboxPnl, -1)
557 app.MainLoop()
558
559 if len(sys.argv) > 1 and sys.argv[1] == 'test':
560 #test_configure_wp_plugins()
561 test_message_inbox()
562
563 #============================================================
564 # $Log: gmProviderInboxWidgets.py,v $
565 # Revision 1.48 2010/02/02 13:56:42 ncq
566 # - text expansion management typo fix
567 #
568 # Revision 1.47 2010/01/10 17:29:26 ncq
569 # - slightly postpone plugin raising after message double-clicking
570 # to avoid async problems with patient activation plugin raising
571 #
572 # Revision 1.46 2010/01/06 14:43:55 ncq
573 # - inbox title flush left
574 #
575 # Revision 1.45 2009/11/30 22:27:57 ncq
576 # - adjust provider inbox filters
577 #
578 # Revision 1.44 2009/11/30 13:16:27 ncq
579 # - no deletion of .is_virtual messages
580 # - data update after patient activation
581 # - enabling active-patient filter on init, too
582 #
583 # Revision 1.43 2009/11/29 13:07:15 ncq
584 # - properly map messages to check boxes as per list
585 #
586 # Revision 1.42 2009/11/28 20:07:08 ncq
587 # - fix message detail display
588 #
589 # Revision 1.41 2009/08/24 20:11:27 ncq
590 # - bump db version
591 # - fix tag creation
592 # - provider inbox:
593 # enable filter-to-active-patient,
594 # listen to new signal,
595 # use cInboxMessage class
596 # - properly constrain LOINC phrasewheel SQL
597 # - include v12 scripts in release
598 # - install arriba jar to /usr/local/bin/
599 # - check for table existence in audit schema generator
600 # - include dem.message inbox with additional generic signals
601 #
602 # Revision 1.40 2009/07/01 17:12:11 ncq
603 # - better wording
604 #
605 # Revision 1.39 2009/06/29 15:10:58 ncq
606 # - prevent deletion of the active workplace
607 #
608 # Revision 1.38 2009/06/22 09:28:21 ncq
609 # - improved wording as per list
610 #
611 # Revision 1.37 2009/06/20 12:47:38 ncq
612 # - test
613 #
614 # Revision 1.36 2009/06/11 12:37:25 ncq
615 # - much simplified initial setup of list ctrls
616 #
617 # Revision 1.35 2009/06/04 16:30:30 ncq
618 # - use set active patient from pat search widgets
619 #
620 # Revision 1.34 2009/05/18 15:32:42 ncq
621 # - add deleting workplaces
622 #
623 # Revision 1.33 2009/02/18 13:47:43 ncq
624 # - do not throw exception in _goto_doc_review if patient
625 # does not exist, rather report error
626 #
627 # Revision 1.32 2009/01/17 23:09:30 ncq
628 # - cleanup
629 #
630 # Revision 1.31 2008/10/22 12:21:57 ncq
631 # - use %x in strftime where appropriate
632 #
633 # Revision 1.30 2008/09/04 12:52:23 ncq
634 # - display received_when for incoming messages
635 #
636 # Revision 1.29 2008/07/13 16:14:59 ncq
637 # - implement keyword based text expansion widgets
638 #
639 # Revision 1.28 2008/06/09 15:36:58 ncq
640 # - provider phrasewheel
641 #
642 # Revision 1.27 2008/05/20 16:45:43 ncq
643 # - add filter for active patient messages
644 # - fix longstanding bug updating display on *every* PAINT event
645 #
646 # Revision 1.26 2008/04/22 21:19:22 ncq
647 # - signal busy-ness when activating patient
648 #
649 # Revision 1.25 2008/03/29 16:21:16 ncq
650 # - handle unreviewed tests messages
651 # - listen to review changes
652 #
653 # Revision 1.24 2008/03/05 22:30:14 ncq
654 # - new style logging
655 #
656 # Revision 1.23 2008/02/25 17:40:45 ncq
657 # - establish db cfg instance early enough
658 #
659 # Revision 1.22 2008/01/30 14:03:42 ncq
660 # - use signal names directly
661 # - switch to std lib logging
662 #
663 # Revision 1.21 2008/01/27 21:18:45 ncq
664 # - don't crash on trying to edit module-less workplace
665 #
666 # Revision 1.20 2008/01/05 16:41:27 ncq
667 # - remove logging from gm_show_*()
668 #
669 # Revision 1.19 2007/11/28 11:56:30 ncq
670 # - better logging
671 #
672 # Revision 1.18 2007/11/23 23:36:38 ncq
673 # - finish configure_workplace_plugins()
674 #
675 # Revision 1.17 2007/11/02 13:59:33 ncq
676 # - request user attention when new item arrives
677 #
678 # Revision 1.16 2007/10/30 12:51:45 ncq
679 # - make it a reget mixin child
680 # - cleanup
681 # - listen on backend changes
682 #
683 # Revision 1.15 2007/10/08 13:05:10 ncq
684 # - use gmListWidgets.cReportListCtrl
685 # - fix right-click on empty message list crashes
686 # - start test suite
687 # - start configure_workplace_plugins()
688 #
689 # Revision 1.14 2007/08/12 00:12:41 ncq
690 # - no more gmSignals.py
691 #
692 # Revision 1.13 2007/05/14 13:11:25 ncq
693 # - use statustext() signal
694 #
695 # Revision 1.12 2007/01/04 22:52:34 ncq
696 # - show proper salutation for people without title
697 #
698 # Revision 1.11 2006/12/17 20:46:24 ncq
699 # - cleanup
700 #
701 # Revision 1.10 2006/11/24 10:01:31 ncq
702 # - gm_beep_statustext() -> gm_statustext()
703 #
704 # Revision 1.9 2006/05/28 16:19:54 ncq
705 # - repopulate_ui() needed for receive_focus() from plugin base class
706 #
707 # Revision 1.8 2006/05/20 18:55:21 ncq
708 # - calculate handler via original category/type not i18ned one
709 #
710 # Revision 1.7 2006/05/16 15:56:03 ncq
711 # - properly resize columns
712 #
713 # Revision 1.6 2006/05/15 14:46:38 ncq
714 # - implement message deletion via context menu popup
715 #
716 # Revision 1.5 2006/05/15 13:39:31 ncq
717 # - cleanup
718 #
719 # Revision 1.4 2006/05/12 22:04:22 ncq
720 # - add _populate_with_data()
721 # - fully implement _goto_doc_review()
722 #
723 # Revision 1.3 2006/05/12 12:21:58 ncq
724 # - implement double-click item handling
725 # - use gmCurrentProvider
726 # - show message on item focused
727 #
728 # Revision 1.2 2006/01/22 18:10:52 ncq
729 # - now really display messages from backend
730 #
731 # Revision 1.1 2006/01/15 14:30:56 ncq
732 # - first crude cut at this
733 #
734 #
735
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Tue Feb 9 04:02:13 2010 | http://epydoc.sourceforge.net |