* src/DisplayState.py: Correct and add comments.

svn: r5546
This commit is contained in:
Alex Roitman 2005-12-14 04:06:42 +00:00
parent dcbe6c9326
commit 070e1f07b8
2 changed files with 101 additions and 37 deletions

View File

@ -1,3 +1,6 @@
2005-12-13 Alex Roitman <shura@gramps-project.org>
* src/DisplayState.py: Correct and add comments.
2005-12-13 Don Allingham <don@gramps-project.org>
* src/EditPerson.py: fix after merge
* src/GrampsDbBase.py: fix after merge

View File

@ -132,61 +132,122 @@ class History(GrampsDBCallback.GrampsDBCallback):
#
#-------------------------------------------------------------------------
class GrampsWindowManager:
"""
Manage hierarchy of open GRAMPS windows.
This class's purpose is to manage the hierarchy of open windows.
The idea is to maintain the tree of branches and leaves.
A leaf does not have children and corresponds to a single open window.
A branch has children and corresponds to a group of windows.
We will follow the convention of having first leaf in any given
branch represent a parent window of the group, and the rest of the
children leaves/branches represent windows spawned from the parent.
The tree structure is maintained as a list of items.
Items which are lists are branches.
Items which are not lists are leaves.
Lookup of an item is done via track sequence. The elements of
the track sequence specify the lookup order: [2,3,1] means
'take the second item of the tree, take its third child, and
then the first child of that child'.
Lookup can be also done by ID for windows that are identifiable.
"""
def __init__(self):
# initialize empty tree and lookup dictionary
self.window_tree = []
self.id2item = {}
def get_item_from_node(self,node):
def get_item_from_track(self,track):
# Recursively find an item given track sequence
item = self.window_tree
for index in node:
for index in track:
item = item[index]
return item
def get_window_from_id(self,window_id):
return self.id2item.get(window_id,None)
def get_item_from_id(self,item_id):
# Find an item given its ID
# Return None if the ID is not found
return self.id2item.get(item_id,None)
def close_node(self,node):
import traceback
traceback.print_stack()
item = self.get_item_from_node(node)
self.close_item_recursively(item)
self.remove_node(node)
def close_item(self,track):
# This is called when item needs to be closed
# Closes all its children and then removes the item from the tree.
item = self.get_item_from_track(track)
last_item = self.close_item_recursively(item)
# now we have the only surviving item from possibly a huge
# nested group of items
if last_item.window_id:
del self.id2item[last_item.window_id]
last_item.window.destroy()
self.remove_item(track)
def close_item_recursively(self,item):
# This function calls children's close_item() method
# to let the children go away cleanly. Then it returns
# the actual window item to later remove from dictionary
# and delete.
if type(item) == list:
# If this item is a branch
# close the children except for the first one
for sub_item in item[1:]:
self.close_item_recursively(sub_item)
self.close_item(sub_item)
# return the first child
the_item = item[0]
else:
if item.window_id:
del self.id2item[item.window_id]
item.window.destroy()
# This item is a leaf -- no children to close
# return itself
the_item = item
return the_item
def add_item(self,node,item):
def remove_item(self,track):
# We need the whole gymnastics below because our item
# may actually be a list consisting of a single real
# item and empty lists.
# find the track corresponding to the parent item
parent_track = track[:-1]
# find index of our item in parent
child_in_parent = track[-1:][0]
# obtain parent item and remove our item from it
parent_item = self.get_item_from_track(parent_track)
parent_item.pop(child_in_parent)
# Rebuild menu
self.build_windows_menu()
def add_item(self,track,item):
# if the item is identifiable then we need to remember
# its id so that in the future we recall this window
# instead of spawning a new one
if item.window_id:
self.id2item[item.window_id] = item
parent_item = self.get_item_from_node(node)
assert type(parent_item) == list or node == [], \
"Gwm: add_item: Incorrect node."
# Make sure we have a track
parent_item = self.get_item_from_track(track)
assert type(parent_item) == list or track == [], \
"Gwm: add_item: Incorrect track."
# Prepare a new item, depending on whether it is branch or leaf
if item.submenu_label:
# This is an item with potential children
# This is an item with potential children -- branch
new_item = [item]
else:
# This is an item without children
# This is an item without children -- leaf
new_item = item
parent_item.append(new_item)
new_node = node + [len(parent_item) + 1]
self.build_windows_menu()
return new_node
def remove_node(self,node):
parent_node = node[:-1]
child_in_parent = node[-1:][0]
item = self.get_item_from_node(parent_node)
item.pop(child_in_parent)
# append new item to the parent
parent_item.append(new_item)
# rebuild the Windows menu based on the new tree
self.build_windows_menu()
# prepare new track corresponding to the added item and return it
new_track = track + [len(parent_item)-1]
return new_track
def call_back_factory(self,item):
if type(item) != list:
def f(obj):
@ -217,7 +278,7 @@ class ManagedWindow:
event, and presenting itself when selected or attempted to create again.
"""
def __init__(self,uistate,node,window_key,submenu_label,menu_label):
def __init__(self,uistate,track,window_key,submenu_label,menu_label):
"""
Create child windows and add itself to menu, if not there already.
@ -227,13 +288,13 @@ class ManagedWindow:
import DisplayState
class SomeWindowClass(DisplayState.ManagedWindow):
def __init__(self,uistate,dbstate,node):
def __init__(self,uistate,dbstate,track):
window_id = self # Or e.g. window_id = person.handle
submenu_label = None # This window cannot have children
menu_label = 'Menu label for this window'
DisplayState.ManagedWindow.__init__(self,
uistate,
node,
track,
window_id,
submenu_label,
menu_label)
@ -244,8 +305,8 @@ class ManagedWindow:
...
"""
if uistate.gwm.get_window_from_id(window_key):
uistate.gwm.get_window_from_id(window_key).present()
if uistate.gwm.get_item_from_id(window_key):
uistate.gwm.get_item_from_id(window_key).present()
self.already_exist = True
else:
self.already_exist = False
@ -253,7 +314,7 @@ class ManagedWindow:
self.submenu_label = submenu_label
self.menu_label = menu_label
self.uistate = uistate
self.node = self.uistate.gwm.add_item(node,self)
self.track = self.uistate.gwm.add_item(track,self)
def close(self):
"""
@ -261,7 +322,7 @@ class ManagedWindow:
Takes care of closing children and removing itself from menu.
"""
self.uistate.gwm.close_node(self.node)
self.uistate.gwm.close_item(self.track)
def present(self):
"""