~ubuntu-branches/ubuntu/utopic/gramps/utopic

« back to all changes in this revision

Viewing changes to src/plugins/view/citationtreeview.py

  • Committer: Package Import Robot
  • Author(s): James A. Treacy
  • Date: 2012-05-22 17:18:36 UTC
  • mfrom: (39.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20120522171836-35fi62lp4w7jnrd7
Tags: 3.4.0-1
* New upstream version
* Updated desktop file. Closes: #667472

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Gramps - a GTK+/GNOME based genealogy program
 
2
#
 
3
# Copyright (C) 2009-2010  Nick Hall
 
4
# Copyright (C) 2011       Tim G L Lyons
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
#
 
20
 
 
21
# $Id: citationtreeview.py 18548 2011-12-04 17:09:17Z kulath $
 
22
 
 
23
"""
 
24
Citation Tree View (or Source tree view).
 
25
A view showing all the Sources with child Citations
 
26
"""
 
27
#-------------------------------------------------------------------------
 
28
#
 
29
# python modules
 
30
#
 
31
#-------------------------------------------------------------------------
 
32
import logging
 
33
LOG = logging.getLogger(".citation")
 
34
_LOG = logging.getLogger('.gui.citationtreeview')
 
35
 
 
36
#-------------------------------------------------------------------------
 
37
#
 
38
# GTK/Gnome modules
 
39
#
 
40
#-------------------------------------------------------------------------
 
41
import gtk
 
42
 
 
43
#-------------------------------------------------------------------------
 
44
#
 
45
# Gramps modules
 
46
#
 
47
#-------------------------------------------------------------------------
 
48
from gui.views.listview import LISTTREE
 
49
from gui.views.treemodels.citationtreemodel import CitationTreeModel
 
50
from gen.plug import CATEGORY_QR_SOURCE_OR_CITATION
 
51
import gen.lib
 
52
from gui.views.listview import ListView
 
53
import Utils
 
54
import Bookmarks
 
55
import Errors
 
56
from DdTargets import DdTargets
 
57
from QuestionDialog import ErrorDialog
 
58
from gui.editors import EditCitation, DeleteCitationQuery, EditSource, \
 
59
    DeleteSrcQuery
 
60
from Filters.SideBar import SourceSidebarFilter
 
61
 
 
62
#-------------------------------------------------------------------------
 
63
#
 
64
# Internationalization
 
65
#
 
66
#-------------------------------------------------------------------------
 
67
from gen.ggettext import gettext as _
 
68
 
 
69
#-------------------------------------------------------------------------
 
70
#
 
71
# PlaceTreeView
 
72
#
 
73
#-------------------------------------------------------------------------
 
74
class CitationTreeView(ListView):
 
75
    """
 
76
    A hierarchical view of sources with citations below them.
 
77
    """
 
78
    # The data items here have to correspond, in order, to the items in
 
79
    # src/giu.views/treemodels/citationtreemodel.py
 
80
    COL_TITLE_PAGE     =  0
 
81
    COL_ID             =  1
 
82
    COL_DATE           =  2
 
83
    COL_CONFIDENCE     =  3
 
84
    COL_CHAN           =  4    
 
85
    COL_SRC_AUTH       =  5
 
86
    COL_SRC_ABBR       =  6
 
87
    COL_SRC_PINFO      =  7
 
88
    # name of the columns
 
89
    COLUMN_NAMES = [
 
90
        _('Title or Page'),
 
91
        _('ID'),
 
92
        _('Date'),
 
93
        _('Confidence'),
 
94
        _('Last Changed'),
 
95
        _('Source: Author'),
 
96
        _('Source: Abbreviation'),
 
97
        _('Source: Publication Information'),
 
98
        ]
 
99
    COLUMN_FILTERABLE = [
 
100
        COL_TITLE_PAGE, 
 
101
        COL_ID,
 
102
        COL_CHAN,
 
103
        COL_SRC_AUTH,
 
104
        COL_SRC_ABBR,
 
105
        COL_SRC_PINFO
 
106
        ]
 
107
    # columns that contain markup
 
108
    MARKUP_COLS = [COL_DATE]
 
109
    # default setting with visible columns, order of the col, and their size
 
110
    CONFIGSETTINGS = (
 
111
        ('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_SRC_AUTH,
 
112
                             COL_SRC_PINFO]),
 
113
        ('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE,
 
114
                          COL_CHAN, COL_SRC_AUTH,
 
115
                          COL_SRC_ABBR, COL_SRC_PINFO]),
 
