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