# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2009 Gerald Britton # # 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: glade.py 10874 2009-03-03 18:00:00Z gbritton $ #------------------------------------------------------------------------ # # Glade # #------------------------------------------------------------------------ """ Glade file operations This module exports the Glade class. """ #------------------------------------------------------------------------ # # Python modules # #------------------------------------------------------------------------ import sys import os import gtk #------------------------------------------------------------------------ # # gramps modules # #------------------------------------------------------------------------ import const #------------------------------------------------------------------------ # # Glade class. Derived from gtk.Builder # #------------------------------------------------------------------------ class Glade(gtk.Builder): """ Glade class: Manage glade files as gtk.Builder objects """ __slots__ = ['__toplevel', '__filename', '__dirname'] def __init__(self, filename=None, dirname=None, toplevel=None): """ Class Constructor: Returns a new instance of the Glade class :type filename: string :param filename: The name of the glade file to be used. Defaults to None :type dirname: string :param dirname: The directory to search for the glade file. Defaults to None which will cause a search for the file in the default directory followed by the directory of the calling module. :type toplevel: toplevel :param toplevel: The toplevel object to search for in the glade file. Defaults to None, which will cause a search for a toplevel matching the file name. :rtype: object reference :returns: reference to the newly-created Glade instance """ gtk.Builder.__init__(self) filename_given = filename is not None dirname_given = dirname is not None # if filename not given, use module name to derive it if not filename_given: filename = sys._getframe(1).f_code.co_filename filename = os.path.basename(filename) filename = filename.rpartition('.')[0] + '.glade' filename = filename.lstrip('_').lower() # if dirname not given, use current directory if not dirname_given: dirname = sys._getframe(1).f_code.co_filename dirname = os.path.dirname(dirname) # try to find the glade file if filename_given and dirname_given: # both given -- use them path = os.path.join(dirname, filename) elif filename_given: # try default directory first path = os.path.join(const.GLADE_DIR, filename) if not os.path.exists(path): # then module directory path = os.path.join(dirname, filename) elif dirname_given: # dirname given -- use it path = os.path.join(dirname, filename) # neither filename nor dirname given. Try: # 1. derived filename in default directory # 2. derived filename in module directory else: path = os.path.join(const.GLADE_DIR, filename) if not os.path.exists(path): path = os.path.join(dirname, filename) # try to build Gtk objects from glade file. Let exceptions happen self.add_from_file(path) self.__filename, self.__dirname = os.path.split(path) # try to find the toplevel widget if toplevel: # toplevel is given self.__toplevel = self.get_object(toplevel) else: # toplevel not given # first, use filename as possible toplevel widget name self.__toplevel = self.get_object(filename.rpartition('.')[0]) # next try lowercase filename as possible widget name if not self.__toplevel: self.__toplevel = self.get_object( filename.rpartition('.')[0].lower()) if not self.__toplevel: # if no match found, search for first toplevel widget for obj in self.get_objects(): if hasattr(obj, 'get_toplevel'): self.__toplevel = obj.get_toplevel() break else: self.__toplevel = None def __get_filename(self): """ __get_filename: return filename of glade file :rtype: string :returns: filename of glade file """ return self.__filename filename = property(__get_filename) def __get_dirname(self): """ __get_dirname: return directory where glade file found :rtype: string :returns: directory where glade file found """ return self.__dirname dirname = property(__get_dirname) def __get_toplevel(self): """ __get_toplevel: return toplevel object :rtype: object :returns: toplevel object """ return self.__toplevel def __set_toplevel(self, toplevel): """ __set_toplevel: set toplevel object :type toplevel: string :param toplevel: The name of the toplevel object to use """ self.__toplevel = self.get_object(toplevel) toplevel = property(__get_toplevel, __set_toplevel) def get_child_object(self, value, toplevel=None): """ get_child_object: search for a child object, by name, within a given toplevel. If no toplevel argument is supplied, use the toplevel attribute for this instance :type value: string :param value: The name of the child object to find :type toplevel: string :param toplevel: The name of the toplevel object to us :rtype: object :returns: child object """ if not toplevel: toplevel = self.__toplevel if not toplevel: raise ValueError, "Top level object required" if isinstance(toplevel, basestring): toplevel = self.get_object(toplevel) # Simple Breadth-First Search queue = [toplevel] while queue: obj = queue.pop(0) if obj.get_name() == value: return obj if hasattr(obj, 'get_children'): queue += obj.get_children() else: return None