Package Gnumed :: Package timelinelib :: Package wxgui :: Package components :: Module cattree
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.wxgui.components.cattree

  1  # Copyright (C) 2009, 2010, 2011  Rickard Lindberg, Roger Lindberg 
  2  # 
  3  # This file is part of Timeline. 
  4  # 
  5  # Timeline is free software: you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation, either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Timeline is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>. 
 17   
 18   
 19  import wx 
 20  import wx.lib.agw.customtreectrl as customtreectrl 
 21   
 22  from timelinelib.db.exceptions import TimelineIOError 
 23  from timelinelib.db.observer import STATE_CHANGE_CATEGORY 
 24  from timelinelib.wxgui.dialogs.categoryeditor import WxCategoryEdtiorDialog 
 25  from timelinelib.wxgui.utils import _ask_question 
 26  from timelinelib.wxgui.utils import category_tree 
 27  import timelinelib.wxgui.utils as gui_utils 
 28   
 29   
 30  NO_CHECKBOX_TYPE = 0 
 31  CHECKBOX_TYPE = 1 
 32   
 33   
34 -class CategoriesTree(customtreectrl.CustomTreeCtrl):
35
36 - def __init__(self, parent, fn_handle_db_error):
37 style = wx.BORDER_SUNKEN 38 agwStyle = (customtreectrl.TR_HIDE_ROOT | 39 customtreectrl.TR_HAS_VARIABLE_ROW_HEIGHT | 40 customtreectrl.TR_LINES_AT_ROOT | 41 customtreectrl.TR_HAS_BUTTONS) 42 if version_str_to_tuple(wx.__version__) < (2, 8, 11, 0): 43 customtreectrl.CustomTreeCtrl.__init__(self, parent, style=style|agwStyle) 44 else: 45 customtreectrl.CustomTreeCtrl.__init__(self, parent, style=style, agwStyle=agwStyle) 46 self._create_gui() 47 self.controller = CategoriesTreeController(self, fn_handle_db_error)
48
49 - def initialize_from_db(self, db):
50 self.controller.initialize_from_db(db)
51
52 - def initialize_from_timeline_view(self, view):
53 self.controller.initialize_from_timeline_view(view)
54
55 - def set_category_tree(self, tree, view_properties):
56 self.DeleteAllItems() 57 self.root = self.AddRoot("") # Hidden because of TR_HIDE_ROOT 58 self._update_categories_from_tree(tree, self.root, view_properties) 59 self.ExpandAll()
60
61 - def get_selected_category(self):
62 item = self.GetSelection() 63 if item is None: 64 return None 65 category = self.GetPyData(item) 66 return category
67
68 - def destroy(self):
69 self.controller.destroy()
70
71 - def _create_gui(self):
72 # Context menu 73 self.mnu = wx.Menu() 74 self.mnu_edit = wx.MenuItem(self.mnu, wx.ID_ANY, _("Edit...")) 75 self.Bind(wx.EVT_MENU, self._mnu_edit_on_click, self.mnu_edit) 76 self.mnu.AppendItem(self.mnu_edit) 77 self.mnu_add = wx.MenuItem(self.mnu, wx.ID_ANY, _("Add...")) 78 self.Bind(wx.EVT_MENU, self._mnu_add_on_click, self.mnu_add) 79 self.mnu.AppendItem(self.mnu_add) 80 self.mnu_delete = wx.MenuItem(self.mnu, wx.ID_ANY, _("Delete")) 81 self.Bind(wx.EVT_MENU, self._mnu_delete_on_click, self.mnu_delete) 82 self.mnu.AppendItem(self.mnu_delete) 83 # Events on control 84 self.Bind(customtreectrl.EVT_TREE_ITEM_CHECKED, 85 self._on_tree_item_checked, self) 86 self.Bind(wx.EVT_RIGHT_DOWN, self._on_right_down) 87 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
88
89 - def _update_menu_enableness(self):
90 enable_if_item = [self.mnu_edit, self.mnu_delete] 91 enable = self.get_selected_category() is not None 92 for menu_item in enable_if_item: 93 menu_item.Enable(enable)
94
95 - def _update_categories_from_tree(self, tree, root_item, view_properties):
96 for (cat, subtree) in tree: 97 legend_panel = wx.Panel(self, size=(10, 10)) 98 legend_panel.SetBackgroundColour(cat.color) 99 if view_properties: 100 ct_type = CHECKBOX_TYPE 101 else: 102 ct_type = NO_CHECKBOX_TYPE 103 item = self.AppendItem(root_item, cat.name, ct_type=ct_type, 104 wnd=legend_panel, data=cat) 105 if view_properties: 106 visible = view_properties.category_visible(cat) 107 self.CheckItem2(item, visible) 108 self._update_categories_from_tree(subtree, item, view_properties)
109
110 - def _on_right_down(self, e):
111 (item, flags) = self.HitTest(e.GetPosition()) 112 if item is not None: 113 self.SelectItem(item, True) 114 self._update_menu_enableness() 115 self.PopupMenu(self.mnu)
116
117 - def _on_key_down(self, e):
118 if self.GetFirstVisibleItem() is None: 119 return 120 keycode = e.GetKeyCode() 121 if keycode == wx.WXK_DELETE: 122 self.controller.delete_selected_category() 123 e.Skip()
124
125 - def _mnu_add_on_click(self, e):
126 self.controller.add_category()
127
128 - def _mnu_edit_on_click(self, e):
129 self.controller.edit_selected_category()
130
131 - def _mnu_delete_on_click(self, e):
132 self.controller.delete_selected_category()
133
134 - def _on_tree_item_checked(self, e):
135 tree_item = e.GetItem() 136 cat = tree_item.GetData() 137 tree_item_checked = tree_item.IsChecked() 138 self.controller.check_category(cat, tree_item_checked)
139 140
141 -class CategoriesTreeController(object):
142
143 - def __init__(self, view, fn_handle_db_error):
144 self.view = view 145 self.db = None 146 self.timeline_view = None 147 self.fn_handle_db_error = fn_handle_db_error
148
149 - def initialize_from_db(self, db):
150 self._change_active_db(db) 151 self.timeline_view = None 152 self._update_category_tree()
153
154 - def initialize_from_timeline_view(self, view):
155 if view is None: 156 new_timeline = None 157 else: 158 new_timeline = view.get_timeline() 159 self._change_active_db(new_timeline) 160 self.timeline_view = view 161 self._update_category_tree()
162
163 - def add_category(self):
164 add_category(self.view, self.db, self.fn_handle_db_error)
165
166 - def edit_selected_category(self):
167 cat = self.view.get_selected_category() 168 if cat: 169 edit_category(self.view, self.db, cat, self.fn_handle_db_error)
170
171 - def delete_selected_category(self):
172 cat = self.view.get_selected_category() 173 if cat: 174 delete_category(self.view, self.db, cat, self.fn_handle_db_error)
175
176 - def check_category(self, cat, checked):
177 if self.timeline_view is None: 178 raise Exception("Checking not allowed when there is no " 179 "timeline view.") 180 self.timeline_view.get_view_properties().set_category_visible(cat, checked) 181 self.timeline_view.redraw_timeline()
182
183 - def destroy(self):
184 if self.db: 185 self.db.unregister(self._db_on_changed)
186
187 - def _change_active_db(self, new_db):
188 if self.db: 189 self.db.unregister(self._db_on_changed) 190 self.db = new_db 191 if self.db: 192 self.db.register(self._db_on_changed)
193
194 - def _db_on_changed(self, state_change):
195 if state_change == STATE_CHANGE_CATEGORY: 196 self._update_category_tree()
197
198 - def _update_category_tree(self):
199 try: 200 if self.db: 201 categories = self.db.get_categories() 202 else: 203 categories = [] 204 except TimelineIOError, e: 205 self.fn_handle_db_error(e) 206 else: 207 tree = category_tree(categories) 208 if self.timeline_view: 209 vp = self.timeline_view.get_view_properties() 210 else: 211 vp = None 212 self.view.set_category_tree(tree, vp)
213 214
215 -def edit_category(parent_ctrl, db, cat, fn_handle_db_error):
216 def create_category_editor(): 217 return WxCategoryEdtiorDialog(parent_ctrl, _("Edit Category"), db, cat)
218 gui_utils.show_modal(create_category_editor, fn_handle_db_error) 219 220
221 -def add_category(parent_ctrl, db, fn_handle_db_error):
222 def create_category_editor(): 223 return WxCategoryEdtiorDialog(parent_ctrl, _("Add Category"), db, None)
224 gui_utils.show_modal(create_category_editor, fn_handle_db_error) 225 226
227 -def delete_category(parent_ctrl, db, cat, fn_handle_db_error):
228 delete_warning = _("Are you sure you want to " 229 "delete category '%s'?") % cat.name 230 if cat.parent is None: 231 update_warning = _("Events belonging to '%s' will no longer " 232 "belong to a category.") % cat.name 233 else: 234 update_warning = _("Events belonging to '%s' will now belong " 235 "to '%s'.") % (cat.name, cat.parent.name) 236 question = "%s\n\n%s" % (delete_warning, update_warning) 237 if _ask_question(question, parent_ctrl) == wx.YES: 238 try: 239 db.delete_category(cat) 240 except TimelineIOError, e: 241 fn_handle_db_error(e)
242 243
244 -def version_str_to_tuple(version_str):
245 """ 246 >>> version_str_to_tuple("0.4.44.3") 247 (0, 4, 44, 3) 248 """ 249 return tuple([int(x) for x in version_str.split(".")])
250