1#
2# Gramps - a GTK+/GNOME based genealogy program
3#
4# Copyright (C) 2000-2006  Donald N. Allingham
5# Copyright (C) 2009       Gary Burton
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21
22#-------------------------------------------------------------------------
23#
24# GTK libraries
25#
26#-------------------------------------------------------------------------
27from gi.repository import GObject
28from gi.repository import Gdk
29from gi.repository import Gtk
30
31_LEFT = Gdk.keyval_from_name("Left")
32_RIGHT = Gdk.keyval_from_name("Right")
33
34#-------------------------------------------------------------------------
35#
36# Classes
37#
38#-------------------------------------------------------------------------
39
40class GrampsTab(Gtk.Box):
41    """
42    This class provides the base level class for 'tabs', which are used to
43    fill in notebook tabs for Gramps edit dialogs.
44
45    Each tab returns a gtk container widget which can be inserted into a
46    Gtk.Notebook by the instantiating object.
47
48    All tab classes should inherit from GrampsTab
49    """
50
51    def __init__(self, dbstate, uistate, track, name):
52        """
53        @param dbstate: The database state. Contains a reference to
54        the database, along with other state information. The GrampsTab
55        uses this to access the database and to pass to and created
56        child windows (such as edit dialogs).
57        @type dbstate: DbState
58        @param uistate: The UI state. Used primarily to pass to any created
59        subwindows.
60        @type uistate: DisplayState
61        @param track: The window tracking mechanism used to manage windows.
62        This is only used to pass to generted child windows.
63        @type track: list
64        @param name: Notebook label name
65        @type name: str/unicode
66        """
67        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
68
69        # store information to pass to child windows
70        self.dbstate = dbstate
71        self.uistate = uistate
72        self.track = track
73        self.changed = False
74        self.__refs_for_deletion = []
75
76        # save name used for notebook label, and build the widget used
77        # for the label
78
79        self.tab_name = name
80        self.track_ref_for_deletion("tab_name")
81        self.label_container = self.build_label_widget()
82        self.track_ref_for_deletion("label_container")
83
84        # build the interface
85        self.share_btn = None
86        self.build_interface()
87        self.parent_notebook = None
88
89    def get_selected(self):
90        return None
91
92    def is_empty(self):
93        """
94        Indicate if the tab contains any data. This is used to determine
95        how the label should be displayed.
96        """
97        return True
98
99    def build_label_widget(self):
100        """
101        Standard routine to build a widget. Does not need to be overridden
102        by the derived class. Creates an container that has the label and
103        the icon in it.
104        @returns: widget to be used for the notebook label.
105        @rtype: Gtk.Box
106        """
107        hbox = Gtk.Box()
108        icon = self.get_icon_name()
109
110        if isinstance(icon, tuple):
111            name = icon[1]
112        else:
113            name = icon
114
115        self.tab_image = Gtk.Image.new_from_icon_name(name, Gtk.IconSize.MENU)
116        self.track_ref_for_deletion("tab_image")
117        self.label = Gtk.Label(label=self.tab_name)
118        self.track_ref_for_deletion("label")
119        hbox.pack_start(self.tab_image, True, True, 0)
120        hbox.set_spacing(6)
121        hbox.add(self.label)
122        hbox.show_all()
123        return hbox
124
125    def get_icon_name(self):
126        """
127        Provide the name of the registered stock icon to be used as the
128        icon in the label. This is typically overridden by the derived
129        class to provide the new name.
130        @returns: stock icon name
131        @rtype: str
132        """
133        return 'document-new'
134
135    def get_tab_widget(self):
136        """
137        Provide the widget to be used for the notebook tab label. A
138        container class is provided, and the object may manipulate the
139        child widgets contained in the container.
140        @returns: gtk widget
141        @rtype: Gtk.Box
142        """
143        return self.label_container
144
145    def key_pressed(self, obj, event):
146        """
147        Handles the key being pressed.
148        The inheriting object must contain a widget that connects at mimimum
149        to this method, eg an eventbox, tree, ...
150        """
151        if event.type == Gdk.EventType.KEY_PRESS:
152            if event.keyval in (_LEFT,) and \
153                    (event.get_state() & Gdk.ModifierType.MOD1_MASK):
154                self.prev_page()
155            elif event.keyval in (_RIGHT,) and \
156                    (event.get_state() & Gdk.ModifierType.MOD1_MASK):
157                self.next_page()
158            else:
159                return
160            return True
161
162    def _set_label(self, show_image=True):
163        """
164        Updates the label based of if the tab contains information. Tabs
165        without information will not have an icon, and the text will not
166        be bold. Tabs that contain data will have their icon displayed and
167        the label text will be in bold face.
168        """
169        if not self.is_empty():
170            if show_image:
171                self.tab_image.show()
172            else:
173                self.tab_image.hide()
174            self.label.set_text("<b>%s</b>" % self.tab_name)
175            self.label.set_use_markup(True)
176        else:
177            self.tab_image.hide()
178            self.label.set_text(self.tab_name)
179        self.label.set_use_underline(True)
180
181    def build_interface(self):
182        """
183        Builds the interface for the derived class. This function should be
184        overridden in the derived class. Since the classes are derived from
185        Gtk.Box, the self.pack_start, self.pack_end, and self.add functions
186        can be used to add widgets to the interface.
187        """
188        pass
189
190    def set_parent_notebook(self, book):
191        self.parent_notebook = book
192        self.track_ref_for_deletion("parent_notebook")
193
194    def next_page(self):
195        if self.parent_notebook:
196            self.parent_notebook.next_page()
197
198    def prev_page(self):
199        if self.parent_notebook:
200            self.parent_notebook.prev_page()
201
202    def track_ref_for_deletion(self, ref):
203        """
204        Record references of instance variables that need to be removed
205        from scope so that the class can be garbage collected
206        """
207        if ref not in self.__refs_for_deletion:
208            self.__refs_for_deletion.append(ref)
209
210    def clean_up(self):
211        """
212        Remove any instance variables from scope which point to non-glade
213        GTK objects so that the class can be garbage collected.
214        """
215        while len(self.__refs_for_deletion):
216            attr = self.__refs_for_deletion.pop()
217            delattr(self, attr)
218