116
        ('columns.size', [200, 75, 100, 75, 100, 150, 100, 150])
 
117
        )    
 
118
    ADD_MSG = _("Add a new citation and a new source")
 
119
    ADD_SOURCE_MSG = _("Add a new source")
 
120
    ADD_CITATION_MSG = _("Add a new citation to an existing source")
 
121
    EDIT_MSG = _("Edit the selected citation or source")
 
122
    DEL_MSG = _("Delete the selected citation or source")
 
123
    MERGE_MSG = _("Merge the selected citations or selected sources")
 
124
    FILTER_TYPE = "Citation"
 
125
    QR_CATEGORY = CATEGORY_QR_SOURCE_OR_CITATION
 
126
    
 
127
    def __init__(self, pdata, dbstate, uistate, nav_group=0):
 
128
        
 
129
        signal_map = {
 
130
            'citation-add'     : self._citation_row_add,
 
131
            'citation-update'  : self._citation_row_update,
 
132
            'citation-delete'  : self._citation_row_delete,
 
133
            'citation-rebuild' : self._citation_object_build,
 
134
            'source-add'       : self._source_row_add,
 
135
            'source-update'    : self._source_row_update,
 
136
            'source-delete'    : self._source_row_delete,
 
137
            'source-rebuild'   : self._source_object_build,
 
138
            }
 
139
 
 
140
        ListView.__init__(
 
141
            self, _('Citation Tree View'), pdata, dbstate, uistate, 
 
142
            self.COLUMN_NAMES, len(self.COLUMN_NAMES), 
 
143
            CitationTreeModel, signal_map,
 
144
            dbstate.db.get_citation_bookmarks(),
 
145
            Bookmarks.CitationBookmarks, nav_group,
 
146
            multiple=True,
 
147
            filter_class=SourceSidebarFilter,
 
148
            markup = CitationTreeView.MARKUP_COLS)
 
149
 
 
150
        self.func_list.update({
 
151
            '<CONTROL>J' : self.jump,
 
152
            '<CONTROL>BackSpace' : self.key_delete,
 
153
            })
 
154
 
 
155
        self.additional_uis.append(self.additional_ui())
 
156
 
 
157
    def setup_filter(self):
 
158
        """
 
159
        Override the setup of the default Search Bar in listview, so that only
 
160
        the searchable source fields are shown. This includes renaming the
 
161
        'Title or Page' search to 'Title'
 
162
        """
 
163
        def name(i):
 
164
            if i == 0:
 
165
                return _('Title')
 
166
            else:
 
167
                return self.colinfo[i]
 
168
             
 
169
        self.search_bar.setup_filter(
 
170
            [(name(pair[1]), pair[1], pair[1] in self.exact_search())
 
171
                for pair in self.column_order() if pair[0] and 
 
172
                                pair[1] in self.COLUMN_FILTERABLE])
 
173
 
 
174
    def _print_handles(self, text, handle_list):
 
175
        for handle in handle_list:
 
176
            source = self.dbstate.db.get_source_from_handle(handle)
 
177
            citation = self.dbstate.db.get_citation_from_handle(handle)
 
178
            _LOG.debug("\n\n\n")
 
179
            if source:
 
180
                _LOG.debug("---- %s -- source %s" % 
 
181
                           (text, source.get_title()))
 
182
            elif citation:
 
183
                _LOG.debug("---- %s -- citation %s" % 
 
184
                           (text, citation.get_page()))
 
185
            else:
 
186
                _LOG.debug("---- %s -- handle %s" % (text, handle))
 
187
   
 
188
    def _citation_row_add(self, handle_list):            
 
189
        self._print_handles("citation row add", handle_list)
 
190
        self.row_add(handle_list)
 
191
    
 
192
    def _citation_row_update(self, handle_list):            
 
193
        self._print_handles("citation row update", handle_list)
 
194
        self.row_update(handle_list)
 
195
    
 
196
    def _citation_row_delete(self, handle_list):            
 
