Clean-up Sources and Citations views:
* Add icon for citations view * disable old sourceview * change citationtreeview to be Sources navigation view * citationlistview is now the Citations view * merge libcitationview into citationlistview and citationtreeview, and corrected and rationalised * remove libcitationview * corrected initialisation of source_handle in Citation.py * fixes for preventing same source being edited twice - fixed blockedtext in citationembededlist - override build_window_key in editcitation.py svn: r18211
This commit is contained in:
parent
a4f9e6834d
commit
a906c98439
@ -134,6 +134,7 @@ class _DdTargets(object):
|
|||||||
self.SOURCE_LINK = _DdType(self, 'source-link')
|
self.SOURCE_LINK = _DdType(self, 'source-link')
|
||||||
self.URL = _DdType(self, 'url')
|
self.URL = _DdType(self, 'url')
|
||||||
self.SURNAME = _DdType(self, 'surname')
|
self.SURNAME = _DdType(self, 'surname')
|
||||||
|
self.CITATION_LINK = _DdType(self, 'citation-link')
|
||||||
|
|
||||||
# List of all types that are used between
|
# List of all types that are used between
|
||||||
# gramps widgets but should not be exported
|
# gramps widgets but should not be exported
|
||||||
@ -160,7 +161,8 @@ class _DdTargets(object):
|
|||||||
self.SOURCEREF,
|
self.SOURCEREF,
|
||||||
self.SOURCE_LINK,
|
self.SOURCE_LINK,
|
||||||
self.URL,
|
self.URL,
|
||||||
self.SURNAME
|
self.SURNAME,
|
||||||
|
self.CITATION_LINK
|
||||||
]
|
]
|
||||||
|
|
||||||
self.CHILD = _DdType(self, 'child')
|
self.CHILD = _DdType(self, 'child')
|
||||||
|
@ -70,7 +70,7 @@ class Citation(MediaBase, NoteBase, PrimaryObject, DateBase):
|
|||||||
MediaBase.__init__(self) # 7
|
MediaBase.__init__(self) # 7
|
||||||
NoteBase.__init__(self) # 6
|
NoteBase.__init__(self) # 6
|
||||||
DateBase.__init__(self) # 2
|
DateBase.__init__(self) # 2
|
||||||
self.source_handle = None, # 5
|
self.source_handle = None # 5
|
||||||
self.page = "" # 3
|
self.page = "" # 3
|
||||||
self.confidence = Citation.CONF_NORMAL # 4
|
self.confidence = Citation.CONF_NORMAL # 4
|
||||||
self.datamap = {} # 8
|
self.datamap = {} # 8
|
||||||
|
@ -180,6 +180,16 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("selection must be either source or citation")
|
raise ValueError("selection must be either source or citation")
|
||||||
|
|
||||||
|
def __blocked_text(self):
|
||||||
|
"""
|
||||||
|
Return the common text used when citation cannot be edited
|
||||||
|
"""
|
||||||
|
return _("This citation cannot be created at this time. "
|
||||||
|
"Either the associated Source object is already being "
|
||||||
|
"edited, or another citation associated with the same "
|
||||||
|
"source is being edited.\n\nTo edit this "
|
||||||
|
"citation, you need to close the object.")
|
||||||
|
|
||||||
def edit_button_clicked(self, obj):
|
def edit_button_clicked(self, obj):
|
||||||
"""
|
"""
|
||||||
Get the selected Citation instance and call the EditCitation editor
|
Get the selected Citation instance and call the EditCitation editor
|
||||||
@ -190,10 +200,8 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
|||||||
This prevents the dialog from coming up twice on the same object.
|
This prevents the dialog from coming up twice on the same object.
|
||||||
"""
|
"""
|
||||||
handle = self.get_selected()
|
handle = self.get_selected()
|
||||||
LOG.debug('selected handle %s' % handle)
|
|
||||||
if handle:
|
if handle:
|
||||||
citation = self.dbstate.db.get_citation_from_handle(handle)
|
citation = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
LOG.debug("selected citation: %s" % citation)
|
|
||||||
try:
|
try:
|
||||||
from gui.editors import EditCitation
|
from gui.editors import EditCitation
|
||||||
EditCitation(self.dbstate, self.uistate, self.track, citation,
|
EditCitation(self.dbstate, self.uistate, self.track, citation,
|
||||||
|
@ -90,6 +90,37 @@ class EditCitation(EditPrimary):
|
|||||||
# EditCitation, not only do we need to protect obj (which will be
|
# EditCitation, not only do we need to protect obj (which will be
|
||||||
# a Citation, but we also need to protect the associated Source.
|
# a Citation, but we also need to protect the associated Source.
|
||||||
|
|
||||||
|
def build_window_key(self, obj):
|
||||||
|
"""
|
||||||
|
Return a key for the edit window that is opened.
|
||||||
|
This function overrides the build_window_key in EditPrimary.
|
||||||
|
|
||||||
|
There is a problem with database object locking. The database locking is
|
||||||
|
handled by the ManagedWindow class, which will only allow one primary
|
||||||
|
object to be edited at a time.
|
||||||
|
|
||||||
|
Normally, the window key is derived from the obj that is being edited.
|
||||||
|
However, in the case of EditCitation, there are two objects being
|
||||||
|
edited, the Citation and the Source. Both must be protected against
|
||||||
|
against the user trying to edit them twice.
|
||||||
|
|
||||||
|
What we do here is to derive the window key from the Source object, if
|
||||||
|
one exists. A Citation always points to exactly one Source object, so if
|
||||||
|
we try to edit the same Citation twice, the associated Source objects
|
||||||
|
will be the same so this will be prevented. If we try to edit a Source
|
||||||
|
object and a Citation object that refers to the same Source, then again,
|
||||||
|
the window key will be the same and this will be prevented.
|
||||||
|
"""
|
||||||
|
if obj and obj.get_reference_handle():
|
||||||
|
# citation already points to source
|
||||||
|
return obj.get_reference_handle()
|
||||||
|
elif self.source and self.source.get_handle():
|
||||||
|
# Citation doesn't yet point to source, but source exists and has a
|
||||||
|
# handle
|
||||||
|
return self.source.get_handle()
|
||||||
|
else:
|
||||||
|
return id(self)
|
||||||
|
|
||||||
def empty_object(self):
|
def empty_object(self):
|
||||||
"""
|
"""
|
||||||
Return an empty Citation object for comparison for changes.
|
Return an empty Citation object for comparison for changes.
|
||||||
@ -181,7 +212,6 @@ class EditCitation(EditPrimary):
|
|||||||
"""Connects any signals that need to be connected.
|
"""Connects any signals that need to be connected.
|
||||||
|
|
||||||
Called by the init routine of the base class L{EditPrimary}.
|
Called by the init routine of the base class L{EditPrimary}.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.define_ok_button(self.glade.get_object('ok'), self.save)
|
self.define_ok_button(self.glade.get_object('ok'), self.save)
|
||||||
self.define_cancel_button(self.glade.get_object('cancel'))
|
self.define_cancel_button(self.glade.get_object('cancel'))
|
||||||
@ -191,7 +221,19 @@ class EditCitation(EditPrimary):
|
|||||||
"""
|
"""
|
||||||
Connect any signals that need to be connected.
|
Connect any signals that need to be connected.
|
||||||
Called by the init routine of the base class (_EditPrimary).
|
Called by the init routine of the base class (_EditPrimary).
|
||||||
|
|
||||||
|
What this code does is to check that the object edited is not deleted
|
||||||
|
whilst editing it. If the object is deleted we need to close the editor
|
||||||
|
windows and clean up. If the database emits a rebuild signal for the
|
||||||
|
database object type we also abort the edit.
|
||||||
|
|
||||||
|
The Citation editor edits two primary objects, and therefore we need to
|
||||||
|
check if either have been deleted. If the source is deleted, the
|
||||||
|
citation must have been deleted first and will emit a signal, so we
|
||||||
|
shouldn't have to connect to the source-delete signal. It should not be
|
||||||
|
necessary to connect to the source- rebuild signal for similar reasons.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# FIXME: Should this be modified so that the 'close' routines
|
# FIXME: Should this be modified so that the 'close' routines
|
||||||
# are executed not only for the 'Citation', bit also for the 'Source'
|
# are executed not only for the 'Citation', bit also for the 'Source'
|
||||||
self._add_db_signal('citation-rebuild', self._do_close)
|
self._add_db_signal('citation-rebuild', self._do_close)
|
||||||
|
@ -151,6 +151,7 @@ def register_stock_icons ():
|
|||||||
('gramps-zoom-out', _('Zoom Out'), gtk.gdk.CONTROL_MASK, 0, ''),
|
('gramps-zoom-out', _('Zoom Out'), gtk.gdk.CONTROL_MASK, 0, ''),
|
||||||
('gramps-zoom-fit-width', _('Fit Width'), gtk.gdk.CONTROL_MASK, 0, ''),
|
('gramps-zoom-fit-width', _('Fit Width'), gtk.gdk.CONTROL_MASK, 0, ''),
|
||||||
('gramps-zoom-best-fit', _('Fit Page'), gtk.gdk.CONTROL_MASK, 0, ''),
|
('gramps-zoom-best-fit', _('Fit Page'), gtk.gdk.CONTROL_MASK, 0, ''),
|
||||||
|
('gramps-citation', _('Citations'), gtk.gdk.CONTROL_MASK, 0, ''),
|
||||||
]
|
]
|
||||||
# the following icons are not yet in new directory structure
|
# the following icons are not yet in new directory structure
|
||||||
# they should be ported in the near future
|
# they should be ported in the near future
|
||||||
|
@ -19,6 +19,7 @@ dist_pkgdata_DATA = \
|
|||||||
gramps-bookmark-edit.png \
|
gramps-bookmark-edit.png \
|
||||||
gramps-bookmark-new.png \
|
gramps-bookmark-new.png \
|
||||||
gramps-bookmark.png \
|
gramps-bookmark.png \
|
||||||
|
gramps-citation.png \
|
||||||
gramps-config.png \
|
gramps-config.png \
|
||||||
gramps-date.png \
|
gramps-date.png \
|
||||||
gramps-date-edit.png \
|
gramps-date-edit.png \
|
||||||
|
BIN
src/images/16x16/gramps-citation.png
Normal file
BIN
src/images/16x16/gramps-citation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
@ -19,6 +19,7 @@ dist_pkgdata_DATA = \
|
|||||||
gramps-bookmark-edit.png \
|
gramps-bookmark-edit.png \
|
||||||
gramps-bookmark-new.png \
|
gramps-bookmark-new.png \
|
||||||
gramps-bookmark.png \
|
gramps-bookmark.png \
|
||||||
|
gramps-citation.png \
|
||||||
gramps-config.png \
|
gramps-config.png \
|
||||||
gramps-date-edit.png \
|
gramps-date-edit.png \
|
||||||
gramps-date.png \
|
gramps-date.png \
|
||||||
|
BIN
src/images/22x22/gramps-citation.png
Normal file
BIN
src/images/22x22/gramps-citation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
@ -19,6 +19,7 @@ dist_pkgdata_DATA = \
|
|||||||
gramps-bookmark-edit.png \
|
gramps-bookmark-edit.png \
|
||||||
gramps-bookmark-new.png \
|
gramps-bookmark-new.png \
|
||||||
gramps-bookmark.png \
|
gramps-bookmark.png \
|
||||||
|
gramps-citation.png \
|
||||||
gramps-config.png \
|
gramps-config.png \
|
||||||
gramps-date-edit.png \
|
gramps-date-edit.png \
|
||||||
gramps-date.png \
|
gramps-date.png \
|
||||||
|
BIN
src/images/48x48/gramps-citation.png
Normal file
BIN
src/images/48x48/gramps-citation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
@ -19,6 +19,7 @@ dist_pkgdata_DATA = \
|
|||||||
gramps-bookmark-edit.svg \
|
gramps-bookmark-edit.svg \
|
||||||
gramps-bookmark-new.svg \
|
gramps-bookmark-new.svg \
|
||||||
gramps-bookmark.svg \
|
gramps-bookmark.svg \
|
||||||
|
gramps-citation.png \
|
||||||
gramps-config.svg \
|
gramps-config.svg \
|
||||||
gramps-date-edit.svg \
|
gramps-date-edit.svg \
|
||||||
gramps-date.svg \
|
gramps-date.svg \
|
||||||
|
BIN
src/images/scalable/gramps-citation.png
Normal file
BIN
src/images/scalable/gramps-citation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
@ -1,427 +0,0 @@
|
|||||||
# Gramps - a GTK+/GNOME based genealogy program
|
|
||||||
#
|
|
||||||
# Copyright (C) 2001-2006 Donald N. Allingham
|
|
||||||
# Copyright (C) 2008 Gary Burton
|
|
||||||
# Copyright (C) 2011 Tim G L Lyons, Nick Hall
|
|
||||||
#
|
|
||||||
# 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$
|
|
||||||
|
|
||||||
"""
|
|
||||||
Citation View
|
|
||||||
"""
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# python modules
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
import logging
|
|
||||||
LOG = logging.getLogger(".citation")
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# GTK/Gnome modules
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
import gtk
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# gramps modules
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
import gen.lib
|
|
||||||
from gui.views.listview import ListView
|
|
||||||
import Utils
|
|
||||||
import Bookmarks
|
|
||||||
import Errors
|
|
||||||
from DdTargets import DdTargets
|
|
||||||
from QuestionDialog import ErrorDialog
|
|
||||||
from gui.editors import EditCitation, DeleteCitationQuery, EditSource, \
|
|
||||||
DeleteSrcQuery
|
|
||||||
from Filters.SideBar import SourceSidebarFilter
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# internationalization
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
from gen.ggettext import gettext as _
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# CitationView
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------
|
|
||||||
class BaseCitationView(ListView):
|
|
||||||
""" citation listview class
|
|
||||||
"""
|
|
||||||
# The configuration parameters have been moved to CitationTreeView and
|
|
||||||
# CitationListView, because they differ for the two different views.
|
|
||||||
|
|
||||||
def __init__(self, pdata, dbstate, uistate, title, model, signal_map,
|
|
||||||
nav_group=0):
|
|
||||||
|
|
||||||
ListView.__init__(
|
|
||||||
self, title, pdata, dbstate, uistate,
|
|
||||||
self.COLUMN_NAMES, len(self.COLUMN_NAMES),
|
|
||||||
model, signal_map,
|
|
||||||
dbstate.db.get_citation_bookmarks(),
|
|
||||||
Bookmarks.CitationBookmarks, nav_group,
|
|
||||||
multiple=True,
|
|
||||||
filter_class=SourceSidebarFilter)
|
|
||||||
|
|
||||||
self.func_list.update({
|
|
||||||
'<CONTROL>J' : self.jump,
|
|
||||||
'<CONTROL>BackSpace' : self.key_delete,
|
|
||||||
})
|
|
||||||
|
|
||||||
self.additional_uis.append(self.additional_ui())
|
|
||||||
|
|
||||||
def navigation_type(self):
|
|
||||||
return 'Citation'
|
|
||||||
|
|
||||||
def get_bookmarks(self):
|
|
||||||
return self.dbstate.db.get_citation_bookmarks()
|
|
||||||
|
|
||||||
def drag_info(self):
|
|
||||||
return DdTargets.SOURCE_LINK
|
|
||||||
|
|
||||||
def define_actions(self):
|
|
||||||
"""
|
|
||||||
This defines the possible actions for the citation views.
|
|
||||||
Possible actions are:
|
|
||||||
add_source: Add a new source (this is also available from the
|
|
||||||
source view)
|
|
||||||
add: Add a new citation and a new source (this can also be done
|
|
||||||
by source view add a source, then citation view add a new
|
|
||||||
citation to an existing source)
|
|
||||||
share: Add a new citation to an existing source (when a source is
|
|
||||||
selected)
|
|
||||||
edit: Edit a source or a citation.
|
|
||||||
merge: Merge the selected sources or citations.
|
|
||||||
remove: Delete the selected sources or citations.
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
ListView.define_actions(self)
|
|
||||||
|
|
||||||
# gtk stock icons are at http://www.pygtk.org/docs/pygtk/gtk-stock-items.html
|
|
||||||
self._add_action('Add source', 'gramps-source', _("Add source..."),
|
|
||||||
accel=None,
|
|
||||||
tip=self.ADD_SOURCE_MSG,
|
|
||||||
callback=self.add_source)
|
|
||||||
self._add_action('Add citation', 'gramps-source', _("Add citation..."),
|
|
||||||
accel=None,
|
|
||||||
tip=self.ADD_CITATION_MSG,
|
|
||||||
callback=self.share)
|
|
||||||
|
|
||||||
self.all_action = gtk.ActionGroup(self.title + "/CitationAll")
|
|
||||||
self.edit_action = gtk.ActionGroup(self.title + "/CitationEdit")
|
|
||||||
|
|
||||||
self._add_action('FilterEdit', None, _('Citation Filter Editor'),
|
|
||||||
callback=self.filter_editor,)
|
|
||||||
self._add_action('QuickReport', None, _("Quick View"), None, None, None)
|
|
||||||
self._add_action('Dummy', None, ' ', None, None, self.dummy_report)
|
|
||||||
|
|
||||||
self._add_action_group(self.edit_action)
|
|
||||||
self._add_action_group(self.all_action)
|
|
||||||
|
|
||||||
def get_stock(self):
|
|
||||||
return 'gramps-citation'
|
|
||||||
|
|
||||||
def additional_ui(self):
|
|
||||||
"""
|
|
||||||
Defines the UI string for UIManager
|
|
||||||
|
|
||||||
This is overridden in citationtreeview because that has additional
|
|
||||||
popup items for open and close all nodes
|
|
||||||
"""
|
|
||||||
return '''<ui>
|
|
||||||
<menubar name="MenuBar">
|
|
||||||
<menu action="FileMenu">
|
|
||||||
<placeholder name="LocalExport">
|
|
||||||
<menuitem action="ExportTab"/>
|
|
||||||
</placeholder>
|
|
||||||
</menu>
|
|
||||||
<menu action="BookMenu">
|
|
||||||
<placeholder name="AddEditBook">
|
|
||||||
<menuitem action="AddBook"/>
|
|
||||||
<menuitem action="EditBook"/>
|
|
||||||
</placeholder>
|
|
||||||
</menu>
|
|
||||||
<menu action="GoMenu">
|
|
||||||
<placeholder name="CommonGo">
|
|
||||||
<menuitem action="Back"/>
|
|
||||||
<menuitem action="Forward"/>
|
|
||||||
<separator/>
|
|
||||||
</placeholder>
|
|
||||||
</menu>
|
|
||||||
<menu action="EditMenu">
|
|
||||||
<placeholder name="CommonEdit">
|
|
||||||
<menuitem action="Add"/>
|
|
||||||
<menuitem action="Add source"/>
|
|
||||||
<menuitem action="Edit"/>
|
|
||||||
<menuitem action="Remove"/>
|
|
||||||
<menuitem action="Merge"/>
|
|
||||||
</placeholder>
|
|
||||||
<menuitem action="FilterEdit"/>
|
|
||||||
</menu>
|
|
||||||
</menubar>
|
|
||||||
<toolbar name="ToolBar">
|
|
||||||
<placeholder name="CommonNavigation">
|
|
||||||
<toolitem action="Back"/>
|
|
||||||
<toolitem action="Forward"/>
|
|
||||||
</placeholder>
|
|
||||||
<placeholder name="CommonEdit">
|
|
||||||
<toolitem action="Add"/>
|
|
||||||
<toolitem action="Add source"/>
|
|
||||||
<toolitem action="Edit"/>
|
|
||||||
<toolitem action="Remove"/>
|
|
||||||
<toolitem action="Merge"/>
|
|
||||||
</placeholder>
|
|
||||||
</toolbar>
|
|
||||||
<popup name="Popup">
|
|
||||||
<menuitem action="Back"/>
|
|
||||||
<menuitem action="Forward"/>
|
|
||||||
<separator/>
|
|
||||||
<menuitem action="Add"/>
|
|
||||||
<menuitem action="Edit"/>
|
|
||||||
<menuitem action="Remove"/>
|
|
||||||
<menuitem action="Merge"/>
|
|
||||||
<separator/>
|
|
||||||
<menu name="QuickReport" action="QuickReport">
|
|
||||||
<menuitem action="Dummy"/>
|
|
||||||
</menu>
|
|
||||||
</popup>
|
|
||||||
</ui>'''
|
|
||||||
|
|
||||||
def dummy_report(self, obj):
|
|
||||||
""" For the xml UI definition of popup to work, the submenu
|
|
||||||
Quick Report must have an entry in the xml
|
|
||||||
As this submenu will be dynamically built, we offer a dummy action
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def add_source(self, obj):
|
|
||||||
"""
|
|
||||||
add_source: Add a new source (this is also available from the
|
|
||||||
source view)
|
|
||||||
|
|
||||||
Create a new Source instance and call the EditSource editor with the
|
|
||||||
new source.
|
|
||||||
|
|
||||||
Called when the Add_source button is clicked.
|
|
||||||
If the window already exists (Errors.WindowActiveError), we ignore it.
|
|
||||||
This prevents the dialog from coming up twice on the same object.
|
|
||||||
|
|
||||||
However, since the window is identified by the Source object, and
|
|
||||||
we have just created a new one, it seems to be impossible for the
|
|
||||||
window to already exist, so this is just an extra safety measure.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
EditSource(self.dbstate, self.uistate, [], gen.lib.Source())
|
|
||||||
except Errors.WindowActiveError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def add(self, obj):
|
|
||||||
"""
|
|
||||||
add: Add a new citation and a new source (this can also be done
|
|
||||||
by source view add a source, then citation view add a new
|
|
||||||
citation to an existing source)
|
|
||||||
|
|
||||||
Create a new Source instance and Citation instance and call the
|
|
||||||
EditSource editor with the new source.
|
|
||||||
|
|
||||||
Called when the Add button is clicked.
|
|
||||||
If the window already exists (Errors.WindowActiveError), we ignore it.
|
|
||||||
This prevents the dialog from coming up twice on the same object.
|
|
||||||
|
|
||||||
However, since the window is identified by the Source object, and
|
|
||||||
we have just created a new one, it seems to be impossible for the
|
|
||||||
window to already exist, so this is just an extra safety measure.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
EditCitation(self.dbstate, self.uistate, [], gen.lib.Citation(),
|
|
||||||
gen.lib.Source())
|
|
||||||
except Errors.WindowActiveError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def share(self, obj):
|
|
||||||
"""
|
|
||||||
share: Add a new citation to an existing source (when a source is
|
|
||||||
selected)
|
|
||||||
"""
|
|
||||||
for handle in self.selected_handles():
|
|
||||||
# The handle will either be a Source handle or a Citation handle
|
|
||||||
source = self.dbstate.db.get_source_from_handle(handle)
|
|
||||||
citation = self.dbstate.db.get_citation_from_handle(handle)
|
|
||||||
if (not source and not citation) or (source and citation):
|
|
||||||
raise ValueError("selection must be either source or citation")
|
|
||||||
if source:
|
|
||||||
try:
|
|
||||||
EditCitation(self.dbstate, self.uistate, [],
|
|
||||||
gen.lib.Citation(), source)
|
|
||||||
except Errors.WindowActiveError:
|
|
||||||
from QuestionDialog import WarningDialog
|
|
||||||
WarningDialog(_("Cannot share this reference"),
|
|
||||||
self.__blocked_text())
|
|
||||||
else:
|
|
||||||
msg = _("Cannot add citation.")
|
|
||||||
msg2 = _("In order to add a citation to an existing source, "
|
|
||||||
" you must select a source.")
|
|
||||||
ErrorDialog(msg, msg2)
|
|
||||||
#
|
|
||||||
def remove(self, obj):
|
|
||||||
self.remove_selected_objects()
|
|
||||||
|
|
||||||
def remove_object_from_handle(self, handle):
|
|
||||||
# The handle will either be a Source handle or a Citation handle
|
|
||||||
source = self.dbstate.db.get_source_from_handle(handle)
|
|
||||||
citation = self.dbstate.db.get_citation_from_handle(handle)
|
|
||||||
if (not source and not citation) or (source and citation):
|
|
||||||
raise ValueError("selection must be either source or citation")
|
|
||||||
if citation:
|
|
||||||
the_lists = Utils.get_citation_referents(handle, self.dbstate.db)
|
|
||||||
object = self.dbstate.db.get_citation_from_handle(handle)
|
|
||||||
query = DeleteCitationQuery(self.dbstate, self.uistate, object,
|
|
||||||
the_lists)
|
|
||||||
is_used = any(the_lists)
|
|
||||||
return (query, is_used, object)
|
|
||||||
else:
|
|
||||||
# FIXME: this is copied from SourceView, because import with
|
|
||||||
# from plugins.view.sourceview import SourceView doesn't
|
|
||||||
# seem to work!
|
|
||||||
the_lists = Utils.get_source_referents(handle, self.dbstate.db)
|
|
||||||
LOG.debug('source referents %s' % [the_lists])
|
|
||||||
citation_referents_list = []
|
|
||||||
for citation in the_lists[7]:
|
|
||||||
LOG.debug('citation %s' % citation)
|
|
||||||
refs = Utils.get_citation_referents(citation, self.dbstate.db)
|
|
||||||
citation_referents_list += [(citation, refs)]
|
|
||||||
LOG.debug('citation_referents_list %s' % [citation_referents_list])
|
|
||||||
|
|
||||||
(person_list, family_list, event_list, place_list, source_list,
|
|
||||||
media_list, repo_list, citation_list) = the_lists
|
|
||||||
the_lists = (person_list, family_list, event_list, place_list,
|
|
||||||
source_list, media_list, repo_list, citation_list,
|
|
||||||
citation_referents_list)
|
|
||||||
|
|
||||||
LOG.debug('the_lists %s' % [the_lists])
|
|
||||||
|
|
||||||
object = self.dbstate.db.get_source_from_handle(handle)
|
|
||||||
query = DeleteSrcQuery(self.dbstate, self.uistate, object,
|
|
||||||
the_lists)
|
|
||||||
is_used = any(the_lists)
|
|
||||||
return (query, is_used, object)
|
|
||||||
|
|
||||||
def edit(self, obj):
|
|
||||||
"""
|
|
||||||
Edit either a Source or a Citation, depending on user selection
|
|
||||||
"""
|
|
||||||
for handle in self.selected_handles():
|
|
||||||
# The handle will either be a Source handle or a Citation handle
|
|
||||||
source = self.dbstate.db.get_source_from_handle(handle)
|
|
||||||
citation = self.dbstate.db.get_citation_from_handle(handle)
|
|
||||||
if (not source and not citation) or (source and citation):
|
|
||||||
raise ValueError("selection must be either source or citation")
|
|
||||||
if citation:
|
|
||||||
LOG.debug("citation handle %s page %s" %
|
|
||||||
(handle, citation.page))
|
|
||||||
try:
|
|
||||||
EditCitation(self.dbstate, self.uistate, [], citation)
|
|
||||||
except Errors.WindowActiveError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
LOG.debug("source handle %s title %s " %
|
|
||||||
(source, source.title))
|
|
||||||
EditSource(self.dbstate, self.uistate, [], source)
|
|
||||||
|
|
||||||
def __blocked_text(self):
|
|
||||||
"""
|
|
||||||
Return the common text used when citation cannot be edited
|
|
||||||
"""
|
|
||||||
return _("This citation cannot be edited at this time. "
|
|
||||||
"Either the associated citation is already being "
|
|
||||||
"edited or another object that is associated with "
|
|
||||||
"the same citation is being edited.\n\nTo edit this "
|
|
||||||
"citation, you need to close the object.")
|
|
||||||
|
|
||||||
def merge(self, obj):
|
|
||||||
"""
|
|
||||||
Merge the selected citations.
|
|
||||||
"""
|
|
||||||
mlist = self.selected_handles()
|
|
||||||
|
|
||||||
if len(mlist) != 2:
|
|
||||||
msg = _("Cannot merge citations.")
|
|
||||||
msg2 = _("Exactly two citations must be selected to perform a "
|
|
||||||
"merge. A second citation can be selected by holding "
|
|
||||||
"down the control key while clicking on the desired "
|
|
||||||
"citation.")
|
|
||||||
ErrorDialog(msg, msg2)
|
|
||||||
else:
|
|
||||||
source1 = self.dbstate.db.get_source_from_handle(mlist[0])
|
|
||||||
citation1 = self.dbstate.db.get_citation_from_handle(mlist[0])
|
|
||||||
if (not source1 and not citation1) or (source1 and citation1):
|
|
||||||
raise ValueError("selection must be either source or citation")
|
|
||||||
|
|
||||||
source2 = self.dbstate.db.get_source_from_handle(mlist[1])
|
|
||||||
citation2 = self.dbstate.db.get_citation_from_handle(mlist[1])
|
|
||||||
if (not source2 and not citation2) or (source2 and citation2):
|
|
||||||
raise ValueError("selection must be either source or citation")
|
|
||||||
|
|
||||||
if citation1 and citation2:
|
|
||||||
if not citation1.get_reference_handle() == \
|
|
||||||
citation2.get_reference_handle():
|
|
||||||
msg = _("Cannot merge citations.")
|
|
||||||
msg2 = _("The two selected citations must have the same "
|
|
||||||
"source to perform a merge. If you want to merge "
|
|
||||||
"these two citations, then you must merge the "
|
|
||||||
"sources first.")
|
|
||||||
ErrorDialog(msg, msg2)
|
|
||||||
else:
|
|
||||||
import Merge
|
|
||||||
Merge.MergeCitations(self.dbstate, self.uistate,
|
|
||||||
mlist[0], mlist[1])
|
|
||||||
elif source1 and source2:
|
|
||||||
import Merge
|
|
||||||
Merge.MergeSources(self.dbstate, self.uistate,
|
|
||||||
mlist[0], mlist[1])
|
|
||||||
else:
|
|
||||||
msg = _("Cannot perform merge.")
|
|
||||||
msg2 = _("Both objects must be of the same type, either "
|
|
||||||
"both must be sources, or both must be "
|
|
||||||
"citations.")
|
|
||||||
ErrorDialog(msg, msg2)
|
|
||||||
|
|
||||||
def get_handle_from_gramps_id(self, gid):
|
|
||||||
obj = self.dbstate.db.get_citation_from_gramps_id(gid)
|
|
||||||
if obj:
|
|
||||||
return obj.get_handle()
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_default_gramplets(self):
|
|
||||||
"""
|
|
||||||
Define the default gramplets for the sidebar and bottombar.
|
|
||||||
This is overridden for the tree view to give 'Source Filter'
|
|
||||||
"""
|
|
||||||
return (("Citation Filter",),
|
|
||||||
("Citation Gallery",
|
|
||||||
"Citation Notes",
|
|
||||||
"Citation Backlinks"))
|
|
@ -69,7 +69,9 @@ CATEGORY_ICON = {
|
|||||||
'Sources': 'gramps-source',
|
'Sources': 'gramps-source',
|
||||||
'Repositories': 'gramps-repository',
|
'Repositories': 'gramps-repository',
|
||||||
'Media': 'gramps-media',
|
'Media': 'gramps-media',
|
||||||
'Notes': 'gramps-notes'}
|
'Notes': 'gramps-notes',
|
||||||
|
'Citations': 'gramps-citation',
|
||||||
|
}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
@ -25,14 +25,37 @@
|
|||||||
Citation List View
|
Citation List View
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# python modules
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
import logging
|
||||||
|
LOG = logging.getLogger(".citation")
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GTK/Gnome modules
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
import gtk
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# gramps modules
|
# gramps modules
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
from libcitationview import BaseCitationView
|
|
||||||
from gui.views.treemodels.citationlistmodel import CitationListModel
|
from gui.views.treemodels.citationlistmodel import CitationListModel
|
||||||
from gen.plug import CATEGORY_QR_SOURCE
|
from gen.plug import CATEGORY_QR_SOURCE
|
||||||
|
import gen.lib
|
||||||
|
from gui.views.listview import ListView
|
||||||
|
import Utils
|
||||||
|
import Bookmarks
|
||||||
|
import Errors
|
||||||
|
from DdTargets import DdTargets
|
||||||
|
from QuestionDialog import ErrorDialog
|
||||||
|
from gui.editors import EditCitation, DeleteCitationQuery
|
||||||
|
from Filters.SideBar import CitationSidebarFilter
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -47,7 +70,7 @@ from gen.ggettext import gettext as _
|
|||||||
# CitationView
|
# CitationView
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class CitationListView(BaseCitationView):
|
class CitationListView(ListView):
|
||||||
"""
|
"""
|
||||||
A list view of citations.
|
A list view of citations.
|
||||||
|
|
||||||
@ -69,7 +92,7 @@ class CitationListView(BaseCitationView):
|
|||||||
COL_SRC_CHAN = 10
|
COL_SRC_CHAN = 10
|
||||||
# name of the columns
|
# name of the columns
|
||||||
COLUMN_NAMES = [
|
COLUMN_NAMES = [
|
||||||
_('Title/Page'),
|
_('Volume/Page'),
|
||||||
_('ID'),
|
_('ID'),
|
||||||
_('Date'),
|
_('Date'),
|
||||||
_('Confidence'),
|
_('Confidence'),
|
||||||
@ -93,8 +116,6 @@ class CitationListView(BaseCitationView):
|
|||||||
ADD_MSG = _("Add a new citation and a new source")
|
ADD_MSG = _("Add a new citation and a new source")
|
||||||
ADD_SOURCE_MSG = _("Add a new source")
|
ADD_SOURCE_MSG = _("Add a new source")
|
||||||
ADD_CITATION_MSG = _("Add a new citation to an existing source")
|
ADD_CITATION_MSG = _("Add a new citation to an existing source")
|
||||||
# Edit delete and merge messages are overridden for the tree view as
|
|
||||||
# they can apply to sources or citations
|
|
||||||
EDIT_MSG = _("Edit the selected citation")
|
EDIT_MSG = _("Edit the selected citation")
|
||||||
DEL_MSG = _("Delete the selected citation")
|
DEL_MSG = _("Delete the selected citation")
|
||||||
MERGE_MSG = _("Merge the selected citations")
|
MERGE_MSG = _("Merge the selected citations")
|
||||||
@ -110,8 +131,225 @@ class CitationListView(BaseCitationView):
|
|||||||
'citation-rebuild' : self.object_build,
|
'citation-rebuild' : self.object_build,
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseCitationView.__init__(self, pdata, dbstate, uistate,
|
ListView.__init__(
|
||||||
_('Citation View'), CitationListModel,
|
self, _('Citation View'), pdata, dbstate, uistate,
|
||||||
signal_map,
|
self.COLUMN_NAMES, len(self.COLUMN_NAMES),
|
||||||
nav_group=nav_group)
|
CitationListModel, signal_map,
|
||||||
|
dbstate.db.get_citation_bookmarks(),
|
||||||
|
Bookmarks.CitationBookmarks, nav_group,
|
||||||
|
multiple=True,
|
||||||
|
filter_class=CitationSidebarFilter)
|
||||||
|
|
||||||
|
self.func_list.update({
|
||||||
|
'<CONTROL>J' : self.jump,
|
||||||
|
'<CONTROL>BackSpace' : self.key_delete,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.additional_uis.append(self.additional_ui())
|
||||||
|
|
||||||
|
def navigation_type(self):
|
||||||
|
return 'Citation'
|
||||||
|
|
||||||
|
def get_bookmarks(self):
|
||||||
|
return self.dbstate.db.get_citation_bookmarks()
|
||||||
|
|
||||||
|
def drag_info(self):
|
||||||
|
return DdTargets.CITATION_LINK
|
||||||
|
|
||||||
|
def define_actions(self):
|
||||||
|
"""
|
||||||
|
This defines the possible actions for the citation views.
|
||||||
|
Possible actions are:
|
||||||
|
add: Add a new citation and a new source (this can also be done
|
||||||
|
by source view add a source, then citation view add a new
|
||||||
|
citation to an existing source)
|
||||||
|
edit: Edit a citation.
|
||||||
|
merge: Merge the selected citations.
|
||||||
|
remove: Delete the selected citations.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
ListView.define_actions(self)
|
||||||
|
|
||||||
|
self.all_action = gtk.ActionGroup(self.title + "/CitationAll")
|
||||||
|
self.edit_action = gtk.ActionGroup(self.title + "/CitationEdit")
|
||||||
|
|
||||||
|
self._add_action('FilterEdit', None, _('Citation Filter Editor'),
|
||||||
|
callback=self.filter_editor,)
|
||||||
|
self._add_action('QuickReport', None, _("Quick View"), None, None, None)
|
||||||
|
self._add_action('Dummy', None, ' ', None, None, self.dummy_report)
|
||||||
|
|
||||||
|
self._add_action_group(self.edit_action)
|
||||||
|
self._add_action_group(self.all_action)
|
||||||
|
|
||||||
|
def get_stock(self):
|
||||||
|
return 'gramps-citation'
|
||||||
|
|
||||||
|
def additional_ui(self):
|
||||||
|
"""
|
||||||
|
Defines the UI string for UIManager
|
||||||
|
"""
|
||||||
|
return '''<ui>
|
||||||
|
<menubar name="MenuBar">
|
||||||
|
<menu action="FileMenu">
|
||||||
|
<placeholder name="LocalExport">
|
||||||
|
<menuitem action="ExportTab"/>
|
||||||
|
</placeholder>
|
||||||
|
</menu>
|
||||||
|
<menu action="BookMenu">
|
||||||
|
<placeholder name="AddEditBook">
|
||||||
|
<menuitem action="AddBook"/>
|
||||||
|
<menuitem action="EditBook"/>
|
||||||
|
</placeholder>
|
||||||
|
</menu>
|
||||||
|
<menu action="GoMenu">
|
||||||
|
<placeholder name="CommonGo">
|
||||||
|
<menuitem action="Back"/>
|
||||||
|
<menuitem action="Forward"/>
|
||||||
|
<separator/>
|
||||||
|
</placeholder>
|
||||||
|
</menu>
|
||||||
|
<menu action="EditMenu">
|
||||||
|
<placeholder name="CommonEdit">
|
||||||
|
<menuitem action="Add"/>
|
||||||
|
<menuitem action="Edit"/>
|
||||||
|
<menuitem action="Remove"/>
|
||||||
|
<menuitem action="Merge"/>
|
||||||
|
</placeholder>
|
||||||
|
<menuitem action="FilterEdit"/>
|
||||||
|
</menu>
|
||||||
|
</menubar>
|
||||||
|
<toolbar name="ToolBar">
|
||||||
|
<placeholder name="CommonNavigation">
|
||||||
|
<toolitem action="Back"/>
|
||||||
|
<toolitem action="Forward"/>
|
||||||
|
</placeholder>
|
||||||
|
<placeholder name="CommonEdit">
|
||||||
|
<toolitem action="Add"/>
|
||||||
|
<toolitem action="Edit"/>
|
||||||
|
<toolitem action="Remove"/>
|
||||||
|
<toolitem action="Merge"/>
|
||||||
|
</placeholder>
|
||||||
|
</toolbar>
|
||||||
|
<popup name="Popup">
|
||||||
|
<menuitem action="Back"/>
|
||||||
|
<menuitem action="Forward"/>
|
||||||
|
<separator/>
|
||||||
|
<menuitem action="Add"/>
|
||||||
|
<menuitem action="Edit"/>
|
||||||
|
<menuitem action="Remove"/>
|
||||||
|
<menuitem action="Merge"/>
|
||||||
|
<separator/>
|
||||||
|
<menu name="QuickReport" action="QuickReport">
|
||||||
|
<menuitem action="Dummy"/>
|
||||||
|
</menu>
|
||||||
|
</popup>
|
||||||
|
</ui>'''
|
||||||
|
|
||||||
|
def dummy_report(self, obj):
|
||||||
|
""" For the xml UI definition of popup to work, the submenu
|
||||||
|
Quick Report must have an entry in the xml
|
||||||
|
As this submenu will be dynamically built, we offer a dummy action
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add(self, obj):
|
||||||
|
"""
|
||||||
|
add: Add a new citation and a new source (this can also be done
|
||||||
|
by source view add a source, then citation view add a new
|
||||||
|
citation to an existing source)
|
||||||
|
|
||||||
|
Create a new Source instance and Citation instance and call the
|
||||||
|
EditCitation editor with the new source and new citation.
|
||||||
|
|
||||||
|
Called when the Add button is clicked.
|
||||||
|
If the window already exists (Errors.WindowActiveError), we ignore it.
|
||||||
|
This prevents the dialog from coming up twice on the same object.
|
||||||
|
|
||||||
|
However, since the window is identified by the Source object, and
|
||||||
|
we have just created a new one, it seems to be impossible for the
|
||||||
|
window to already exist, so this is just an extra safety measure.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
EditCitation(self.dbstate, self.uistate, [], gen.lib.Citation(),
|
||||||
|
gen.lib.Source())
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove(self, obj):
|
||||||
|
self.remove_selected_objects()
|
||||||
|
|
||||||
|
def remove_object_from_handle(self, handle):
|
||||||
|
the_lists = Utils.get_citation_referents(handle, self.dbstate.db)
|
||||||
|
object = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
|
query = DeleteCitationQuery(self.dbstate, self.uistate, object,
|
||||||
|
the_lists)
|
||||||
|
is_used = any(the_lists)
|
||||||
|
return (query, is_used, object)
|
||||||
|
|
||||||
|
def edit(self, obj):
|
||||||
|
"""
|
||||||
|
Edit a Citation
|
||||||
|
"""
|
||||||
|
for handle in self.selected_handles():
|
||||||
|
citation = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
|
try:
|
||||||
|
EditCitation(self.dbstate, self.uistate, [], citation)
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __blocked_text(self):
|
||||||
|
"""
|
||||||
|
Return the common text used when citation cannot be edited
|
||||||
|
"""
|
||||||
|
return _("This citation cannot be edited at this time. "
|
||||||
|
"Either the associated citation is already being "
|
||||||
|
"edited or another object that is associated with "
|
||||||
|
"the same citation is being edited.\n\nTo edit this "
|
||||||
|
"citation, you need to close the object.")
|
||||||
|
|
||||||
|
def merge(self, obj):
|
||||||
|
"""
|
||||||
|
Merge the selected citations.
|
||||||
|
"""
|
||||||
|
mlist = self.selected_handles()
|
||||||
|
|
||||||
|
if len(mlist) != 2:
|
||||||
|
msg = _("Cannot merge citations.")
|
||||||
|
msg2 = _("Exactly two citations must be selected to perform a "
|
||||||
|
"merge. A second citation can be selected by holding "
|
||||||
|
"down the control key while clicking on the desired "
|
||||||
|
"citation.")
|
||||||
|
ErrorDialog(msg, msg2)
|
||||||
|
else:
|
||||||
|
citation1 = self.dbstate.db.get_citation_from_handle(mlist[0])
|
||||||
|
citation2 = self.dbstate.db.get_citation_from_handle(mlist[1])
|
||||||
|
if not citation1.get_reference_handle() == \
|
||||||
|
citation2.get_reference_handle():
|
||||||
|
msg = _("Cannot merge citations.")
|
||||||
|
msg2 = _("The two selected citations must have the same "
|
||||||
|
"source to perform a merge. If you want to merge "
|
||||||
|
"these two citations, then you must merge the "
|
||||||
|
"sources first.")
|
||||||
|
ErrorDialog(msg, msg2)
|
||||||
|
else:
|
||||||
|
import Merge
|
||||||
|
Merge.MergeCitations(self.dbstate, self.uistate,
|
||||||
|
mlist[0], mlist[1])
|
||||||
|
|
||||||
|
def get_handle_from_gramps_id(self, gid):
|
||||||
|
obj = self.dbstate.db.get_citation_from_gramps_id(gid)
|
||||||
|
if obj:
|
||||||
|
return obj.get_handle()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_default_gramplets(self):
|
||||||
|
"""
|
||||||
|
Define the default gramplets for the sidebar and bottombar.
|
||||||
|
This is overridden for the tree view to give 'Source Filter'
|
||||||
|
"""
|
||||||
|
return (("Citation Filter",),
|
||||||
|
("Citation Gallery",
|
||||||
|
"Citation Notes",
|
||||||
|
"Citation Backlinks"))
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
# $Id$
|
# $Id$
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Citation Tree View
|
Citation Tree View (or Source tree view).
|
||||||
|
A view showing all the Sources with child Citations
|
||||||
"""
|
"""
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -31,15 +32,31 @@ Citation Tree View
|
|||||||
import logging
|
import logging
|
||||||
LOG = logging.getLogger(".citation")
|
LOG = logging.getLogger(".citation")
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GTK/Gnome modules
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
import gtk
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Gramps modules
|
# Gramps modules
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
from gui.views.listview import LISTTREE
|
from gui.views.listview import LISTTREE
|
||||||
from libcitationview import BaseCitationView
|
|
||||||
from gui.views.treemodels.citationtreemodel import CitationTreeModel
|
from gui.views.treemodels.citationtreemodel import CitationTreeModel
|
||||||
from gen.plug import CATEGORY_QR_SOURCE
|
from gen.plug import CATEGORY_QR_SOURCE
|
||||||
|
import gen.lib
|
||||||
|
from gui.views.listview import ListView
|
||||||
|
import Utils
|
||||||
|
import Bookmarks
|
||||||
|
import Errors
|
||||||
|
from DdTargets import DdTargets
|
||||||
|
from QuestionDialog import ErrorDialog
|
||||||
|
from gui.editors import EditCitation, DeleteCitationQuery, EditSource, \
|
||||||
|
DeleteSrcQuery
|
||||||
|
from Filters.SideBar import SourceSidebarFilter
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -53,9 +70,9 @@ from gen.ggettext import gettext as _
|
|||||||
# PlaceTreeView
|
# PlaceTreeView
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class CitationTreeView(BaseCitationView):
|
class CitationTreeView(ListView):
|
||||||
"""
|
"""
|
||||||
A hierarchical view of the top three levels of places.
|
A hierarchical view of sources with citations below them.
|
||||||
"""
|
"""
|
||||||
# The data items here have to correspond, in order, to the items in
|
# The data items here have to correspond, in order, to the items in
|
||||||
# src/giu.views/treemodels/citationtreemodel.py
|
# src/giu.views/treemodels/citationtreemodel.py
|
||||||
@ -69,7 +86,7 @@ class CitationTreeView(BaseCitationView):
|
|||||||
COL_SRC_PINFO = 7
|
COL_SRC_PINFO = 7
|
||||||
# name of the columns
|
# name of the columns
|
||||||
COLUMN_NAMES = [
|
COLUMN_NAMES = [
|
||||||
_('Title/Page'),
|
_('Title or Page'),
|
||||||
_('ID'),
|
_('ID'),
|
||||||
_('Date'),
|
_('Date'),
|
||||||
_('Confidence'),
|
_('Confidence'),
|
||||||
@ -80,12 +97,12 @@ class CitationTreeView(BaseCitationView):
|
|||||||
]
|
]
|
||||||
# default setting with visible columns, order of the col, and their size
|
# default setting with visible columns, order of the col, and their size
|
||||||
CONFIGSETTINGS = (
|
CONFIGSETTINGS = (
|
||||||
('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_DATE,
|
('columns.visible', [COL_TITLE_PAGE, COL_ID, COL_SRC_AUTH,
|
||||||
COL_CONFIDENCE]),
|
COL_SRC_PINFO]),
|
||||||
('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE,
|
('columns.rank', [COL_TITLE_PAGE, COL_ID, COL_DATE, COL_CONFIDENCE,
|
||||||
COL_CHAN, COL_SRC_AUTH,
|
COL_CHAN, COL_SRC_AUTH,
|
||||||
COL_SRC_ABBR, COL_SRC_PINFO]),
|
COL_SRC_ABBR, COL_SRC_PINFO]),
|
||||||
('columns.size', [200, 75, 100, 100, 100, 75, 100, 150])
|
('columns.size', [200, 75, 100, 75, 100, 150, 100, 150])
|
||||||
)
|
)
|
||||||
ADD_MSG = _("Add a new citation and a new source")
|
ADD_MSG = _("Add a new citation and a new source")
|
||||||
ADD_SOURCE_MSG = _("Add a new source")
|
ADD_SOURCE_MSG = _("Add a new source")
|
||||||
@ -109,10 +126,30 @@ class CitationTreeView(BaseCitationView):
|
|||||||
'source-rebuild' : self.object_build,
|
'source-rebuild' : self.object_build,
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseCitationView.__init__(self, pdata, dbstate, uistate,
|
ListView.__init__(
|
||||||
_('Citation Tree View'), CitationTreeModel,
|
self, _('Citation Tree View'), pdata, dbstate, uistate,
|
||||||
signal_map,
|
self.COLUMN_NAMES, len(self.COLUMN_NAMES),
|
||||||
nav_group=nav_group)
|
CitationTreeModel, signal_map,
|
||||||
|
dbstate.db.get_citation_bookmarks(),
|
||||||
|
Bookmarks.CitationBookmarks, nav_group,
|
||||||
|
multiple=True,
|
||||||
|
filter_class=SourceSidebarFilter)
|
||||||
|
|
||||||
|
self.func_list.update({
|
||||||
|
'<CONTROL>J' : self.jump,
|
||||||
|
'<CONTROL>BackSpace' : self.key_delete,
|
||||||
|
})
|
||||||
|
|
||||||
|
self.additional_uis.append(self.additional_ui())
|
||||||
|
|
||||||
|
def navigation_type(self):
|
||||||
|
return 'Citation'
|
||||||
|
|
||||||
|
def get_bookmarks(self):
|
||||||
|
return self.dbstate.db.get_citation_bookmarks()
|
||||||
|
|
||||||
|
def drag_info(self):
|
||||||
|
return DdTargets.SOURCE_LINK
|
||||||
|
|
||||||
def type_list(self):
|
def type_list(self):
|
||||||
"""
|
"""
|
||||||
@ -120,6 +157,9 @@ class CitationTreeView(BaseCitationView):
|
|||||||
"""
|
"""
|
||||||
return LISTTREE
|
return LISTTREE
|
||||||
|
|
||||||
|
def get_stock(self):
|
||||||
|
return 'gramps-citation'
|
||||||
|
|
||||||
def get_viewtype_stock(self):
|
def get_viewtype_stock(self):
|
||||||
"""
|
"""
|
||||||
Override the default icon. Set for hierarchical view.
|
Override the default icon. Set for hierarchical view.
|
||||||
@ -128,9 +168,43 @@ class CitationTreeView(BaseCitationView):
|
|||||||
|
|
||||||
def define_actions(self):
|
def define_actions(self):
|
||||||
"""
|
"""
|
||||||
Define actions for the popup menu specific to the tree view.
|
This defines the possible actions for the citation views.
|
||||||
|
Possible actions are:
|
||||||
|
add_source: Add a new source (this is also available from the
|
||||||
|
source view)
|
||||||
|
add: Add a new citation and a new source (this can also be done
|
||||||
|
by source view add a source, then citation view add a new
|
||||||
|
citation to an existing source)
|
||||||
|
share: Add a new citation to an existing source (when a source is
|
||||||
|
selected)
|
||||||
|
edit: Edit a source or a citation.
|
||||||
|
merge: Merge the selected sources or citations.
|
||||||
|
remove: Delete the selected sources or citations.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
BaseCitationView.define_actions(self)
|
ListView.define_actions(self)
|
||||||
|
|
||||||
|
self._add_action('Add source', 'gramps-source', _("Add source..."),
|
||||||
|
accel=None,
|
||||||
|
tip=self.ADD_SOURCE_MSG,
|
||||||
|
callback=self.add_source)
|
||||||
|
self._add_action('Add citation', 'gramps-citation',
|
||||||
|
_("Add citation..."),
|
||||||
|
accel=None,
|
||||||
|
tip=self.ADD_CITATION_MSG,
|
||||||
|
callback=self.share)
|
||||||
|
|
||||||
|
self.all_action = gtk.ActionGroup(self.title + "/CitationAll")
|
||||||
|
self.edit_action = gtk.ActionGroup(self.title + "/CitationEdit")
|
||||||
|
|
||||||
|
self._add_action('FilterEdit', None, _('Citation Filter Editor'),
|
||||||
|
callback=self.filter_editor,)
|
||||||
|
self._add_action('QuickReport', None, _("Quick View"), None, None, None)
|
||||||
|
self._add_action('Dummy', None, ' ', None, None, self.dummy_report)
|
||||||
|
|
||||||
|
self._add_action_group(self.edit_action)
|
||||||
|
self._add_action_group(self.all_action)
|
||||||
|
|
||||||
self.all_action.add_actions([
|
self.all_action.add_actions([
|
||||||
('OpenAllNodes', None, _("Expand all Nodes"), None, None,
|
('OpenAllNodes', None, _("Expand all Nodes"), None, None,
|
||||||
@ -206,3 +280,228 @@ class CitationTreeView(BaseCitationView):
|
|||||||
</popup>
|
</popup>
|
||||||
</ui>'''
|
</ui>'''
|
||||||
|
|
||||||
|
def dummy_report(self, obj):
|
||||||
|
""" For the xml UI definition of popup to work, the submenu
|
||||||
|
Quick Report must have an entry in the xml
|
||||||
|
As this submenu will be dynamically built, we offer a dummy action
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add_source(self, obj):
|
||||||
|
"""
|
||||||
|
add_source: Add a new source (this is also available from the
|
||||||
|
source view)
|
||||||
|
|
||||||
|
Create a new Source instance and call the EditSource editor with the
|
||||||
|
new source.
|
||||||
|
|
||||||
|
Called when the Add_source button is clicked.
|
||||||
|
If the window already exists (Errors.WindowActiveError), we ignore it.
|
||||||
|
This prevents the dialog from coming up twice on the same object.
|
||||||
|
|
||||||
|
However, since the window is identified by the Source object, and
|
||||||
|
we have just created a new one, it seems to be impossible for the
|
||||||
|
window to already exist, so this is just an extra safety measure.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
EditSource(self.dbstate, self.uistate, [], gen.lib.Source())
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add(self, obj):
|
||||||
|
"""
|
||||||
|
add: Add a new citation and a new source (this can also be done
|
||||||
|
by source view add a source, then citation view add a new
|
||||||
|
citation to an existing source)
|
||||||
|
|
||||||
|
Create a new Source instance and Citation instance and call the
|
||||||
|
EditSource editor with the new source.
|
||||||
|
|
||||||
|
Called when the Add button is clicked.
|
||||||
|
If the window already exists (Errors.WindowActiveError), we ignore it.
|
||||||
|
This prevents the dialog from coming up twice on the same object.
|
||||||
|
|
||||||
|
However, since the window is identified by the Source object, and
|
||||||
|
we have just created a new one, it seems to be impossible for the
|
||||||
|
window to already exist, so this is just an extra safety measure.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
EditCitation(self.dbstate, self.uistate, [], gen.lib.Citation(),
|
||||||
|
gen.lib.Source())
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def share(self, obj):
|
||||||
|
"""
|
||||||
|
share: Add a new citation to an existing source (when a source is
|
||||||
|
selected)
|
||||||
|
"""
|
||||||
|
for handle in self.selected_handles():
|
||||||
|
# The handle will either be a Source handle or a Citation handle
|
||||||
|
source = self.dbstate.db.get_source_from_handle(handle)
|
||||||
|
citation = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
|
if (not source and not citation) or (source and citation):
|
||||||
|
raise ValueError("selection must be either source or citation")
|
||||||
|
if source:
|
||||||
|
try:
|
||||||
|
EditCitation(self.dbstate, self.uistate, [],
|
||||||
|
gen.lib.Citation(), source)
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
from QuestionDialog import WarningDialog
|
||||||
|
WarningDialog(_("Cannot share this reference"),
|
||||||
|
self.__blocked_text())
|
||||||
|
else:
|
||||||
|
msg = _("Cannot add citation.")
|
||||||
|
msg2 = _("In order to add a citation to an existing source, "
|
||||||
|
" you must select a source.")
|
||||||
|
ErrorDialog(msg, msg2)
|
||||||
|
#
|
||||||
|
def remove(self, obj):
|
||||||
|
self.remove_selected_objects()
|
||||||
|
|
||||||
|
def remove_object_from_handle(self, handle):
|
||||||
|
# The handle will either be a Source handle or a Citation handle
|
||||||
|
source = self.dbstate.db.get_source_from_handle(handle)
|
||||||
|
citation = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
|
if (not source and not citation) or (source and citation):
|
||||||
|
raise ValueError("selection must be either source or citation")
|
||||||
|
if citation:
|
||||||
|
the_lists = Utils.get_citation_referents(handle, self.dbstate.db)
|
||||||
|
object = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
|
query = DeleteCitationQuery(self.dbstate, self.uistate, object,
|
||||||
|
the_lists)
|
||||||
|
is_used = any(the_lists)
|
||||||
|
return (query, is_used, object)
|
||||||
|
else:
|
||||||
|
# FIXME: this is copied from SourceView, because import with
|
||||||
|
# from plugins.view.sourceview import SourceView
|
||||||
|
# doesn't seem to work!
|
||||||
|
the_lists = Utils.get_source_referents(handle, self.dbstate.db)
|
||||||
|
LOG.debug('source referents %s' % [the_lists])
|
||||||
|
citation_referents_list = []
|
||||||
|
for citation in the_lists[7]:
|
||||||
|
LOG.debug('citation %s' % citation)
|
||||||
|
refs = Utils.get_citation_referents(citation, self.dbstate.db)
|
||||||
|
citation_referents_list += [(citation, refs)]
|
||||||
|
LOG.debug('citation_referents_list %s' % [citation_referents_list])
|
||||||
|
|
||||||
|
(person_list, family_list, event_list, place_list, source_list,
|
||||||
|
media_list, repo_list, citation_list) = the_lists
|
||||||
|
the_lists = (person_list, family_list, event_list, place_list,
|
||||||
|
source_list, media_list, repo_list, citation_list,
|
||||||
|
citation_referents_list)
|
||||||
|
|
||||||
|
LOG.debug('the_lists %s' % [the_lists])
|
||||||
|
|
||||||
|
object = self.dbstate.db.get_source_from_handle(handle)
|
||||||
|
query = DeleteSrcQuery(self.dbstate, self.uistate, object,
|
||||||
|
the_lists)
|
||||||
|
is_used = any(the_lists)
|
||||||
|
return (query, is_used, object)
|
||||||
|
|
||||||
|
def edit(self, obj):
|
||||||
|
"""
|
||||||
|
Edit either a Source or a Citation, depending on user selection
|
||||||
|
"""
|
||||||
|
for handle in self.selected_handles():
|
||||||
|
# The handle will either be a Source handle or a Citation handle
|
||||||
|
source = self.dbstate.db.get_source_from_handle(handle)
|
||||||
|
citation = self.dbstate.db.get_citation_from_handle(handle)
|
||||||
|
if (not source and not citation) or (source and citation):
|
||||||
|
raise ValueError("selection must be either source or citation")
|
||||||
|
if citation:
|
||||||
|
try:
|
||||||
|
EditCitation(self.dbstate, self.uistate, [], citation)
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
pass
|
||||||
|
else: # FIXME need try block here
|
||||||
|
try:
|
||||||
|
EditSource(self.dbstate, self.uistate, [], source)
|
||||||
|
except Errors.WindowActiveError:
|
||||||
|
from QuestionDialog import WarningDialog
|
||||||
|
WarningDialog(_("Cannot share this reference"),
|
||||||
|
self.__blocked_text2())
|
||||||
|
|
||||||
|
def __blocked_text(self):
|
||||||
|
"""
|
||||||
|
Return the common text used when citation cannot be edited
|
||||||
|
"""
|
||||||
|
return _("This citation cannot be created at this time. "
|
||||||
|
"Either the associated Source object is already being "
|
||||||
|
"edited, or another citation associated with the same "
|
||||||
|
"source is being edited.\n\nTo edit this "
|
||||||
|
"citation, you need to close the object.")
|
||||||
|
|
||||||
|
def __blocked_text2(self):
|
||||||
|
"""
|
||||||
|
Return the common text used when citation cannot be edited
|
||||||
|
"""
|
||||||
|
return _("This source cannot be edited at this time. "
|
||||||
|
"Either the associated Source object is already being "
|
||||||
|
"edited, or another citation associated with the same "
|
||||||
|
"source is being edited.\n\nTo edit this "
|
||||||
|
"source, you need to close the object.")
|
||||||
|
|
||||||
|
def merge(self, obj):
|
||||||
|
"""
|
||||||
|
Merge the selected citations.
|
||||||
|
"""
|
||||||
|
mlist = self.selected_handles()
|
||||||
|
|
||||||
|
if len(mlist) != 2:
|
||||||
|
msg = _("Cannot merge citations.")
|
||||||
|
msg2 = _("Exactly two citations must be selected to perform a "
|
||||||
|
"merge. A second citation can be selected by holding "
|
||||||
|
"down the control key while clicking on the desired "
|
||||||
|
"citation.")
|
||||||
|
ErrorDialog(msg, msg2)
|
||||||
|
else:
|
||||||
|
source1 = self.dbstate.db.get_source_from_handle(mlist[0])
|
||||||
|
citation1 = self.dbstate.db.get_citation_from_handle(mlist[0])
|
||||||
|
if (not source1 and not citation1) or (source1 and citation1):
|
||||||
|
raise ValueError("selection must be either source or citation")
|
||||||
|
|
||||||
|
source2 = self.dbstate.db.get_source_from_handle(mlist[1])
|
||||||
|
citation2 = self.dbstate.db.get_citation_from_handle(mlist[1])
|
||||||
|
if (not source2 and not citation2) or (source2 and citation2):
|
||||||
|
raise ValueError("selection must be either source or citation")
|
||||||
|
|
||||||
|
if citation1 and citation2:
|
||||||
|
if not citation1.get_reference_handle() == \
|
||||||
|
citation2.get_reference_handle():
|
||||||
|
msg = _("Cannot merge citations.")
|
||||||
|
msg2 = _("The two selected citations must have the same "
|
||||||
|
"source to perform a merge. If you want to merge "
|
||||||
|
"these two citations, then you must merge the "
|
||||||
|
"sources first.")
|
||||||
|
ErrorDialog(msg, msg2)
|
||||||
|
else:
|
||||||
|
import Merge
|
||||||
|
Merge.MergeCitations(self.dbstate, self.uistate,
|
||||||
|
mlist[0], mlist[1])
|
||||||
|
elif source1 and source2:
|
||||||
|
import Merge
|
||||||
|
Merge.MergeSources(self.dbstate, self.uistate,
|
||||||
|
mlist[0], mlist[1])
|
||||||
|
else:
|
||||||
|
msg = _("Cannot perform merge.")
|
||||||
|
msg2 = _("Both objects must be of the same type, either "
|
||||||
|
"both must be sources, or both must be "
|
||||||
|
"citations.")
|
||||||
|
ErrorDialog(msg, msg2)
|
||||||
|
|
||||||
|
def get_handle_from_gramps_id(self, gid):
|
||||||
|
obj = self.dbstate.db.get_citation_from_gramps_id(gid)
|
||||||
|
if obj:
|
||||||
|
return obj.get_handle()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_default_gramplets(self):
|
||||||
|
"""
|
||||||
|
Define the default gramplets for the sidebar and bottombar.
|
||||||
|
"""
|
||||||
|
return (("Source Filter",),
|
||||||
|
("Citation Gallery",
|
||||||
|
"Citation Notes",
|
||||||
|
"Citation Backlinks"))
|
||||||
|
@ -197,20 +197,21 @@ viewclass = 'RepositoryView',
|
|||||||
order = START,
|
order = START,
|
||||||
)
|
)
|
||||||
|
|
||||||
register(VIEW,
|
# FIXME: REDUNDANT As of gramps 3.4, sourceview.py is redundant.
|
||||||
id = 'sourceview',
|
#register(VIEW,
|
||||||
name = _("Source View"),
|
#id = 'sourceview',
|
||||||
description = _("The view showing all the sources"),
|
#name = _("Source View"),
|
||||||
version = '1.0',
|
#description = _("The view showing all the sources"),
|
||||||
gramps_target_version = '3.4',
|
#version = '1.0',
|
||||||
status = STABLE,
|
#gramps_target_version = '3.4',
|
||||||
fname = 'sourceview.py',
|
#status = STABLE,
|
||||||
authors = [u"The Gramps project"],
|
#fname = 'sourceview.py',
|
||||||
authors_email = ["http://gramps-project.org"],
|
#authors = [u"The Gramps project"],
|
||||||
category = ("Sources", _("Sources")),
|
#authors_email = ["http://gramps-project.org"],
|
||||||
viewclass = 'SourceView',
|
#category = ("Sources", _("Sources")),
|
||||||
order = START,
|
#viewclass = 'SourceView',
|
||||||
)
|
#order = START,
|
||||||
|
# )
|
||||||
|
|
||||||
register(VIEW,
|
register(VIEW,
|
||||||
id = 'citationlistview',
|
id = 'citationlistview',
|
||||||
@ -237,8 +238,7 @@ status = STABLE,
|
|||||||
fname = 'citationtreeview.py',
|
fname = 'citationtreeview.py',
|
||||||
authors = [u"Tim G L Lyons", u"Nick Hall"],
|
authors = [u"Tim G L Lyons", u"Nick Hall"],
|
||||||
authors_email = [""],
|
authors_email = [""],
|
||||||
category = ("Citations", _("Citations")),
|
category = ("Sources", _("Sources")),
|
||||||
viewclass = 'CitationTreeView',
|
viewclass = 'CitationTreeView',
|
||||||
stock_icon = 'gramps-tree-group',
|
|
||||||
order = START,
|
order = START,
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user