* src/DbState.py: Added new class to keep track of database
status * src/PageView.py: base class for pluggable views * src/PersonView.py: new version of PeopleView * src/ViewManager.py: view and database management class svn: r5040
This commit is contained in:
parent
f1b3c2c39f
commit
3e153e8f6e
@ -1,3 +1,10 @@
|
||||
2005-08-08 Don Allingham <don@gramps-project.org>
|
||||
* src/DbState.py: Added new class to keep track of database
|
||||
status
|
||||
* src/PageView.py: base class for pluggable views
|
||||
* src/PersonView.py: new version of PeopleView
|
||||
* src/ViewManager.py: view and database management class
|
||||
|
||||
2005-08-05 Don Allingham <don@gramps-project.org>
|
||||
* various: remove set_date/get_date removal to be replaced by
|
||||
DateHandler calls
|
||||
|
@ -313,7 +313,7 @@ class ArgHandler:
|
||||
# the InMem formats, without setting up a new database. Then
|
||||
# go on and process the rest of the command line arguments.
|
||||
|
||||
self.parent.cl = bool(self.exports or self.actions)
|
||||
#self.parent.cl = bool(self.exports or self.actions)
|
||||
|
||||
name,format = self.open
|
||||
success = False
|
||||
@ -339,7 +339,7 @@ class ArgHandler:
|
||||
os._exit(1)
|
||||
|
||||
if self.imports:
|
||||
self.parent.cl = bool(self.exports or self.actions or self.parent.cl)
|
||||
#self.parent.cl = bool(self.exports or self.actions or self.parent.cl)
|
||||
|
||||
# Create dir for imported database(s)
|
||||
self.impdir_path = os.path.expanduser("~/.gramps/import" )
|
||||
@ -373,33 +373,29 @@ class ArgHandler:
|
||||
"supply at least one input file to process."
|
||||
print "Launching interactive session..."
|
||||
|
||||
if self.parent.cl:
|
||||
for expt in self.exports:
|
||||
print "Exporting: file %s, format %s." % expt
|
||||
self.cl_export(expt[0],expt[1])
|
||||
# if self.parent.cl:
|
||||
# for expt in self.exports:
|
||||
# print "Exporting: file %s, format %s." % expt
|
||||
# self.cl_export(expt[0],expt[1])
|
||||
|
||||
for (action,options_str) in self.actions:
|
||||
print "Performing action: %s." % action
|
||||
if options_str:
|
||||
print "Using options string: %s" % options_str
|
||||
self.cl_action(action,options_str)
|
||||
# for (action,options_str) in self.actions:
|
||||
# print "Performing action: %s." % action
|
||||
# if options_str:
|
||||
# print "Using options string: %s" % options_str
|
||||
# self.cl_action(action,options_str)
|
||||
|
||||
print "Cleaning up."
|
||||
# remove import db after use
|
||||
self.parent.db.close()
|
||||
if self.imports:
|
||||
os.remove(self.imp_db_path)
|
||||
print "Exiting."
|
||||
os._exit(0)
|
||||
# print "Cleaning up."
|
||||
# # remove import db after use
|
||||
# self.parent.db.close()
|
||||
# if self.imports:
|
||||
# os.remove(self.imp_db_path)
|
||||
# print "Exiting."
|
||||
# os._exit(0)
|
||||
|
||||
if self.imports:
|
||||
self.parent.import_tool_callback()
|
||||
elif GrampsKeys.get_lastfile() and GrampsKeys.get_autoload():
|
||||
if self.auto_save_load(GrampsKeys.get_lastfile()) == 0:
|
||||
DbPrompter.DbPrompter(self.parent,0)
|
||||
else:
|
||||
DbPrompter.DbPrompter(self.parent,0)
|
||||
|
||||
self.auto_save_load(GrampsKeys.get_lastfile())
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@ -137,9 +137,9 @@ class ExistingDbPrompter:
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,parent,parent_window=None):
|
||||
self.parent = parent
|
||||
self.parent_window = parent_window
|
||||
def __init__(self,state):
|
||||
self.state = state
|
||||
self.parent_window = state.window
|
||||
|
||||
def chooser(self):
|
||||
"""
|
||||
@ -197,7 +197,7 @@ class ExistingDbPrompter:
|
||||
const.app_gedcom]:
|
||||
|
||||
try:
|
||||
return open_native(self.parent,filename,filetype)
|
||||
return self.open_native(self.state,filename,filetype)
|
||||
except db.DBInvalidArgError, msg:
|
||||
QuestionDialog.ErrorDialog(
|
||||
_("Could not open file: %s") % filename, msg[1])
|
||||
@ -221,8 +221,8 @@ class ExistingDbPrompter:
|
||||
self.parent_window)
|
||||
prompter = NewNativeDbPrompter(self.parent,self.parent_window)
|
||||
if prompter.chooser():
|
||||
importData(self.parent.db,filename)
|
||||
self.parent.import_tool_callback()
|
||||
importData(self.state.db,filename)
|
||||
#self.parent.import_tool_callback()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@ -400,7 +400,7 @@ class NewNativeDbPrompter:
|
||||
except:
|
||||
pass
|
||||
self.parent.db = GrampsBSDDB.GrampsBSDDB()
|
||||
self.parent.read_file(filename)
|
||||
self.read_file(filename)
|
||||
# Add the file to the recent items
|
||||
RecentFiles.recent_files(filename,const.app_gramps)
|
||||
self.parent.build_recent_menu()
|
||||
@ -497,7 +497,7 @@ class NewSaveasDbPrompter:
|
||||
WriteGedcom.exportData(self.parent.db,filename,None,None)
|
||||
self.parent.db.close()
|
||||
self.parent.db = GrampsGEDDB.GrampsGEDDB()
|
||||
self.parent.read_file(filename)
|
||||
self.read_file(filename)
|
||||
# Add the file to the recent items
|
||||
RecentFiles.recent_files(filename,const.app_gramps)
|
||||
self.parent.build_recent_menu()
|
||||
@ -508,47 +508,104 @@ class NewSaveasDbPrompter:
|
||||
choose.destroy()
|
||||
return False
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Helper function
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def open_native(parent,filename,filetype):
|
||||
"""
|
||||
Open native database and return the status.
|
||||
"""
|
||||
def read_file(self,filename,callback=None):
|
||||
mode = "w"
|
||||
filename = os.path.normpath(os.path.abspath(filename))
|
||||
|
||||
(the_path,the_file) = os.path.split(filename)
|
||||
GrampsKeys.save_last_import_dir(the_path)
|
||||
if os.path.isdir(filename):
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('The selected file is a directory, not '
|
||||
'a file.\nA GRAMPS database must be a file.'))
|
||||
return 0
|
||||
elif os.path.exists(filename):
|
||||
if not os.access(filename,os.R_OK):
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('You do not have read access to the selected '
|
||||
'file.'))
|
||||
return 0
|
||||
elif not os.access(filename,os.W_OK):
|
||||
mode = "r"
|
||||
WarningDialog(_('Read only database'),
|
||||
_('You do not have write access to the selected '
|
||||
'file.'))
|
||||
|
||||
success = False
|
||||
if filetype == const.app_gramps:
|
||||
parent.db = GrampsBSDDB.GrampsBSDDB()
|
||||
msgxml = gtk.glade.XML(const.gladeFile, "load_message","gramps")
|
||||
msg_top = msgxml.get_widget('load_message')
|
||||
msg_label = msgxml.get_widget('message')
|
||||
try:
|
||||
if self.load_database(filename,callback,mode=mode) == 1:
|
||||
if filename[-1] == '/':
|
||||
filename = filename[:-1]
|
||||
name = os.path.basename(filename)
|
||||
if self.state.db.readonly:
|
||||
self.state.window.set_title("%s (%s) - GRAMPS" % (name,_('Read Only')))
|
||||
else:
|
||||
self.state.window.set_title("%s - GRAMPS" % name)
|
||||
else:
|
||||
GrampsKeys.save_last_file("")
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('The database file specified could not be opened.'))
|
||||
return False
|
||||
except ( IOError, OSError, Errors.FileVersionError), msg:
|
||||
ErrorDialog(_('Cannot open database'),str(msg))
|
||||
return False
|
||||
except (db.DBAccessError,db.DBError), msg:
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('%s could not be opened.' % filename) + '\n' + msg[1])
|
||||
return False
|
||||
except Exception:
|
||||
DisplayTrace.DisplayTrace()
|
||||
return False
|
||||
|
||||
def update_msg(msg):
|
||||
msg_label.set_text("<i>%s</i>" % msg)
|
||||
msg_label.set_use_markup(True)
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
return True
|
||||
|
||||
success = parent.read_file(filename,update_msg)
|
||||
msg_top.destroy()
|
||||
elif filetype == const.app_gramps_xml:
|
||||
parent.db = GrampsXMLDB.GrampsXMLDB()
|
||||
success = parent.read_file(filename)
|
||||
elif filetype == const.app_gedcom:
|
||||
parent.db = GrampsGEDDB.GrampsGEDDB()
|
||||
success = parent.read_file(filename)
|
||||
def load_database(self,name,callback=None,mode="w"):
|
||||
|
||||
if success:
|
||||
filename = name
|
||||
|
||||
if self.state.db.load(filename,callback,mode) == 0:
|
||||
return 0
|
||||
|
||||
#val = self.post_load(name,callback)
|
||||
return val
|
||||
|
||||
|
||||
def open_native(self,filename,filetype):
|
||||
"""
|
||||
Open native database and return the status.
|
||||
"""
|
||||
|
||||
(the_path,the_file) = os.path.split(filename)
|
||||
GrampsKeys.save_last_import_dir(the_path)
|
||||
|
||||
success = False
|
||||
if filetype == const.app_gramps:
|
||||
state.db = GrampsBSDDB.GrampsBSDDB()
|
||||
msgxml = gtk.glade.XML(const.gladeFile, "load_message","gramps")
|
||||
msg_top = msgxml.get_widget('load_message')
|
||||
msg_label = msgxml.get_widget('message')
|
||||
|
||||
def update_msg(msg):
|
||||
msg_label.set_text("<i>%s</i>" % msg)
|
||||
msg_label.set_use_markup(True)
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
|
||||
success = self.read_file(filename,update_msg)
|
||||
msg_top.destroy()
|
||||
elif filetype == const.app_gramps_xml:
|
||||
state.db = GrampsXMLDB.GrampsXMLDB()
|
||||
success = self.read_file(filename)
|
||||
elif filetype == const.app_gedcom:
|
||||
state.db = GrampsGEDDB.GrampsGEDDB()
|
||||
success = self.read_file(filename)
|
||||
|
||||
#if success:
|
||||
# Add the file to the recent items
|
||||
RecentFiles.recent_files(filename,filetype)
|
||||
parent.build_recent_menu()
|
||||
#RecentFiles.recent_files(filename,filetype)
|
||||
#parent.build_recent_menu()
|
||||
|
||||
return success
|
||||
|
||||
|
||||
|
||||
return success
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
130
src/DbState.py
Normal file
130
src/DbState.py
Normal file
@ -0,0 +1,130 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GNOME python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import GrampsDbBase
|
||||
import GrampsDBCallback
|
||||
import GrampsKeys
|
||||
import NameDisplay
|
||||
|
||||
|
||||
class History:
|
||||
|
||||
def __init__(self):
|
||||
self.history = []
|
||||
self.mhistory = []
|
||||
self.index = -1
|
||||
self.lock = False
|
||||
|
||||
def clear(self):
|
||||
self.history = []
|
||||
self.mistory = []
|
||||
self.index = -1
|
||||
self.lock = False
|
||||
|
||||
def remove(self,person_handle,old_id=None):
|
||||
"""Removes a person from the history list"""
|
||||
if old_id:
|
||||
del_id = old_id
|
||||
else:
|
||||
del_id = person_handle
|
||||
|
||||
hc = self.history.count(del_id)
|
||||
for c in range(hc):
|
||||
self.history.remove(del_id)
|
||||
self.index -= 1
|
||||
|
||||
mhc = self.mhistory.count(del_id)
|
||||
for c in range(mhc):
|
||||
self.mhistory.remove(del_id)
|
||||
|
||||
class DbState(GrampsDBCallback.GrampsDBCallback):
|
||||
|
||||
__signals__ = {
|
||||
'database-changed' : (GrampsDbBase.GrampsDbBase,),
|
||||
'active-changed' : (str,),
|
||||
}
|
||||
|
||||
def __init__(self,window,status):
|
||||
self.window = window
|
||||
GrampsDBCallback.GrampsDBCallback.__init__(self)
|
||||
self.db = GrampsDbBase.GrampsDbBase()
|
||||
self.active = None
|
||||
self.status = status
|
||||
self.status_id = status.get_context_id('GRAMPS')
|
||||
self.phistory = History()
|
||||
|
||||
def clear_history(self):
|
||||
self.phistory.clear()
|
||||
|
||||
def change_active_person(self,person):
|
||||
self.active = person
|
||||
|
||||
def change_active_handle(self,handle):
|
||||
self.emit('active-changed',(handle,))
|
||||
|
||||
def get_active_person(self):
|
||||
return self.active
|
||||
|
||||
def change_database(self,db):
|
||||
self.db = db
|
||||
self.emit('database-changed',(self.db,))
|
||||
|
||||
def modify_statusbar(self):
|
||||
|
||||
self.status.pop(self.status_id)
|
||||
if self.active == None:
|
||||
self.status.push(self.status_id,"")
|
||||
else:
|
||||
if GrampsKeys.get_statusbar() <= 1:
|
||||
pname = NameDisplay.displayer.display(self.active)
|
||||
name = "[%s] %s" % (self.active.get_gramps_id(),pname)
|
||||
else:
|
||||
name = self.display_relationship()
|
||||
self.status.push(self.status_id,name)
|
||||
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
|
||||
def status_text(self,text):
|
||||
self.status.pop(self.status_id)
|
||||
self.status.push(self.status_id,text)
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
@ -796,7 +796,8 @@ class EditPerson:
|
||||
return changed
|
||||
|
||||
def check_lds(self):
|
||||
self.lds_baptism.set_date(unicode(self.ldsbap_date.get_text()))
|
||||
date_str = unicode(self.ldsbap_date.get_text())
|
||||
DateHandler.set_date(self.lds_baptism,date_str)
|
||||
temple = _temple_names[self.ldsbap_temple.get_active()]
|
||||
if const.lds_temple_codes.has_key(temple):
|
||||
self.lds_baptism.set_temple(const.lds_temple_codes[temple])
|
||||
@ -804,7 +805,8 @@ class EditPerson:
|
||||
self.lds_baptism.set_temple("")
|
||||
self.lds_baptism.set_place_handle(self.get_place(self.ldsbapplace,1))
|
||||
|
||||
self.lds_endowment.set_date(unicode(self.ldsend_date.get_text()))
|
||||
date_str = unicode(self.ldsend_date.get_text())
|
||||
DateHandler.set_date(self.lds_endowment,date_str)
|
||||
temple = _temple_names[self.ldsend_temple.get_active()]
|
||||
if const.lds_temple_codes.has_key(temple):
|
||||
self.lds_endowment.set_temple(const.lds_temple_codes[temple])
|
||||
@ -812,7 +814,8 @@ class EditPerson:
|
||||
self.lds_endowment.set_temple("")
|
||||
self.lds_endowment.set_place_handle(self.get_place(self.ldsendowplace,1))
|
||||
|
||||
self.lds_sealing.set_date(unicode(self.ldsseal_date.get_text()))
|
||||
date_str = unicode(self.ldsseal_date.get_text())
|
||||
DateHandler.set_date(self.lds_sealing,date_str)
|
||||
temple = _temple_names[self.ldsseal_temple.get_active()]
|
||||
if const.lds_temple_codes.has_key(temple):
|
||||
self.lds_sealing.set_temple(const.lds_temple_codes[temple])
|
||||
|
@ -384,7 +384,7 @@ class EventListBox(ReorderListBox):
|
||||
self.change_list.add(self.data[index])
|
||||
|
||||
def set_date(self,index,value):
|
||||
self.data[index][1].set_date(value)
|
||||
DateHandler.set_date(self.data[index][1],value)
|
||||
self.change_list.add(self.data[index])
|
||||
|
||||
def add(self,obj):
|
||||
@ -536,7 +536,7 @@ class AddressListBox(ReorderListBox):
|
||||
button_list, titles, DdTargets.ADDRESS)
|
||||
|
||||
def set_date(self,index,value):
|
||||
self.data[index].set_date(value)
|
||||
DateHandler.set_date(self.data[index],value)
|
||||
|
||||
def set_addr(self,index,value):
|
||||
self.data[index].set_street(value)
|
||||
|
@ -684,7 +684,7 @@ class Marriage:
|
||||
if not lds_ord:
|
||||
if date or temple or place or self.seal_stat:
|
||||
lds_ord = RelLib.LdsOrd()
|
||||
lds_ord.set_date(date)
|
||||
DateHandler.set_date(lds_ord,date)
|
||||
temple_code = const.lds_temple_codes.get(temple,"")
|
||||
lds_ord.set_temple(temple_code)
|
||||
lds_ord.set_status(self.seal_stat)
|
||||
|
73
src/PageView.py
Normal file
73
src/PageView.py
Normal file
@ -0,0 +1,73 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2001-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
import gtk
|
||||
|
||||
class PageView:
|
||||
|
||||
def __init__(self,title,state):
|
||||
self.title = title
|
||||
self.state = state
|
||||
self.action_list = []
|
||||
self.action_toggle_list = []
|
||||
self.action_group = None
|
||||
self.widget = None
|
||||
self.ui = ""
|
||||
|
||||
def get_stock(self):
|
||||
return gtk.STOCK_MEDIA_MISSING
|
||||
|
||||
def get_ui(self):
|
||||
return self.ui
|
||||
|
||||
def get_title(self):
|
||||
return self.title
|
||||
|
||||
def get_display(self):
|
||||
if not self.widget:
|
||||
self.widget = self.build_widget()
|
||||
return self.widget
|
||||
|
||||
def build_widget(self):
|
||||
assert False
|
||||
|
||||
def define_actions(self):
|
||||
assert False
|
||||
|
||||
def _build_action_group(self):
|
||||
self.action_group = gtk.ActionGroup(self.title)
|
||||
if len(self.action_list) > 0:
|
||||
self.action_group.add_actions(self.action_list)
|
||||
if len(self.action_toggle_list) > 0:
|
||||
self.action_group.add_toggle_actions(self.action_toggle_list)
|
||||
|
||||
def add_action(self, name, stock_icon, label, accel=None, tip=None, callback=None):
|
||||
self.action_list.append((name,stock_icon,label,accel,tip,callback))
|
||||
|
||||
def add_toggle_action(self, name, stock_icon, label, accel=None, tip=None, callback=None):
|
||||
self.action_toggle_list.append((name,stock_icon,label,accel,tip,callback))
|
||||
|
||||
def get_actions(self):
|
||||
if not self.action_group:
|
||||
self.define_actions()
|
||||
self._build_action_group()
|
||||
return self.action_group
|
@ -78,6 +78,7 @@ class PeopleView:
|
||||
self.parent = parent
|
||||
|
||||
self.parent.connect('database-changed',self.change_db)
|
||||
self.parent.connect('active-changed',self.change_db)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Entire Database"))
|
||||
@ -243,15 +244,15 @@ class PeopleView:
|
||||
self.apply_filter()
|
||||
self.goto_active_person()
|
||||
|
||||
def goto_active_person(self):
|
||||
if not self.parent.active_person or self.inactive:
|
||||
def goto_active_person(self,obj=None):
|
||||
if not self.state.active or self.inactive:
|
||||
return
|
||||
self.inactive = True
|
||||
p = self.parent.active_person
|
||||
p = self.state.active
|
||||
try:
|
||||
path = self.person_model.on_get_path(p.get_handle())
|
||||
group_name = p.get_primary_name().get_group_name()
|
||||
top_name = self.parent.db.get_name_group_mapping(group_name)
|
||||
top_name = self.state.db.get_name_group_mapping(group_name)
|
||||
top_path = self.person_model.on_get_path(top_name)
|
||||
self.person_tree.expand_row(top_path,0)
|
||||
|
||||
@ -264,7 +265,7 @@ class PeopleView:
|
||||
except KeyError:
|
||||
self.person_selection.unselect_all()
|
||||
print "Person not currently available due to filter"
|
||||
self.parent.active_person = p
|
||||
self.state.active = p
|
||||
self.inactive = False
|
||||
|
||||
def alpha_event(self,*obj):
|
||||
|
783
src/PersonView.py
Normal file
783
src/PersonView.py
Normal file
@ -0,0 +1,783 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2003 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# standard python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gtk
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
from gtk.gdk import ACTION_COPY, BUTTON1_MASK
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import PeopleModel
|
||||
import PageView
|
||||
import GenericFilter
|
||||
import EditPerson
|
||||
import NameDisplay
|
||||
import Utils
|
||||
import QuestionDialog
|
||||
|
||||
from DdTargets import DdTargets
|
||||
|
||||
column_names = [
|
||||
_('Name'),
|
||||
_('ID') ,
|
||||
_('Gender'),
|
||||
_('Birth Date'),
|
||||
_('Birth Place'),
|
||||
_('Death Date'),
|
||||
_('Death Place'),
|
||||
_('Spouse'),
|
||||
_('Last Change'),
|
||||
_('Cause of Death'),
|
||||
]
|
||||
|
||||
|
||||
class PersonView(PageView.PageView):
|
||||
|
||||
def __init__(self,state):
|
||||
PageView.PageView.__init__(self,'Person View',state)
|
||||
self.inactive = False
|
||||
state.connect('database-changed',self.change_db)
|
||||
state.connect('active-changed',self.goto_active_person)
|
||||
|
||||
def setup_filter(self):
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Entire Database"))
|
||||
all.add_rule(GenericFilter.Everyone([]))
|
||||
|
||||
self.DataFilter = None
|
||||
self.init_filters()
|
||||
|
||||
def define_actions(self):
|
||||
self.add_action('Add', gtk.STOCK_ADD, "_Add", callback=self.add)
|
||||
self.add_action('Edit', gtk.STOCK_EDIT, "_Edit", callback=self.edit)
|
||||
self.add_action('Remove', gtk.STOCK_REMOVE, "_Remove", callback=self.remove)
|
||||
self.add_action('Forward',gtk.STOCK_GO_FORWARD,"_Forward", callback=self.fwd_clicked)
|
||||
self.add_action('Back', gtk.STOCK_GO_BACK, "_Back", callback=self.back_clicked)
|
||||
self.add_action('HomePerson', gtk.STOCK_HOME, "_Home", callback=self.home)
|
||||
self.add_toggle_action('Filter', None, '_Filter', callback=self.filter_toggle)
|
||||
|
||||
def get_stock(self):
|
||||
return 'gramps-person'
|
||||
|
||||
def build_tree(self):
|
||||
self.person_model = PeopleModel.PeopleModel(
|
||||
self.state.db, self.DataFilter, self.filter_invert.get_active())
|
||||
self.person_tree.set_model(self.person_model)
|
||||
|
||||
def build_widget(self):
|
||||
self.vbox = gtk.VBox()
|
||||
self.vbox.set_border_width(4)
|
||||
self.vbox.set_spacing(4)
|
||||
|
||||
self.filterbar = gtk.HBox()
|
||||
self.filterbar.set_spacing(4)
|
||||
self.filter_text = gtk.Entry()
|
||||
self.filter_label = gtk.Label('Label:')
|
||||
self.filter_list = gtk.ComboBox()
|
||||
self.filter_invert = gtk.CheckButton('Invert')
|
||||
self.filter_button = gtk.Button('Apply')
|
||||
self.filterbar.pack_start(self.filter_list,False)
|
||||
self.filterbar.pack_start(self.filter_label,False)
|
||||
self.filterbar.pack_start(self.filter_text,True)
|
||||
self.filterbar.pack_start(self.filter_invert,False)
|
||||
self.filterbar.pack_end(self.filter_button,False)
|
||||
|
||||
self.filter_text.hide()
|
||||
self.filter_text.set_sensitive(0)
|
||||
self.filter_label.hide()
|
||||
|
||||
self.person_tree = gtk.TreeView()
|
||||
self.person_tree.set_rules_hint(True)
|
||||
self.person_tree.set_headers_visible(True)
|
||||
|
||||
scrollwindow = gtk.ScrolledWindow()
|
||||
scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
scrollwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN)
|
||||
scrollwindow.add(self.person_tree)
|
||||
|
||||
self.vbox.pack_start(self.filterbar,False)
|
||||
self.vbox.pack_start(scrollwindow,True)
|
||||
|
||||
# temporary hack
|
||||
|
||||
self.renderer = gtk.CellRendererText()
|
||||
self.inactive = False
|
||||
|
||||
self.columns = []
|
||||
self.build_columns()
|
||||
self.person_tree.connect('row_activated', self.alpha_event)
|
||||
self.person_tree.connect('button-press-event',
|
||||
self.on_plist_button_press)
|
||||
self.person_tree.connect('drag_data_get', self.person_drag_data_get)
|
||||
|
||||
|
||||
self.person_selection = self.person_tree.get_selection()
|
||||
self.person_selection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||
self.person_selection.connect('changed',self.row_changed)
|
||||
|
||||
self.vbox.set_focus_chain([self.person_tree,self.filter_list, self.filter_text,
|
||||
self.filter_invert, self.filter_button])
|
||||
|
||||
a = gtk.ListStore(str,str)
|
||||
self.person_tree.set_model(a)
|
||||
|
||||
self.setup_filter()
|
||||
|
||||
return self.vbox
|
||||
|
||||
def ui_definition(self):
|
||||
return '''<ui>
|
||||
<menubar name="MenuBar">
|
||||
<menu action="ViewMenu">
|
||||
<menuitem action="Filter"/>
|
||||
</menu>
|
||||
<menu action="GoMenu">
|
||||
<placeholder name="CommonGo">
|
||||
<menuitem action="Back"/>
|
||||
<menuitem action="Forward"/>
|
||||
<separator/>
|
||||
<menuitem action="HomePerson"/>
|
||||
<separator/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
<menu action="EditMenu">
|
||||
<placeholder name="CommonEdit">
|
||||
<menuitem action="Add"/>
|
||||
<menuitem action="Edit"/>
|
||||
<menuitem action="Remove"/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
</menubar>
|
||||
<toolbar name="ToolBar">
|
||||
<placeholder name="CommonNavigation">
|
||||
<toolitem action="Back"/>
|
||||
<toolitem action="Forward"/>
|
||||
<toolitem action="HomePerson"/>
|
||||
</placeholder>
|
||||
<placeholder name="CommonEdit">
|
||||
<toolitem action="Add"/>
|
||||
<toolitem action="Edit"/>
|
||||
<toolitem action="Remove"/>
|
||||
</placeholder>
|
||||
</toolbar>
|
||||
</ui>'''
|
||||
|
||||
def filter_toggle(self,obj):
|
||||
if obj.get_active():
|
||||
self.filterbar.show()
|
||||
else:
|
||||
self.filterbar.hide()
|
||||
|
||||
def add(self,obj):
|
||||
person = RelLib.Person()
|
||||
EditPerson.EditPerson(self, person, self.state.db,
|
||||
None)
|
||||
|
||||
def edit(self,obj):
|
||||
EditPerson.EditPerson(self, self.state.active, self.state.db,
|
||||
None)
|
||||
|
||||
def remove(self,obj):
|
||||
mlist = self.get_selected_objects()
|
||||
if len(mlist) == 0:
|
||||
return
|
||||
|
||||
for sel in mlist:
|
||||
p = self.state.db.get_person_from_handle(sel)
|
||||
self.active_person = p
|
||||
name = NameDisplay.displayer.display(p)
|
||||
|
||||
msg = _('Deleting the person will remove the person '
|
||||
'from the database.')
|
||||
msg = "%s %s" % (msg,Utils.data_recover_msg)
|
||||
QuestionDialog.QuestionDialog(_('Delete %s?') % name,msg,
|
||||
_('_Delete Person'),
|
||||
self.delete_person_response)
|
||||
|
||||
def delete_person_response(self):
|
||||
#self.disable_interface()
|
||||
trans = self.state.db.transaction_begin()
|
||||
|
||||
n = NameDisplay.displayer.display(self.active_person)
|
||||
|
||||
if self.state.db.get_default_person() == self.active_person:
|
||||
self.state.db.set_default_person_handle(None)
|
||||
|
||||
for family_handle in self.active_person.get_family_handle_list():
|
||||
if not family_handle:
|
||||
continue
|
||||
family = self.state.db.get_family_from_handle(family_handle)
|
||||
family_to_remove = False
|
||||
if self.active_person.get_handle() == family.get_father_handle():
|
||||
if family.get_mother_handle():
|
||||
family.set_father_handle(None)
|
||||
else:
|
||||
family_to_remove = True
|
||||
else:
|
||||
if family.get_father_handle():
|
||||
family.set_mother_handle(None)
|
||||
else:
|
||||
family_to_remove = True
|
||||
if family_to_remove:
|
||||
for child_handle in family.get_child_handle_list():
|
||||
child = self.state.db.get_person_from_handle(child_handle)
|
||||
child.remove_parent_family_handle(family_handle)
|
||||
self.db.commit_person(child,trans)
|
||||
self.state.db.remove_family(family_handle,trans)
|
||||
else:
|
||||
self.state.db.commit_family(family,trans)
|
||||
|
||||
for (family_handle,mrel,frel) in self.active_person.get_parent_family_handle_list():
|
||||
if family_handle:
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
family.remove_child_handle(self.active_person.get_handle())
|
||||
self.db.commit_family(family,trans)
|
||||
|
||||
handle = self.active_person.get_handle()
|
||||
|
||||
person = self.active_person
|
||||
self.remove_from_person_list(person)
|
||||
self.people_view.remove_from_history(handle)
|
||||
self.state.db.remove_person(handle, trans)
|
||||
|
||||
if self.state.phistory.index >= 0:
|
||||
self.active_person = self.state.db.get_person_from_handle(self.state.phistory.history[self.index])
|
||||
else:
|
||||
self.state.change_active_person(None)
|
||||
self.state.db.transaction_commit(trans,_("Delete Person (%s)") % n)
|
||||
#self.redraw_histmenu()
|
||||
#self.enable_interface()
|
||||
|
||||
def build_columns(self):
|
||||
for column in self.columns:
|
||||
self.person_tree.remove_column(column)
|
||||
|
||||
column = gtk.TreeViewColumn(_('Name'), self.renderer,text=0)
|
||||
column.set_resizable(True)
|
||||
#column.set_clickable(True)
|
||||
#column.connect('clicked',self.sort_clicked)
|
||||
column.set_min_width(225)
|
||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
self.person_tree.append_column(column)
|
||||
self.columns = [column]
|
||||
|
||||
for pair in self.state.db.get_person_column_order():
|
||||
if not pair[0]:
|
||||
continue
|
||||
name = column_names[pair[1]]
|
||||
column = gtk.TreeViewColumn(name, self.renderer, markup=pair[1])
|
||||
column.set_resizable(True)
|
||||
column.set_min_width(60)
|
||||
column.set_sizing(gtk.TREE_VIEW_COLUMN_GROW_ONLY)
|
||||
self.columns.append(column)
|
||||
self.person_tree.append_column(column)
|
||||
|
||||
def row_changed(self,obj):
|
||||
"""Called with a row is changed. Check the selected objects from
|
||||
the person_tree to get the IDs of the selected objects. Set the
|
||||
active person to the first person in the list. If no one is
|
||||
selected, set the active person to None"""
|
||||
|
||||
selected_ids = self.get_selected_objects()
|
||||
try:
|
||||
person = self.state.db.get_person_from_handle(selected_ids[0])
|
||||
self.state.change_active_person(person)
|
||||
self.goto_active_person()
|
||||
except:
|
||||
self.state.change_active_person(None)
|
||||
|
||||
if len(selected_ids) == 1:
|
||||
self.person_tree.drag_source_set(BUTTON1_MASK,
|
||||
[DdTargets.PERSON_LINK.target()],
|
||||
ACTION_COPY)
|
||||
elif len(selected_ids) > 1:
|
||||
self.person_tree.drag_source_set(BUTTON1_MASK,
|
||||
[DdTargets.PERSON_LINK_LIST.target()],
|
||||
ACTION_COPY)
|
||||
self.state.modify_statusbar()
|
||||
|
||||
def alpha_event(self,*obj):
|
||||
pass
|
||||
#self.parent.load_person(self.parent.active_person)
|
||||
|
||||
def on_plist_button_press(self,obj,event):
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
|
||||
self.build_people_context_menu(event)
|
||||
|
||||
def person_drag_data_get(self, widget, context, sel_data, info, time):
|
||||
selected_ids = self.get_selected_objects()
|
||||
|
||||
if len(selected_ids) == 1:
|
||||
sel_data.set(sel_data.target, 8, selected_ids[0])
|
||||
elif len(selected_ids) > 1:
|
||||
sel_data.set(DdTargets.PERSON_LINK_LIST.drag_type,8,
|
||||
pickle.dumps(selected_ids))
|
||||
|
||||
def apply_filter_clicked(self):
|
||||
index = self.filter_list.get_active()
|
||||
self.DataFilter = self.filter_model.get_filter(index)
|
||||
if self.DataFilter.need_param:
|
||||
qual = unicode(self.filter_text.get_text())
|
||||
self.DataFilter.set_parameter(qual)
|
||||
self.apply_filter()
|
||||
self.goto_active_person()
|
||||
|
||||
def goto_active_person(self,obj=None):
|
||||
if not self.state.active or self.inactive:
|
||||
return
|
||||
self.inactive = True
|
||||
p = self.state.active
|
||||
try:
|
||||
path = self.person_model.on_get_path(p.get_handle())
|
||||
group_name = p.get_primary_name().get_group_name()
|
||||
top_name = self.state.db.get_name_group_mapping(group_name)
|
||||
top_path = self.person_model.on_get_path(top_name)
|
||||
self.person_tree.expand_row(top_path,0)
|
||||
|
||||
current = self.person_model.on_get_iter(path)
|
||||
selected = self.person_selection.path_is_selected(path)
|
||||
if current != p.get_handle() or not selected:
|
||||
self.person_selection.unselect_all()
|
||||
self.person_selection.select_path(path)
|
||||
self.person_tree.scroll_to_cell(path,None,1,0.5,0)
|
||||
except KeyError:
|
||||
self.person_selection.unselect_all()
|
||||
print "Person not currently available due to filter"
|
||||
self.state.active = p
|
||||
self.inactive = False
|
||||
|
||||
def redisplay_person_list(self):
|
||||
self.build_tree()
|
||||
|
||||
def person_added(self,handle_list):
|
||||
for node in handle_list:
|
||||
person = self.state.db.get_person_from_handle(node)
|
||||
top = person.get_primary_name().get_group_name()
|
||||
self.person_model.rebuild_data(self.DataFilter)
|
||||
if not self.person_model.is_visable(node):
|
||||
continue
|
||||
if (not self.person_model.sname_sub.has_key(top) or
|
||||
len(self.person_model.sname_sub[top]) == 1):
|
||||
path = self.person_model.on_get_path(top)
|
||||
pnode = self.person_model.get_iter(path)
|
||||
self.person_model.row_inserted(path,pnode)
|
||||
path = self.person_model.on_get_path(node)
|
||||
pnode = self.person_model.get_iter(path)
|
||||
self.person_model.row_inserted(path,pnode)
|
||||
|
||||
def person_removed(self,handle_list):
|
||||
for node in handle_list:
|
||||
person = self.state.db.get_person_from_handle(node)
|
||||
if not self.person_model.is_visable(node):
|
||||
continue
|
||||
top = person.get_primary_name().get_group_name()
|
||||
mylist = self.person_model.sname_sub.get(top,[])
|
||||
if mylist:
|
||||
try:
|
||||
path = self.person_model.on_get_path(node)
|
||||
self.person_model.row_deleted(path)
|
||||
if len(mylist) == 1:
|
||||
path = self.person_model.on_get_path(top)
|
||||
self.person_model.row_deleted(path)
|
||||
except KeyError:
|
||||
pass
|
||||
self.person_model.rebuild_data(self.DataFilter,skip=node)
|
||||
|
||||
def person_updated(self,handle_list):
|
||||
for node in handle_list:
|
||||
person = self.state.db.get_person_from_handle(node)
|
||||
try:
|
||||
oldpath = self.person_model.iter2path[node]
|
||||
except:
|
||||
return
|
||||
pathval = self.person_model.on_get_path(node)
|
||||
pnode = self.person_model.get_iter(pathval)
|
||||
|
||||
# calculate the new data
|
||||
|
||||
if person.primary_name.group_as:
|
||||
surname = person.primary_name.group_as
|
||||
else:
|
||||
surname = self.state.db.get_name_group_mapping(person.primary_name.surname)
|
||||
|
||||
|
||||
if oldpath[0] == surname:
|
||||
self.person_model.build_sub_entry(surname)
|
||||
else:
|
||||
self.person_model.calculate_data(self.DataFilter)
|
||||
|
||||
# find the path of the person in the new data build
|
||||
newpath = self.person_model.temp_iter2path[node]
|
||||
|
||||
# if paths same, just issue row changed signal
|
||||
|
||||
if oldpath == newpath:
|
||||
self.person_model.row_changed(pathval,pnode)
|
||||
else:
|
||||
# paths different, get the new surname list
|
||||
|
||||
mylist = self.person_model.temp_sname_sub.get(oldpath[0],[])
|
||||
path = self.person_model.on_get_path(node)
|
||||
|
||||
# delete original
|
||||
self.person_model.row_deleted(pathval)
|
||||
|
||||
# delete top node of original if necessar
|
||||
if len(mylist)==0:
|
||||
self.person_model.row_deleted(pathval[0])
|
||||
|
||||
# determine if we need to insert a new top node',
|
||||
insert = not self.person_model.sname_sub.has_key(newpath[0])
|
||||
|
||||
# assign new data
|
||||
self.person_model.assign_data()
|
||||
|
||||
# insert new row if needed
|
||||
if insert:
|
||||
path = self.person_model.on_get_path(newpath[0])
|
||||
pnode = self.person_model.get_iter(path)
|
||||
self.person_model.row_inserted(path,pnode)
|
||||
|
||||
# insert new person
|
||||
path = self.person_model.on_get_path(node)
|
||||
pnode = self.person_model.get_iter(path)
|
||||
self.person_model.row_inserted(path,pnode)
|
||||
|
||||
self.goto_active_person()
|
||||
|
||||
def change_db(self,db):
|
||||
self.build_columns()
|
||||
db.connect('person-add', self.person_added)
|
||||
db.connect('person-update', self.person_updated)
|
||||
db.connect('person-delete', self.person_removed)
|
||||
db.connect('person-rebuild', self.redisplay_person_list)
|
||||
self.apply_filter()
|
||||
|
||||
def init_filters(self):
|
||||
|
||||
cell = gtk.CellRendererText()
|
||||
self.filter_list.clear()
|
||||
self.filter_list.pack_start(cell,True)
|
||||
self.filter_list.add_attribute(cell,'text',0)
|
||||
|
||||
filter_list = []
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Entire Database"))
|
||||
all.add_rule(GenericFilter.Everyone([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Females"))
|
||||
all.add_rule(GenericFilter.IsFemale([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Males"))
|
||||
all.add_rule(GenericFilter.IsMale([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with unknown gender"))
|
||||
all.add_rule(GenericFilter.HasUnknownGender([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Disconnected individuals"))
|
||||
all.add_rule(GenericFilter.Disconnected([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People with names containing..."))
|
||||
all.add_rule(GenericFilter.SearchName([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Adopted people"))
|
||||
all.add_rule(GenericFilter.HaveAltFamilies([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with images"))
|
||||
all.add_rule(GenericFilter.HavePhotos([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with incomplete names"))
|
||||
all.add_rule(GenericFilter.IncompleteNames([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with children"))
|
||||
all.add_rule(GenericFilter.HaveChildren([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with no marriage records"))
|
||||
all.add_rule(GenericFilter.NeverMarried([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with multiple marriage records"))
|
||||
all.add_rule(GenericFilter.MultipleMarriages([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People without a known birth date"))
|
||||
all.add_rule(GenericFilter.NoBirthdate([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with incomplete events"))
|
||||
all.add_rule(GenericFilter.PersonWithIncompleteEvent([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Families with incomplete events"))
|
||||
all.add_rule(GenericFilter.FamilyWithIncompleteEvent([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People probably alive"))
|
||||
all.add_rule(GenericFilter.ProbablyAlive([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People marked private"))
|
||||
all.add_rule(GenericFilter.PeoplePrivate([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Witnesses"))
|
||||
all.add_rule(GenericFilter.IsWitness([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People with records containing..."))
|
||||
all.add_rule(GenericFilter.HasTextMatchingSubstringOf([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People with records matching regular expression..."))
|
||||
all.add_rule(GenericFilter.HasTextMatchingRegexpOf([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with notes"))
|
||||
all.add_rule(GenericFilter.HasNote([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People with notes containing..."))
|
||||
all.add_rule(GenericFilter.HasNoteMatchingSubstringOf([]))
|
||||
filter_list.append(all)
|
||||
|
||||
self.filter_model = GenericFilter.FilterStore(filter_list)
|
||||
self.filter_list.set_model(self.filter_model)
|
||||
self.filter_list.set_active(self.filter_model.default_index())
|
||||
self.filter_list.connect('changed',self.on_filter_name_changed)
|
||||
self.filter_text.set_sensitive(0)
|
||||
|
||||
def on_filter_name_changed(self,obj):
|
||||
index = self.filter_list.get_active()
|
||||
mime_filter = self.filter_model.get_filter(index)
|
||||
qual = mime_filter.need_param
|
||||
if qual:
|
||||
self.filter_text.show()
|
||||
self.filter_text.set_sensitive(1)
|
||||
self.filter_label.show()
|
||||
self.filter_label.set_text(mime_filter.get_rules()[0].labels[0])
|
||||
else:
|
||||
self.filter_text.hide()
|
||||
self.filter_text.set_sensitive(0)
|
||||
self.filter_label.hide()
|
||||
|
||||
def apply_filter(self,current_model=None):
|
||||
#self.parent.status_text(_('Updating display...'))
|
||||
self.build_tree()
|
||||
#self.parent.modify_statusbar()
|
||||
|
||||
def get_selected_objects(self):
|
||||
(mode,paths) = self.person_selection.get_selected_rows()
|
||||
mlist = []
|
||||
for path in paths:
|
||||
node = self.person_model.on_get_iter(path)
|
||||
mlist.append(self.person_model.on_get_value(node, PeopleModel.COLUMN_INT_ID))
|
||||
return mlist
|
||||
|
||||
def remove_from_person_list(self,person):
|
||||
"""Remove the selected person from the list. A person object is
|
||||
expected, not an ID"""
|
||||
path = self.person_model.on_get_path(person.get_handle())
|
||||
(col,row) = path
|
||||
if row > 0:
|
||||
self.person_selection.select_path((col,row-1))
|
||||
elif row == 0 and self.person_model.on_get_iter(path):
|
||||
self.person_selection.select_path(path)
|
||||
|
||||
def build_backhistmenu(self,event):
|
||||
"""Builds and displays the menu with the back portion of the history"""
|
||||
hobj = self.state.phistory
|
||||
if hobj.index > 0:
|
||||
backhistmenu = gtk.Menu()
|
||||
backhistmenu.set_title(_('Back Menu'))
|
||||
pids = hobj.history[:hobj.index]
|
||||
pids.reverse()
|
||||
num = 1
|
||||
for pid in pids:
|
||||
if num <= 10:
|
||||
f,r = divmod(num,10)
|
||||
hotkey = "_%d" % r
|
||||
elif num <= 20:
|
||||
hotkey = "_%s" % chr(ord('a')+num-11)
|
||||
elif num >= 21:
|
||||
break
|
||||
person = self.state.db.get_person_from_handle(pid)
|
||||
item = gtk.MenuItem("%s. %s [%s]" %
|
||||
(hotkey,
|
||||
NameDisplay.displayer.display(person),
|
||||
person.get_gramps_id()))
|
||||
item.connect("activate",self.back_clicked,num)
|
||||
item.show()
|
||||
backhistmenu.append(item)
|
||||
num = num + 1
|
||||
backhistmenu.popup(None,None,None,event.button,event.time)
|
||||
|
||||
def back_pressed(self,obj,event):
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
|
||||
self.build_backhistmenu(event)
|
||||
|
||||
def build_fwdhistmenu(self,event):
|
||||
"""Builds and displays the menu with the forward portion of the history"""
|
||||
if self.hindex < len(self.history)-1:
|
||||
fwdhistmenu = gtk.Menu()
|
||||
fwdhistmenu.set_title(_('Forward Menu'))
|
||||
pids = self.history[self.hindex+1:]
|
||||
num = 1
|
||||
for pid in pids:
|
||||
if num <= 10:
|
||||
f,r = divmod(num,10)
|
||||
hotkey = "_%d" % r
|
||||
elif num <= 20:
|
||||
hotkey = "_%s" % chr(ord('a')+num-11)
|
||||
elif num >= 21:
|
||||
break
|
||||
person = self.db.get_person_from_handle(pid)
|
||||
item = gtk.MenuItem("%s. %s [%s]" %
|
||||
(hotkey,
|
||||
NameDisplay.displayer.display(person),
|
||||
person.get_gramps_id()))
|
||||
item.connect("activate",self.fwd_clicked,num)
|
||||
item.show()
|
||||
fwdhistmenu.append(item)
|
||||
num = num + 1
|
||||
fwdhistmenu.popup(None,None,None,event.button,event.time)
|
||||
|
||||
def fwd_pressed(self,obj,event):
|
||||
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
|
||||
self.build_fwdhistmenu(event)
|
||||
|
||||
def fwd_clicked(self,obj,step=1):
|
||||
print "fwd clicked"
|
||||
hobj = self.state.phistory
|
||||
hobj.lock = True
|
||||
print hobj.history
|
||||
if hobj.index+1 < len(hobj.history):
|
||||
try:
|
||||
hobj.index += step
|
||||
handle = str(hobj.history[hobj.index])
|
||||
self.state.active = self.state.db.get_person_from_handle(handle)
|
||||
self.state.modify_statusbar()
|
||||
self.state.change_active_handle(handle)
|
||||
hobj.mhistory.append(self.history[hobj.index])
|
||||
#self.redraw_histmenu()
|
||||
self.set_buttons(True)
|
||||
if hobj.index == len(hobj.history)-1:
|
||||
self.fwdbtn.set_sensitive(False)
|
||||
self.forward.set_sensitive(False)
|
||||
else:
|
||||
self.fwdbtn.set_sensitive(True)
|
||||
self.forward.set_sensitive(True)
|
||||
self.backbtn.set_sensitive(True)
|
||||
self.back.set_sensitive(True)
|
||||
except:
|
||||
self.clear_history()
|
||||
else:
|
||||
self.fwdbtn.set_sensitive(False)
|
||||
self.forward.set_sensitive(False)
|
||||
self.backbtn.set_sensitive(True)
|
||||
self.back.set_sensitive(True)
|
||||
self.goto_active_person()
|
||||
hobj.lock = False
|
||||
|
||||
def back_clicked(self,obj,step=1):
|
||||
hobj = self.state.phistory
|
||||
hobj.lock = True
|
||||
if hobj.index > 0:
|
||||
try:
|
||||
hobj.index -= step
|
||||
handle = str(hobj.history[hobj.hindex])
|
||||
self.active = self.db.get_person_from_handle(handle)
|
||||
self.modify_statusbar()
|
||||
self.change_active_handle(handle)
|
||||
hobj.mhistory.append(hobj.history[hobj.index])
|
||||
self.redraw_histmenu()
|
||||
self.set_buttons(1)
|
||||
if hobj.index == 0:
|
||||
self.backbtn.set_sensitive(False)
|
||||
self.back.set_sensitive(False)
|
||||
else:
|
||||
self.backbtn.set_sensitive(True)
|
||||
self.back.set_sensitive(True)
|
||||
self.fwdbtn.set_sensitive(True)
|
||||
self.forward.set_sensitive(True)
|
||||
except:
|
||||
hobj.clear_history()
|
||||
else:
|
||||
self.backbtn.set_sensitive(False)
|
||||
self.back.set_sensitive(False)
|
||||
self.fwdbtn.set_sensitive(True)
|
||||
self.forward.set_sensitive(True)
|
||||
self.goto_active_person()
|
||||
hobj.lock = False
|
||||
|
||||
def home(self,obj):
|
||||
defperson = self.state.db.get_default_person()
|
||||
if defperson:
|
||||
self.state.change_active_person(defperson)
|
||||
self.goto_active_person()
|
@ -1264,9 +1264,9 @@ class GrampsParser:
|
||||
def stop_date(self,tag):
|
||||
if tag:
|
||||
if self.address:
|
||||
self.address.set_date(tag)
|
||||
DateHandler.set_date(self.address,tag)
|
||||
else:
|
||||
self.event.set_date(tag)
|
||||
DateHandler.set_date(self.event,tag)
|
||||
|
||||
def stop_first(self,tag):
|
||||
self.name.set_first_name(tag)
|
||||
|
677
src/ViewManager.py
Normal file
677
src/ViewManager.py
Normal file
@ -0,0 +1,677 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2005 Donald N. Allingham
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
from gettext import gettext as _
|
||||
from bsddb import db
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GNOME modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
try:
|
||||
from gnomevfs import get_mime_type
|
||||
except:
|
||||
from gnome.vfs import get_mime_type
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import DbState
|
||||
import DbPrompter
|
||||
import const
|
||||
import PluginMgr
|
||||
import GrampsKeys
|
||||
import GrampsDbBase
|
||||
import GrampsBSDDB
|
||||
import GrampsGEDDB
|
||||
import GrampsXMLDB
|
||||
import GrampsCfg
|
||||
import Errors
|
||||
import DisplayTrace
|
||||
import Utils
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
_KNOWN_FORMATS = {
|
||||
const.app_gramps : _('GRAMPS (grdb)'),
|
||||
const.app_gramps_xml : _('GRAMPS XML'),
|
||||
const.app_gedcom : _('GEDCOM'),
|
||||
}
|
||||
|
||||
uidefault = '''<ui>
|
||||
<menubar name="MenuBar">
|
||||
<menu action="FileMenu">
|
||||
<menuitem action="New"/>
|
||||
<menuitem action="Open"/>
|
||||
<menuitem action="OpenRecent"/>
|
||||
<separator/>
|
||||
<menuitem action="Import"/>
|
||||
<menuitem action="SaveAs"/>
|
||||
<menuitem action="Export"/>
|
||||
<separator/>
|
||||
<menuitem action="Abandon"/>
|
||||
<menuitem action="Quit"/>
|
||||
</menu>
|
||||
<menu action="EditMenu">
|
||||
<menuitem action="Undo"/>
|
||||
<separator/>
|
||||
<placeholder name="CommonEdit"/>
|
||||
<menuitem action="CmpMerge"/>
|
||||
<menuitem action="FastMerge"/>
|
||||
<separator/>
|
||||
<menuitem action="Preferences"/>
|
||||
<menuitem action="ColumnEdit"/>
|
||||
</menu>
|
||||
<menu action="ViewMenu">
|
||||
<menuitem action="Sidebar"/>
|
||||
<menuitem action="Toolbar"/>
|
||||
</menu>
|
||||
<menu action="GoMenu">
|
||||
<placeholder name="CommonGo"/>
|
||||
</menu>
|
||||
<menu action="BookMenu">
|
||||
<menuitem action="AddBook"/>
|
||||
<menuitem action="EditBook"/>
|
||||
<menuitem action="GoToBook"/>
|
||||
</menu>
|
||||
<menu action="ReportsMenu">
|
||||
</menu>
|
||||
<menu action="ToolsMenu">
|
||||
</menu>
|
||||
<menu action="WindowsMenu">
|
||||
</menu>
|
||||
<menu action="HelpMenu">
|
||||
<menuitem action="About"/>
|
||||
</menu>
|
||||
</menubar>
|
||||
<toolbar name="ToolBar">
|
||||
<toolitem action="New"/>
|
||||
<toolitem action="Open"/>
|
||||
<separator/>
|
||||
<placeholder name="CommonNavigation"/>
|
||||
<separator/>
|
||||
<toolitem action="ScratchPad"/>
|
||||
<toolitem action="Reports"/>
|
||||
<toolitem action="Tools"/>
|
||||
<separator/>
|
||||
<placeholder name="CommonEdit"/>
|
||||
</toolbar>
|
||||
</ui>
|
||||
'''
|
||||
|
||||
class ViewManager:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.active_page = None
|
||||
self.views = []
|
||||
self.window = gtk.Window()
|
||||
self.window.connect('destroy', lambda w: gtk.main_quit())
|
||||
self.window.set_size_request(775,500)
|
||||
|
||||
self.statusbar = gtk.Statusbar()
|
||||
self.state = DbState.DbState(self.window,self.statusbar)
|
||||
|
||||
self.RelClass = PluginMgr.relationship_class
|
||||
|
||||
vbox = gtk.VBox()
|
||||
self.window.add(vbox)
|
||||
hbox = gtk.HBox()
|
||||
hbox.set_border_width(4)
|
||||
self.ebox = gtk.EventBox()
|
||||
self.bbox = gtk.VBox()
|
||||
self.ebox.add(self.bbox)
|
||||
hbox.pack_start(self.ebox,False)
|
||||
|
||||
self.notebook = gtk.Notebook()
|
||||
self.notebook.set_show_tabs(False)
|
||||
self.build_ui_manager()
|
||||
|
||||
hbox.pack_start(self.notebook,True)
|
||||
self.menubar = self.uimanager.get_widget('/MenuBar')
|
||||
self.toolbar = self.uimanager.get_widget('/ToolBar')
|
||||
vbox.pack_start(self.menubar, False)
|
||||
vbox.pack_start(self.toolbar, False)
|
||||
vbox.add(hbox)
|
||||
vbox.pack_end(self.statusbar,False)
|
||||
|
||||
self.notebook.connect('switch-page',self.change_page)
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def init_interface(self):
|
||||
self.create_pages()
|
||||
self.change_page(None,None,0)
|
||||
|
||||
def set_color(self,obj):
|
||||
style = obj.get_style().copy()
|
||||
new_color = style.bg[gtk.STATE_ACTIVE]
|
||||
style.bg[gtk.STATE_NORMAL] = new_color
|
||||
style.bg[gtk.STATE_PRELIGHT] = new_color
|
||||
style.bg[gtk.STATE_ACTIVE] = new_color
|
||||
style.bg[gtk.STATE_INSENSITIVE] = new_color
|
||||
style.bg[gtk.STATE_SELECTED] = new_color
|
||||
obj.set_style(style)
|
||||
|
||||
def build_ui_manager(self):
|
||||
self.merge_id = 0
|
||||
self.uimanager = gtk.UIManager()
|
||||
|
||||
accelgroup = self.uimanager.get_accel_group()
|
||||
self.window.add_accel_group(accelgroup)
|
||||
|
||||
self.actiongroup = gtk.ActionGroup('MainWindow')
|
||||
self.actiongroup.add_actions([
|
||||
# Name Stock Icon Label
|
||||
('FileMenu', None, '_File'),
|
||||
('New', gtk.STOCK_NEW, '_New', "<control>n", None, self.on_new_activate),
|
||||
('Open', gtk.STOCK_OPEN, '_Open', "<control>o", None, self.on_open_activate),
|
||||
('OpenRecent', gtk.STOCK_OPEN, 'Open _Recent'),
|
||||
('Import', gtk.STOCK_CONVERT, '_Import'),
|
||||
('SaveAs', gtk.STOCK_SAVE_AS, '_Save As'),
|
||||
('Export', gtk.STOCK_SAVE_AS, '_Export'),
|
||||
('Abandon', gtk.STOCK_REVERT_TO_SAVED, '_Abandon changes and quit'),
|
||||
('Quit', gtk.STOCK_QUIT, '_Quit', '<control>q', None, gtk.main_quit),
|
||||
('Undo', gtk.STOCK_UNDO, '_Undo', '<control>z' ),
|
||||
('Preferences',gtk.STOCK_PREFERENCES, '_Preferences'),
|
||||
('ColumnEdit', gtk.STOCK_PROPERTIES, '_Column Editor'),
|
||||
('CmpMerge', None, '_Compare and merge'),
|
||||
('FastMerge', None, '_Fast merge'),
|
||||
('ScratchPad', gtk.STOCK_PASTE, '_ScratchPad', None, None, self.on_scratchpad),
|
||||
('Reports', gtk.STOCK_DND_MULTIPLE, '_Reports'),
|
||||
('Tools', gtk.STOCK_EXECUTE, '_Tools'),
|
||||
('EditMenu', None, '_Edit'),
|
||||
('GoMenu', None, '_Go'),
|
||||
('ViewMenu', None, '_View'),
|
||||
('BookMenu', None, '_Bookmarks'),
|
||||
('AddBook', gtk.STOCK_INDEX, '_Add bookmark', '<control>d'),
|
||||
('EditBook', None, '_Edit bookmarks', '<control>b'),
|
||||
('GoToBook', gtk.STOCK_JUMP_TO, '_Go to bookmark'),
|
||||
('ReportsMenu',None, '_Reports'),
|
||||
('ToolsMenu', None, '_Tools'),
|
||||
('WindowsMenu',None, '_Windows'),
|
||||
('HelpMenu', None, '_Help'),
|
||||
('About', gtk.STOCK_ABOUT, '_About'),
|
||||
])
|
||||
|
||||
self.actiongroup.add_toggle_actions([
|
||||
('Sidebar', None, '_Sidebar', None, None, self.sidebar_toggle),
|
||||
('Toolbar', None, '_Toolbar', None, None, self.toolbar_toggle),
|
||||
])
|
||||
|
||||
merge_id = self.uimanager.add_ui_from_string(uidefault)
|
||||
self.uimanager.insert_action_group(self.actiongroup,1)
|
||||
|
||||
def sidebar_toggle(self,obj):
|
||||
if obj.get_active():
|
||||
self.ebox.show()
|
||||
self.notebook.set_show_tabs(False)
|
||||
else:
|
||||
self.ebox.hide()
|
||||
self.notebook.set_show_tabs(True)
|
||||
|
||||
def toolbar_toggle(self,obj):
|
||||
if obj.get_active():
|
||||
self.toolbar.show()
|
||||
else:
|
||||
self.toolbar.hide()
|
||||
|
||||
def register_view(self, view):
|
||||
self.views.append(view)
|
||||
|
||||
def create_pages(self):
|
||||
self.pages = []
|
||||
index = 0
|
||||
self.set_color(self.ebox)
|
||||
for page_def in self.views:
|
||||
page = page_def(self.state)
|
||||
|
||||
# create icon/label for notebook
|
||||
hbox = gtk.HBox()
|
||||
image = gtk.Image()
|
||||
image.set_from_stock(page.get_stock(),gtk.ICON_SIZE_MENU)
|
||||
hbox.pack_start(image,False)
|
||||
hbox.add(gtk.Label(page.get_title()))
|
||||
hbox.show_all()
|
||||
|
||||
# create notebook page and add to notebook
|
||||
page_display = page.get_display()
|
||||
page_display.show_all()
|
||||
self.notebook.append_page(page_display,hbox)
|
||||
self.pages.append(page)
|
||||
|
||||
# create the button add it to the sidebar
|
||||
button = gtk.Button(stock=page.get_stock(),label=page.get_title())
|
||||
button.set_border_width(4)
|
||||
button.set_relief(gtk.RELIEF_NONE)
|
||||
button.set_alignment(0,0.5)
|
||||
button.connect('clicked',lambda x,y : self.notebook.set_current_page(y),
|
||||
index)
|
||||
self.set_color(button)
|
||||
button.show()
|
||||
index += 1
|
||||
self.bbox.pack_start(button,False)
|
||||
|
||||
def change_page(self,obj,page,num):
|
||||
if self.merge_id:
|
||||
self.uimanager.remove_ui(self.merge_id)
|
||||
if self.active_page:
|
||||
self.uimanager.remove_action_group(self.active_page.get_actions())
|
||||
|
||||
if len(self.pages) > 0:
|
||||
self.active_page = self.pages[num]
|
||||
|
||||
self.uimanager.insert_action_group(self.active_page.get_actions(),1)
|
||||
self.merge_id = self.uimanager.add_ui_from_string(self.active_page.ui_definition())
|
||||
|
||||
def on_open_activate(self,obj):
|
||||
|
||||
choose = gtk.FileChooserDialog(_('GRAMPS: Open database'),
|
||||
self.state.window,
|
||||
gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
(gtk.STOCK_CANCEL,
|
||||
gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN,
|
||||
gtk.RESPONSE_OK))
|
||||
|
||||
# Always add automatic (macth all files) filter
|
||||
add_all_files_filter(choose)
|
||||
add_grdb_filter(choose)
|
||||
add_xml_filter(choose)
|
||||
add_gedcom_filter(choose)
|
||||
|
||||
format_list = [const.app_gramps,const.app_gramps_xml,const.app_gedcom]
|
||||
# Add more data type selections if opening existing db
|
||||
for (importData,mime_filter,mime_type,native_format,format_name) in PluginMgr.import_list:
|
||||
if not native_format:
|
||||
choose.add_filter(mime_filter)
|
||||
format_list.append(mime_type)
|
||||
_KNOWN_FORMATS[mime_type] = format_name
|
||||
|
||||
(box,type_selector) = format_maker(format_list)
|
||||
choose.set_extra_widget(box)
|
||||
|
||||
# Suggested folder: try last open file, last import, last export,
|
||||
# then home.
|
||||
default_dir = os.path.split(GrampsKeys.get_lastfile())[0] + os.path.sep
|
||||
if len(default_dir)<=1:
|
||||
default_dir = GrampsKeys.get_last_import_dir()
|
||||
if len(default_dir)<=1:
|
||||
default_dir = GrampsKeys.get_last_export_dir()
|
||||
if len(default_dir)<=1:
|
||||
default_dir = '~/'
|
||||
|
||||
choose.set_current_folder(default_dir)
|
||||
response = choose.run()
|
||||
if response == gtk.RESPONSE_OK:
|
||||
filename = choose.get_filename()
|
||||
if len(filename) == 0:
|
||||
return False
|
||||
filetype = type_selector.get_value()
|
||||
if filetype == 'auto':
|
||||
filetype = get_mime_type(filename)
|
||||
(the_path,the_file) = os.path.split(filename)
|
||||
choose.destroy()
|
||||
if filetype in [const.app_gramps,const.app_gramps_xml,
|
||||
const.app_gedcom]:
|
||||
|
||||
try:
|
||||
return self.open_native(filename,filetype)
|
||||
except db.DBInvalidArgError, msg:
|
||||
QuestionDialog.ErrorDialog(
|
||||
_("Could not open file: %s") % filename, msg[1])
|
||||
return False
|
||||
except:
|
||||
import DisplayTrace
|
||||
DisplayTrace.DisplayTrace()
|
||||
return False
|
||||
|
||||
# The above native formats did not work, so we need to
|
||||
# look up the importer for this format
|
||||
# and create an empty native database to import data in
|
||||
# for (importData,mime_filter,mime_type,native_format,format_name) in PluginMgr.import_list:
|
||||
# if filetype == mime_type or the_file == mime_type:
|
||||
# QuestionDialog.OkDialog(
|
||||
# _("Opening non-native format"),
|
||||
# _("New GRAMPS database has to be set up "
|
||||
# "when opening non-native formats. The "
|
||||
# "following dialog will let you select "
|
||||
# "the new database."),
|
||||
# self.state.window)
|
||||
# prompter = NewNativeDbPrompter(self.parent,self.parent_window)
|
||||
# if prompter.chooser():
|
||||
# importData(self.state.db,filename)
|
||||
# #self.parent.import_tool_callback()
|
||||
# return True
|
||||
# else:
|
||||
# return False
|
||||
QuestionDialog.ErrorDialog(
|
||||
_("Could not open file: %s") % filename,
|
||||
_('File type "%s" is unknown to GRAMPS.\n\nValid types are: GRAMPS database, GRAMPS XML, GRAMPS package, and GEDCOM.') % filetype)
|
||||
choose.destroy()
|
||||
return False
|
||||
|
||||
def on_new_activate(self,obj):
|
||||
|
||||
choose = gtk.FileChooserDialog(_('GRAMPS: Create GRAMPS database'),
|
||||
self.state.window,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
(gtk.STOCK_CANCEL,
|
||||
gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN,
|
||||
gtk.RESPONSE_OK))
|
||||
|
||||
# Always add automatic (macth all files) filter
|
||||
add_all_files_filter(choose)
|
||||
add_grdb_filter(choose)
|
||||
|
||||
# Suggested folder: try last open file, import, then last export,
|
||||
# then home.
|
||||
default_dir = os.path.split(GrampsKeys.get_lastfile())[0] + os.path.sep
|
||||
if len(default_dir)<=1:
|
||||
default_dir = GrampsKeys.get_last_import_dir()
|
||||
if len(default_dir)<=1:
|
||||
default_dir = GrampsKeys.get_last_export_dir()
|
||||
if len(default_dir)<=1:
|
||||
default_dir = '~/'
|
||||
|
||||
new_filename = Utils.get_new_filename('grdb',default_dir)
|
||||
|
||||
choose.set_current_folder(default_dir)
|
||||
choose.set_current_name(os.path.split(new_filename)[1])
|
||||
|
||||
while (True):
|
||||
response = choose.run()
|
||||
if response == gtk.RESPONSE_OK:
|
||||
filename = choose.get_filename()
|
||||
if filename == None:
|
||||
continue
|
||||
if os.path.splitext(filename)[1] != ".grdb":
|
||||
filename = filename + ".grdb"
|
||||
choose.destroy()
|
||||
try:
|
||||
self.state.db.close()
|
||||
except:
|
||||
pass
|
||||
self.state.db = GrampsBSDDB.GrampsBSDDB()
|
||||
self.read_file(filename)
|
||||
# Add the file to the recent items
|
||||
#RecentFiles.recent_files(filename,const.app_gramps)
|
||||
#self.parent.build_recent_menu()
|
||||
return True
|
||||
else:
|
||||
choose.destroy()
|
||||
return False
|
||||
choose.destroy()
|
||||
return False
|
||||
|
||||
def open_native(self,filename,filetype):
|
||||
"""
|
||||
Open native database and return the status.
|
||||
"""
|
||||
|
||||
(the_path,the_file) = os.path.split(filename)
|
||||
GrampsKeys.save_last_import_dir(the_path)
|
||||
|
||||
success = False
|
||||
if filetype == const.app_gramps:
|
||||
self.state.db = GrampsBSDDB.GrampsBSDDB()
|
||||
msgxml = gtk.glade.XML(const.gladeFile, "load_message","gramps")
|
||||
msg_top = msgxml.get_widget('load_message')
|
||||
msg_label = msgxml.get_widget('message')
|
||||
|
||||
def update_msg(msg):
|
||||
msg_label.set_text("<i>%s</i>" % msg)
|
||||
msg_label.set_use_markup(True)
|
||||
while gtk.events_pending():
|
||||
gtk.main_iteration()
|
||||
|
||||
success = self.read_file(filename,update_msg)
|
||||
msg_top.destroy()
|
||||
elif filetype == const.app_gramps_xml:
|
||||
self.state.db = GrampsXMLDB.GrampsXMLDB()
|
||||
success = self.read_file(filename)
|
||||
elif filetype == const.app_gedcom:
|
||||
self.state.db = GrampsGEDDB.GrampsGEDDB()
|
||||
success = self.read_file(filename)
|
||||
|
||||
#if success:
|
||||
# Add the file to the recent items
|
||||
#RecentFiles.recent_files(filename,filetype)
|
||||
#parent.build_recent_menu()
|
||||
|
||||
return success
|
||||
|
||||
def read_file(self,filename,callback=None):
|
||||
mode = "w"
|
||||
filename = os.path.normpath(os.path.abspath(filename))
|
||||
|
||||
if os.path.isdir(filename):
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('The selected file is a directory, not '
|
||||
'a file.\nA GRAMPS database must be a file.'))
|
||||
return 0
|
||||
elif os.path.exists(filename):
|
||||
if not os.access(filename,os.R_OK):
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('You do not have read access to the selected '
|
||||
'file.'))
|
||||
return 0
|
||||
elif not os.access(filename,os.W_OK):
|
||||
mode = "r"
|
||||
WarningDialog(_('Read only database'),
|
||||
_('You do not have write access to the selected '
|
||||
'file.'))
|
||||
|
||||
try:
|
||||
if self.load_database(filename,callback,mode=mode) == 1:
|
||||
if filename[-1] == '/':
|
||||
filename = filename[:-1]
|
||||
name = os.path.basename(filename)
|
||||
if self.state.db.readonly:
|
||||
self.state.window.set_title("%s (%s) - GRAMPS" % (name,_('Read Only')))
|
||||
else:
|
||||
self.state.window.set_title("%s - GRAMPS" % name)
|
||||
else:
|
||||
GrampsKeys.save_last_file("")
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('The database file specified could not be opened.'))
|
||||
return 0
|
||||
except ( IOError, OSError, Errors.FileVersionError), msg:
|
||||
ErrorDialog(_('Cannot open database'),str(msg))
|
||||
return 0
|
||||
except (db.DBAccessError,db.DBError), msg:
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('%s could not be opened.' % filename) + '\n' + msg[1])
|
||||
return 0
|
||||
except Exception:
|
||||
DisplayTrace.DisplayTrace()
|
||||
return 0
|
||||
|
||||
# Undo/Redo always start with standard labels and insensitive state
|
||||
#self.undo_callback(None)
|
||||
#self.redo_callback(None)
|
||||
#self.goto_active_person()
|
||||
return 1
|
||||
|
||||
def load_database(self,name,callback=None,mode="w"):
|
||||
|
||||
filename = name
|
||||
|
||||
if self.state.db.load(filename,callback,mode) == 0:
|
||||
return 0
|
||||
val = self.post_load(name,callback)
|
||||
return val
|
||||
|
||||
def post_load(self,name,callback=None):
|
||||
if not self.state.db.version_supported():
|
||||
raise Errors.FileVersionError(
|
||||
"The database version is not supported by this version of GRAMPS.\n"
|
||||
"Please upgrade to the corresponding version or use XML for porting"
|
||||
"data between different database versions.")
|
||||
|
||||
self.state.db.set_save_path(name)
|
||||
|
||||
res = self.state.db.get_researcher()
|
||||
owner = GrampsCfg.get_researcher()
|
||||
if res.get_name() == "" and owner.get_name():
|
||||
self.state.db.set_researcher(owner)
|
||||
|
||||
#self.setup_bookmarks()
|
||||
|
||||
#self.state.db.set_undo_callback(self.undo_callback)
|
||||
#self.state.db.set_redo_callback(self.redo_callback)
|
||||
|
||||
if self.state.db.need_upgrade():
|
||||
if callback:
|
||||
callback(_('Upgrading database...'))
|
||||
self.state.db.upgrade()
|
||||
|
||||
GrampsKeys.save_last_file(name)
|
||||
|
||||
self.relationship = self.RelClass(self.state.db)
|
||||
self.state.emit("database-changed", (self.state.db,))
|
||||
|
||||
#self.change_active_person(self.find_initial_person())
|
||||
#self.goto_active_person()
|
||||
|
||||
#if callback:
|
||||
# callback(_('Setup complete'))
|
||||
#self.enable_buttons(True)
|
||||
return 1
|
||||
|
||||
def on_scratchpad(self,obj):
|
||||
import ScratchPad
|
||||
ScratchPad.ScratchPadWindow(self.db, self)
|
||||
|
||||
def add_all_files_filter(chooser):
|
||||
"""
|
||||
Add an all-permitting filter to the file chooser dialog.
|
||||
"""
|
||||
mime_filter = gtk.FileFilter()
|
||||
mime_filter.set_name(_('All files'))
|
||||
mime_filter.add_pattern('*')
|
||||
chooser.add_filter(mime_filter)
|
||||
|
||||
def add_gramps_files_filter(chooser):
|
||||
"""
|
||||
Add an all-GRAMPS filter to the file chooser dialog.
|
||||
"""
|
||||
mime_filter = gtk.FileFilter()
|
||||
mime_filter.set_name(_('All GRAMPS files'))
|
||||
mime_filter.add_mime_type(const.app_gramps)
|
||||
mime_filter.add_mime_type(const.app_gramps_xml)
|
||||
mime_filter.add_mime_type(const.app_gedcom)
|
||||
chooser.add_filter(mime_filter)
|
||||
|
||||
def add_grdb_filter(chooser):
|
||||
"""
|
||||
Add a GRDB filter to the file chooser dialog.
|
||||
"""
|
||||
mime_filter = gtk.FileFilter()
|
||||
mime_filter.set_name(_('GRAMPS databases'))
|
||||
mime_filter.add_mime_type(const.app_gramps)
|
||||
chooser.add_filter(mime_filter)
|
||||
|
||||
def add_xml_filter(chooser):
|
||||
"""
|
||||
Add a GRAMPS XML filter to the file chooser dialog.
|
||||
"""
|
||||
mime_filter = gtk.FileFilter()
|
||||
mime_filter.set_name(_('GRAMPS XML databases'))
|
||||
mime_filter.add_mime_type(const.app_gramps_xml)
|
||||
chooser.add_filter(mime_filter)
|
||||
|
||||
def add_gedcom_filter(chooser):
|
||||
"""
|
||||
Add a GEDCOM filter to the file chooser dialog.
|
||||
"""
|
||||
mime_filter = gtk.FileFilter()
|
||||
mime_filter.set_name(_('GEDCOM files'))
|
||||
mime_filter.add_mime_type(const.app_gedcom)
|
||||
chooser.add_filter(mime_filter)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Format selectors and filters
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsFormatWidget(gtk.ComboBox):
|
||||
|
||||
def __init__(self):
|
||||
gtk.ComboBox.__init__(self,model=None)
|
||||
|
||||
def set(self,format_list):
|
||||
self.store = gtk.ListStore(str)
|
||||
self.set_model(self.store)
|
||||
cell = gtk.CellRendererText()
|
||||
self.pack_start(cell,True)
|
||||
self.add_attribute(cell,'text',0)
|
||||
self.format_list = format_list
|
||||
|
||||
for format,label in format_list:
|
||||
self.store.append(row=[label])
|
||||
self.set_active(0)
|
||||
|
||||
def get_value(self):
|
||||
active = self.get_active()
|
||||
if active < 0:
|
||||
return None
|
||||
return self.format_list[active][0]
|
||||
|
||||
def format_maker(formats):
|
||||
"""
|
||||
A factory function making format selection widgets.
|
||||
|
||||
Accepts a list of formats to include into selector.
|
||||
The auto selection is always added as the first one.
|
||||
The returned box contains both the label and the selector.
|
||||
"""
|
||||
format_list = [ ('auto',_('Automatically detected')) ]
|
||||
for format in formats:
|
||||
if _KNOWN_FORMATS.has_key(format):
|
||||
format_list.append( (format,_KNOWN_FORMATS[format]) )
|
||||
|
||||
type_selector = GrampsFormatWidget()
|
||||
type_selector.set(format_list)
|
||||
|
||||
box = gtk.HBox()
|
||||
label = gtk.Label(_('Select file _type:'))
|
||||
label.set_use_underline(True)
|
||||
label.set_mnemonic_widget(type_selector)
|
||||
box.pack_start(label,expand=False,fill=False,padding=6)
|
||||
box.add(type_selector)
|
||||
box.show_all()
|
||||
return (box,type_selector)
|
||||
|
2013
src/gramps_main.py
2013
src/gramps_main.py
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user