197
        self._print_handles("citation row delete", handle_list)
 
198
        self.row_delete(handle_list)
 
199
    
 
200
    def _citation_object_build(self, *args):            
 
201
        _LOG.debug("citation object build")
 
202
        self.object_build(*args)
 
203
    
 
204
    def _source_row_add(self, handle_list):            
 
205
        self._print_handles("source row add", handle_list)
 
206
        self.row_add(handle_list)
 
207
    
 
208
    def _source_row_update(self, handle_list):            
 
209
        self._print_handles("source row update", handle_list)
 
210
        self.row_update(handle_list)
 
211
    
 
212
    def _source_row_delete(self, handle_list):            
 
213
        self._print_handles("source row delete", handle_list)
 
214
        self.row_delete(handle_list)
 
215
    
 
216
    def _source_object_build(self, *args):            
 
217
        _LOG.debug("source object build")
 
218
        self.object_build(*args)
 
219
    
 
220
    def navigation_type(self):
 
221
        return 'Citation'
 
222
 
 
223
    def get_bookmarks(self):
 
224
        return self.dbstate.db.get_citation_bookmarks()
 
225
 
 
226
    def drag_info(self):
 
227
        # Since drag only needs to work when just one row is selected, ideally,
 
228
        # this should just return SOURCE_LINK if one source is selected and
 
229
        # CITATION_LINK if one citation is selected, and probably None
 
230
        # otherwise. However, this doesn't work. Drag and drop failed to work at
 
231
        # all for citationtree view, and I think this was because None is
 
232
        # returned during initialisation. There is also a problem where it seems
 
233
        # at some point during a citation merge, neither a Source nor a Citation
 
234
        # is selected. Hence the simplistic solution implemented below, where
 
235
        # CITATION_LINK is always returned except when it is obviously correct
 
236
        # to return SOURCE_LINK.
 
237
        
 
238
        selection = self.selected_handles()
 
239
        if len(selection) == 1 and \
 
240
            self.dbstate.db.get_source_from_handle(selection[0]):
 
241
                return DdTargets.SOURCE_LINK
 
242
        else:
 
243
            return DdTargets.CITATION_LINK
 
244
    
 
245
    def type_list(self):
 
246
        """
 
247
        set the listtype, this governs eg keybinding
 
248
        """
 
249
        return LISTTREE
 
250
 
 
251
    def get_stock(self):
 
252
        return 'gramps-citation'
 
253
 
 
254
    def get_viewtype_stock(self):
 
255
        """
 
256
        Override the default icon.  Set for hierarchical view.
 
257
        """
 
258
        return 'gramps-tree-group'
 
259
        
 
260
    def define_actions(self):
 
261
        """
 
262
        This defines the possible actions for the citation views.
 
263
        Possible actions are:
 
264
        add_source: Add a new source (this is also available from the
 
265
                      source view)
 
266
        add:        Add a new citation and a new source (this can also be done 
 
267
                      by source view add a source, then citation view add a new 
 
268
                      citation to an existing source)
 
269
        share:      Add a new citation to an existing source (when a source is
 
270
                      selected)
 
271
        edit:       Edit a source or a citation.
 
272
        merge:      Merge the selected sources or citations.
 
273
        remove:     Delete the selected sources or citations.
 
274
        
 
275
        
 
276
        """
 
277
        ListView.define_actions(self)
 
278
 
 
279
        self._add_action('Add source', 'gramps-source', _("Add source..."), 
 
280
                         accel=None, 
 
281
                         tip=self.ADD_SOURCE_MSG, 
 
282
                         callback=self.add_source)
 
283
        self._add_action('Add citation', 'gramps-citation', 
 
284
                         _("Add citation..."), 
 
285
                         accel=None, 
 
286
                         tip=self.ADD_CITATION_MSG, 
 
287
                         callback=self.share)
 
288
        
 
289
        self.all_action = gtk.ActionGroup(self.title + "/CitationAll")
 
290
        self.edit_action = gtk.ActionGroup(self.title + "/CitationEdit")
 
291
 
 
292
        self._add_action('FilterEdit', None, _('Citation Filter Editor'),
 
293
                         callback=self.filter_editor,)
 
294
        self._add_action('QuickReport', None, _("Quick View"), None, None, None)
 
