1# Gramps - a GTK+/GNOME based genealogy program
2#
3# Copyright (C) 2001-2006  Donald N. Allingham
4# Copyright (C) 2008       Gary Burton
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20
21"""
22Repository View
23"""
24
25#-------------------------------------------------------------------------
26#
27# GTK/Gnome modules
28#
29#-------------------------------------------------------------------------
30from gi.repository import Gtk
31
32#-------------------------------------------------------------------------
33#
34# gramps modules
35#
36#-------------------------------------------------------------------------
37from gramps.gen.lib import Repository
38from gramps.gui.views.listview import ListView, TEXT, MARKUP, ICON
39from gramps.gui.views.treemodels import RepositoryModel
40from gramps.gui.views.bookmarks import RepoBookmarks
41from gramps.gen.errors import WindowActiveError
42from gramps.gen.config import config
43from gramps.gui.editors import EditRepository, DeleteRepositoryQuery
44from gramps.gui.ddtargets import DdTargets
45from gramps.gui.dialog import ErrorDialog
46from gramps.gui.filters.sidebar import RepoSidebarFilter
47from gramps.gui.merge import MergeRepository
48from gramps.gen.plug import CATEGORY_QR_REPOSITORY
49
50#-------------------------------------------------------------------------
51#
52# internationalization
53#
54#-------------------------------------------------------------------------
55from gramps.gen.const import GRAMPS_LOCALE as glocale
56_ = glocale.translation.sgettext
57
58
59#-------------------------------------------------------------------------
60#
61# RepositoryView
62#
63#-------------------------------------------------------------------------
64class RepositoryView(ListView):
65    """ repository listview class
66    """
67    COL_NAME = 0
68    COL_ID = 1
69    COL_TYPE = 2
70    COL_URL = 3
71    COL_STREET = 4
72    COL_LOCALITY = 5
73    COL_CITY = 6
74    COL_STATE = 7
75    COL_COUNTRY = 8
76    COL_ZIP = 9
77    COL_EMAIL = 10
78    COL_SURL = 11
79    COL_PRIV = 12
80    COL_TAGS = 13
81    COL_CHAN = 14
82
83    # column definitions
84    COLUMNS = [
85        (_('Name'), TEXT, None),
86        (_('ID'), TEXT, None),
87        (_('Type'), TEXT, None),
88        (_('Home URL'), TEXT, None),
89        (_('Street'), TEXT, None),
90        (_('Locality'), TEXT, None),
91        (_('City'), TEXT, None),
92        (_('State/County'), TEXT, None),
93        (_('Country'), TEXT, None),
94        (_('ZIP/Postal Code'), TEXT, None),
95        (_('Email'), TEXT, None),
96        (_('Search URL'), TEXT, None),
97        (_('Private'), ICON, 'gramps-lock'),
98        (_('Tags'), TEXT, None),
99        (_('Last Changed'), TEXT, None),
100        ]
101    # default setting with visible columns, order of the col, and their size
102    CONFIGSETTINGS = (
103        ('columns.visible', [COL_NAME, COL_ID, COL_TYPE, COL_URL, COL_STREET,
104                             ]),
105        ('columns.rank', [COL_NAME, COL_ID, COL_TYPE, COL_URL, COL_STREET,
106                          COL_LOCALITY, COL_CITY, COL_STATE, COL_COUNTRY,
107                          COL_ZIP, COL_EMAIL, COL_SURL, COL_PRIV, COL_TAGS,
108                          COL_CHAN]),
109        ('columns.size', [200, 75, 100, 250, 100, 100, 100, 100, 100,
110                             100, 100, 100, 40, 100, 100])
111        )
112    ADD_MSG = _("Add a new repository")
113    EDIT_MSG = _("Edit the selected repository")
114    DEL_MSG = _("Delete the selected repository")
115    MERGE_MSG = _("Merge the selected repositories")
116    FILTER_TYPE = "Repository"
117    QR_CATEGORY = CATEGORY_QR_REPOSITORY
118
119    def __init__(self, pdata, dbstate, uistate, nav_group=0):
120
121        signal_map = {
122            'repository-add'     : self.row_add,
123            'repository-update'  : self.row_update,
124            'repository-delete'  : self.row_delete,
125            'repository-rebuild' : self.object_build,
126            }
127
128        ListView.__init__(
129            self, _('Repositories'), pdata, dbstate, uistate,
130            RepositoryModel, signal_map,
131            RepoBookmarks, nav_group,
132            multiple=True,
133            filter_class=RepoSidebarFilter)
134
135        self.additional_uis.append(self.additional_ui)
136
137    def navigation_type(self):
138        return 'Repository'
139
140    def drag_info(self):
141        return DdTargets.REPO_LINK
142
143    def get_stock(self):
144        return 'gramps-repository'
145
146    additional_ui = [  # Defines the UI string for UIManager
147        '''
148      <placeholder id="LocalExport">
149        <item>
150          <attribute name="action">win.ExportTab</attribute>
151          <attribute name="label" translatable="yes">Export View...</attribute>
152        </item>
153      </placeholder>
154''',
155        '''
156      <section id="AddEditBook">
157        <item>
158          <attribute name="action">win.AddBook</attribute>
159          <attribute name="label" translatable="yes">_Add Bookmark</attribute>
160        </item>
161        <item>
162          <attribute name="action">win.EditBook</attribute>
163          <attribute name="label" translatable="no">%s...</attribute>
164        </item>
165      </section>
166''' % _('Organize Bookmarks'),
167        '''
168      <placeholder id="CommonGo">
169      <section>
170        <item>
171          <attribute name="action">win.Back</attribute>
172          <attribute name="label" translatable="yes">_Back</attribute>
173        </item>
174        <item>
175          <attribute name="action">win.Forward</attribute>
176          <attribute name="label" translatable="yes">_Forward</attribute>
177        </item>
178      </section>
179      </placeholder>
180''',
181        '''
182      <section id='CommonEdit' groups='RW'>
183        <item>
184          <attribute name="action">win.Add</attribute>
185          <attribute name="label" translatable="yes">_Add...</attribute>
186        </item>
187        <item>
188          <attribute name="action">win.Edit</attribute>
189          <attribute name="label">%s</attribute>
190        </item>
191        <item>
192          <attribute name="action">win.Remove</attribute>
193          <attribute name="label" translatable="yes">_Delete</attribute>
194        </item>
195        <item>
196          <attribute name="action">win.Merge</attribute>
197          <attribute name="label" translatable="yes">_Merge...</attribute>
198        </item>
199      </section>
200''' % _("action|_Edit..."),  # to use sgettext()
201        '''
202        <placeholder id='otheredit'>
203        <item>
204          <attribute name="action">win.FilterEdit</attribute>
205          <attribute name="label" translatable="yes">'''
206        '''Repository Filter Editor</attribute>
207        </item>
208        </placeholder>
209''',  # Following are the Toolbar items
210        '''
211    <placeholder id='CommonNavigation'>
212    <child groups='RO'>
213      <object class="GtkToolButton">
214        <property name="icon-name">go-previous</property>
215        <property name="action-name">win.Back</property>
216        <property name="tooltip_text" translatable="yes">'''
217        '''Go to the previous object in the history</property>
218        <property name="label" translatable="yes">_Back</property>
219        <property name="use-underline">True</property>
220      </object>
221      <packing>
222        <property name="homogeneous">False</property>
223      </packing>
224    </child>
225    <child groups='RO'>
226      <object class="GtkToolButton">
227        <property name="icon-name">go-next</property>
228        <property name="action-name">win.Forward</property>
229        <property name="tooltip_text" translatable="yes">'''
230        '''Go to the next object in the history</property>
231        <property name="label" translatable="yes">_Forward</property>
232        <property name="use-underline">True</property>
233      </object>
234      <packing>
235        <property name="homogeneous">False</property>
236      </packing>
237    </child>
238    </placeholder>
239''',
240        '''
241    <placeholder id='BarCommonEdit'>
242    <child groups='RW'>
243      <object class="GtkToolButton">
244        <property name="icon-name">list-add</property>
245        <property name="action-name">win.Add</property>
246        <property name="tooltip_text">%s</property>
247        <property name="label" translatable="yes">_Add...</property>
248        <property name="use-underline">True</property>
249      </object>
250      <packing>
251        <property name="homogeneous">False</property>
252      </packing>
253    </child>
254    <child groups='RW'>
255      <object class="GtkToolButton">
256        <property name="icon-name">gtk-edit</property>
257        <property name="action-name">win.Edit</property>
258        <property name="tooltip_text">%s</property>
259        <property name="label" translatable="yes">Edit...</property>
260        <property name="use-underline">True</property>
261      </object>
262      <packing>
263        <property name="homogeneous">False</property>
264      </packing>
265    </child>
266    <child groups='RW'>
267      <object class="GtkToolButton">
268        <property name="icon-name">list-remove</property>
269        <property name="action-name">win.Remove</property>
270        <property name="tooltip_text">%s</property>
271        <property name="label" translatable="yes">_Delete</property>
272        <property name="use-underline">True</property>
273      </object>
274      <packing>
275        <property name="homogeneous">False</property>
276      </packing>
277    </child>
278    <child groups='RW'>
279      <object class="GtkToolButton">
280        <property name="icon-name">gramps-merge</property>
281        <property name="action-name">win.Merge</property>
282        <property name="tooltip_text">%s</property>
283        <property name="label" translatable="yes">_Merge...</property>
284        <property name="use-underline">True</property>
285      </object>
286      <packing>
287        <property name="homogeneous">False</property>
288      </packing>
289    </child>
290    </placeholder>
291''' % (ADD_MSG, EDIT_MSG, DEL_MSG, MERGE_MSG),
292        '''
293    <menu id="Popup">
294      <section>
295        <item>
296          <attribute name="action">win.Back</attribute>
297          <attribute name="label" translatable="yes">_Back</attribute>
298        </item>
299        <item>
300          <attribute name="action">win.Forward</attribute>
301          <attribute name="label" translatable="yes">Forward</attribute>
302        </item>
303      </section>
304      <section id="PopUpTree">
305      </section>
306      <section>
307        <item>
308          <attribute name="action">win.Add</attribute>
309          <attribute name="label" translatable="yes">_Add...</attribute>
310        </item>
311        <item>
312          <attribute name="action">win.Edit</attribute>
313          <attribute name="label">%s</attribute>
314        </item>
315        <item>
316          <attribute name="action">win.Remove</attribute>
317          <attribute name="label" translatable="yes">_Delete</attribute>
318        </item>
319        <item>
320          <attribute name="action">win.Merge</attribute>
321          <attribute name="label" translatable="yes">_Merge...</attribute>
322        </item>
323      </section>
324      <section>
325        <placeholder id='QuickReport'>
326        </placeholder>
327      </section>
328    </menu>
329    ''' % _('action|_Edit...')  # to use sgettext()
330    ]
331
332    def add(self, *obj):
333        EditRepository(self.dbstate, self.uistate, [], Repository())
334
335    def remove(self, *obj):
336        self.remove_selected_objects()
337
338    def remove_object_from_handle(self, handle):
339        source_list = [
340            item[1] for item in
341            self.dbstate.db.find_backlink_handles(handle, ['Source'])]
342        object = self.dbstate.db.get_repository_from_handle(handle)
343        query = DeleteRepositoryQuery(self.dbstate, self.uistate, object,
344                                      source_list)
345        is_used = len(source_list) > 0
346        return (query, is_used, object)
347
348    def edit(self, *obj):
349        for handle in self.selected_handles():
350            repos = self.dbstate.db.get_repository_from_handle(handle)
351            try:
352                EditRepository(self.dbstate, self.uistate, [], repos)
353            except WindowActiveError:
354                pass
355
356    def merge(self, *obj):
357        """
358        Merge the selected repositories.
359        """
360        mlist = self.selected_handles()
361
362        if len(mlist) != 2:
363            msg = _("Cannot merge repositories.")
364            msg2 = _("Exactly two repositories must be selected to perform a "
365                     "merge. A second repository can be selected by holding "
366                     "down the control key while clicking on the desired "
367                     "repository.")
368            ErrorDialog(msg, msg2, parent=self.uistate.window)
369        else:
370            MergeRepository(self.dbstate, self.uistate, [], mlist[0], mlist[1])
371
372    def get_handle_from_gramps_id(self, gid):
373        obj = self.dbstate.db.get_repository_from_gramps_id(gid)
374        if obj:
375            return obj.get_handle()
376        else:
377            return None
378
379    def tag_updated(self, handle_list):
380        """
381        Update tagged rows when a tag color changes.
382        """
383        all_links = set([])
384        for tag_handle in handle_list:
385            links = set([link[1] for link in
386                         self.dbstate.db.find_backlink_handles(tag_handle,
387                                                include_classes='Repository')])
388            all_links = all_links.union(links)
389        self.row_update(list(all_links))
390
391    def add_tag(self, transaction, repo_handle, tag_handle):
392        """
393        Add the given tag to the given repository.
394        """
395        repo = self.dbstate.db.get_repository_from_handle(repo_handle)
396        repo.add_tag(tag_handle)
397        self.dbstate.db.commit_repository(repo, transaction)
398
399    def get_default_gramplets(self):
400        """
401        Define the default gramplets for the sidebar and bottombar.
402        """
403        return (("Repository Filter",),
404                ("Repository Details",
405                 "Repository Notes",
406                 "Repository Backlinks"))
407