295
        self._add_action('Dummy', None, '  ', None, None, self.dummy_report)
 
296
 
 
297
        self._add_action_group(self.edit_action)
 
298
        self._add_action_group(self.all_action)
 
299
 
 
300
        self.all_action.add_actions([
 
301
                ('OpenAllNodes', None, _("Expand all Nodes"), None, None, 
 
302
                 self.open_all_nodes),  
 
303
                ('CloseAllNodes', None, _("Collapse all Nodes"), None, None, 
 
304
                 self.close_all_nodes), 
 
305
                ])
 
306
 
 
307
    def additional_ui(self):
 
308
        """
 
309
        Defines the UI string for UIManager
 
310
        """
 
311
        return '''<ui>
 
312
          <menubar name="MenuBar">
 
313
            <menu action="FileMenu">
 
314
              <placeholder name="LocalExport">
 
315
                <menuitem action="ExportTab"/>
 
316
              </placeholder>
 
317
            </menu>
 
318
            <menu action="BookMenu">
 
319
              <placeholder name="AddEditBook">
 
320
                <menuitem action="AddBook"/>
 
321
                <menuitem action="EditBook"/>
 
322
              </placeholder>
 
323
            </menu>
 
324
            <menu action="GoMenu">
 
325
              <placeholder name="CommonGo">
 
326
                <menuitem action="Back"/>
 
327
                <menuitem action="Forward"/>
 
328
              </placeholder>
 
329
            </menu>
 
330
            <menu action="EditMenu">
 
331
              <placeholder name="CommonEdit">
 
332
                <menuitem action="Add"/>
 
333
                <menuitem action="Add source"/>
 
334
                <menuitem action="Add citation"/>
 
335
                <menuitem action="Edit"/>
 
336
                <menuitem action="Remove"/>
 
337
                <menuitem action="Merge"/>
 
338
             </placeholder>
 
339
              <menuitem action="FilterEdit"/>
 
340
            </menu>
 
341
          </menubar>
 
342
          <toolbar name="ToolBar">
 
343
            <placeholder name="CommonNavigation">
 
344
              <toolitem action="Back"/>  
 
345
              <toolitem action="Forward"/>  
 
346
            </placeholder>
 
347
            <placeholder name="CommonEdit">
 
348
              <toolitem action="Add"/>
 
349
              <toolitem action="Add source"/>
 
350
              <toolitem action="Add citation"/>
 
351
              <toolitem action="Edit"/>
 
352
              <toolitem action="Remove"/>
 
353
              <toolitem action="Merge"/>
 
354
            </placeholder>
 
355
          </toolbar>
 
356
          <popup name="Popup">
 
357
            <menuitem action="Back"/>
 
358
            <menuitem action="Forward"/>
 
359
            <separator/>
 
360
            <menuitem action="OpenAllNodes"/>
 
361
            <menuitem action="CloseAllNodes"/>
 
362
            <separator/>
 
363
            <menuitem action="Add"/>
 
364
            <menuitem action="Edit"/>
 
365
            <menuitem action="Remove"/>
 
366
            <menuitem action="Merge"/>
 
367
            <separator/>
 
368
            <menu name="QuickReport" action="QuickReport">
 
369
              <menuitem action="Dummy"/>
 
370
            </menu>
 
371
          </popup>
 
372
        </ui>'''
 
373
 
 
374
    def dummy_report(self, obj):
 
375
        """ For the xml UI definition of popup to work, the submenu 
 
376
            Quick Report must have an entry in the xml
 
377
            As this submenu will be dynamically built, we offer a dummy action
 
378
        """
 
379
        pass
 
380
 
 
381
    def add_source(self, obj):
 
382
        """
 
383
        add_source: Add a new source (this is also available from the
 
384
                      source view)
 
385
        
 
386
        Create a new Source instance and call the EditSource editor with the
 
387
        new source. 
 
388
        
 
389
        Called when the Add_source button is clicked. 
 
390
        If the window already exists (Errors.WindowActiveError), we ignore it. 
 
391
        This prevents the dialog from coming up twice on the same object.
 
392
        
 
393
        However, since the window is identified by the Source object, and
 
394
        we have just created a new one, it seems to be impossible for the 
 
395
        window to already exist, so this is just an extra safety measure.
 
396
        """
 
397
        try:
 
398
            EditSource(self.dbstate, self.uistate, [], gen.lib.Source())
 
399
        except Errors.WindowActiveError:
 
400
            pass
 
401
 
 
402
    def add(self, obj):
 
403
        """
 
404
        add:        Add a new citation and a new source (this can also be done 
 
405
                      by source view add a source, then citation view add a new 
 
406
                      citation to an existing source)
 
407
        
 
408
        Create a new Source instance and Citation instance and call the 
 
409
        EditSource editor with the new source. 
 
410
        
 
411
        Called when the Add button is clicked. 
 
412
        If the window already exists (Errors.WindowActiveError), we ignore it. 
 
413
        This prevents the dialog from coming up twice on the same object.
 
414
        
 
415
        However, since the window is identified by the Source object, and
 
416
        we have just created a new one, it seems to be impossible for the 
 
417
        window to already exist, so this is just an extra safety measure.
 
418
        """
 
419
        try:
 
420
            EditCitation(self.dbstate, self.uistate, [], gen.lib.Citation(),
 
421
                         gen.lib.Source())
 
422
        except Errors.WindowActiveError:
 
423
            pass
 
424
 
 
425
    def share(self, obj):
 
426
        """
 
427
        share:      Add a new citation to an existing source (when a source is
 
428
                      selected)
 
429
        """
 
430
        for handle in self.selected_handles():
 
431
            # The handle will either be a Source handle or a Citation handle
 
432
            source = self.dbstate.db.get_source_from_handle(handle)
 
433
            citation = self.dbstate.db.get_citation_from_handle(handle)
 
434
            if (not source and not citation) or (source and citation):
 
435
                raise ValueError("selection must be either source or citation")
 
436
            if source:
 
437
                try:
 
438
                    EditCitation(self.dbstate, self.uistate, [], 
 
439
                                 gen.lib.Citation(), source)
 
440
                except Errors.WindowActiveError:
 
441
                    from QuestionDialog import WarningDialog
 
442
                    WarningDialog(_("Cannot share this reference"),
 
443
                                  self.__blocked_text())
 
444
            else:
 
445
                msg = _("Cannot add citation.")
 
446
                msg2 = _("In order to add a citation to an existing source, "
 
447
                         " you must select a source.")
 
448
                ErrorDialog(msg, msg2)
 
449
#    
 
450
    def remove(self, obj):
 
451
        self.remove_selected_objects()
 
452
 
 
453
    def remove_object_from_handle(self, handle):
 
454
        # The handle will either be a Source handle or a Citation handle
 
455
        source = self.dbstate.db.get_source_from_handle(handle)
 
456
        citation = self.dbstate.db.get_citation_from_handle(handle)
 
457
        if (not source and not citation) or (source and citation):
 
458
            raise ValueError("selection must be either source or citation")
 
459
        if citation:
 
460
            the_lists = Utils.get_citation_referents(handle, self.dbstate.db)
 
461
            object = self.dbstate.db.get_citation_from_handle(handle)
 
462
            query = DeleteCitationQuery(self.dbstate, self.uistate, object, 
 
463
                                        the_lists)
 
464
            is_used = any(the_lists)
 
465
            return (query, is_used, object)
 
466
        else:
 
467
            the_lists = Utils.get_source_and_citation_referents(handle, 
 
468
                                                                self.dbstate.db)
 
469
            LOG.debug('the_lists %s' % [the_lists])    
 
470
    
 
471
            object = self.dbstate.db.get_source_from_handle(handle)
 
472
            query = DeleteSrcQuery(self.dbstate, self.uistate, object, 
 
473
                                   the_lists)
 
474
            is_used = any(the_lists)
 
475
            return (query, is_used, object)
 
476
 
 
477
    def edit(self, obj):
 
478
        """
 
479
        Edit either a Source or a Citation, depending on user selection
 
480
        """
 
481
        for handle in self.selected_handles():
 
482
            # The handle will either be a Source handle or a Citation handle
 
483
            source = self.dbstate.db.get_source_from_handle(handle)
 
484
            citation = self.dbstate.db.get_citation_from_handle(handle)
 
485
            if (not source and not citation) or (source and citation):
 
486
                raise ValueError("selection must be either source or citation")
 
487
            if citation:
 
488
                try:
 
489
                    EditCitation(self.dbstate, self.uistate, [], citation)
 
490
                except Errors.WindowActiveError:
 
491
                    pass
 
492
            else: # FIXME need try block here
 
493
                try:
 
494
                    EditSource(self.dbstate, self.uistate, [], source)
 
495
                except Errors.WindowActiveError:
 
496
                    from QuestionDialog import WarningDialog
 
497
                    WarningDialog(_("Cannot share this reference"),
 
498
                                  self.__blocked_text2())
 
499
 
 
500
    def __blocked_text(self):
 
501
        """
 
502
        Return the common text used when citation cannot be edited
 
503
        """
 
504
        return _("This citation cannot be created at this time. "
 
505
                    "Either the associated Source object is already being "
 
506
                    "edited, or another citation associated with the same "
 
507
                    "source is being edited.\n\nTo edit this "
 
508
                    "citation, you need to close the object.")
 
509
 
 
510
    def __blocked_text2(self):
 
511
        """
 
512
        Return the common text used when citation cannot be edited
 
513
        """
 
514
        return _("This source cannot be edited at this time. "
 
515
                    "Either the associated Source object is already being "
 
516
                    "edited, or another citation associated with the same "
 
517
                    "source is being edited.\n\nTo edit this "
 
518
                    "source, you need to close the object.")
 
519
 
 
520
    def merge(self, obj):
 
521
        """
 
522
        Merge the selected citations.
 
523
        """
 
524
        mlist = self.selected_handles()
 
525
        
 
526
        if len(mlist) != 2:
 
527
            msg = _("Cannot merge citations.")
 
528
            msg2 = _("Exactly two citations must be selected to perform a "
 
529
                     "merge. A second citation can be selected by holding "
 
530
                     "down the control key while clicking on the desired "
 
531
                     "citation.")
 
532
            ErrorDialog(msg, msg2)
 
533
        else:
 
534
            source1 = self.dbstate.db.get_source_from_handle(mlist[0])
 
535
            citation1 = self.dbstate.db.get_citation_from_handle(mlist[0])
 
536
            if (not source1 and not citation1) or (source1 and citation1):
 
537
                raise ValueError("selection must be either source or citation")
 
538
            
 
539
            source2 = self.dbstate.db.get_source_from_handle(mlist[1])
 
540
            citation2 = self.dbstate.db.get_citation_from_handle(mlist[1])
 
541
            if (not source2 and not citation2) or (source2 and citation2):
 
542
                raise ValueError("selection must be either source or citation")
 
543
            
 
544
            if citation1 and citation2:
 
545
                if not citation1.get_reference_handle()  == \
 
546
                                citation2.get_reference_handle():         
 
547
                    msg = _("Cannot merge citations.")
 
548
                    msg2 = _("The two selected citations must have the same "
 
549
                             "source to perform a merge. If you want to merge "
 
550
                             "these two citations, then you must merge the "
 
551
                             "sources first.")
 
552
                    ErrorDialog(msg, msg2)
 
553
                else:
 
554
                    import Merge
 
555
                    Merge.MergeCitations(self.dbstate, self.uistate, 
 
556
                                         mlist[0], mlist[1])
 
557
            elif source1 and source2:
 
558
                import Merge
 
559
                Merge.MergeSources(self.dbstate, self.uistate, 
 
560
                                     mlist[0], mlist[1])
 
561
            else:
 
562
                msg = _("Cannot perform merge.")
 
563
                msg2 = _("Both objects must be of the same type, either "
 
564
                         "both must be sources, or both must be "
 
565
                         "citations.")
 
566
                ErrorDialog(msg, msg2)
 
567
 
 
568
    def get_handle_from_gramps_id(self, gid):
 
569
        obj = self.dbstate.db.get_citation_from_gramps_id(gid)
 
570
        if obj:
 
571
            return obj.get_handle()
 
572
        else:
 
573
            return None
 
574
 
 
575
    def get_default_gramplets(self):
 
576
        """
 
577
        Define the default gramplets for the sidebar and bottombar.
 
578
        """
 
579
        return (("Source Filter",),
 
580
                ("Citation Gallery",
 
581
                 "Citation Notes",
 
582
                 "Citation Backlinks"))