2006-08-10 Don Allingham <don@gramps-project.org>

* src/DisplayTabs/_EmbeddedList.py: use cPickle instead of pickle
	* src/DisplayTabs/_GalleryTab.py: add dnd functionality
	* src/DdTargets.py: add URI_LIST and APP_ROOT



svn: r7151
This commit is contained in:
Don Allingham 2006-08-11 03:22:38 +00:00
parent f528c0d750
commit 2368211ba1
4 changed files with 179 additions and 1 deletions

View File

@ -1,3 +1,8 @@
2006-08-10 Don Allingham <don@gramps-project.org>
* src/DisplayTabs/_EmbeddedList.py: use cPickle instead of pickle
* src/DisplayTabs/_GalleryTab.py: add dnd functionality
* src/DdTargets.py: add URI_LIST and APP_ROOT
2006-08-10 Alex Roitman <shura@gramps-project.org>
* src/Filters/SideBar/_PersonSidebarFilter.py (get_filter): Typo.

View File

@ -153,6 +153,8 @@ class _DdTargets(object):
self.STRING = _DdType(self,'STRING', 0, 2)
self.COMPOUND_TEXT = _DdType(self,'COMPOUND_TEXT', 0, 3)
self.UTF8_STRING = _DdType(self,'UTF8_STRING', 0, 4)
self.URI_LIST = _DdType(self,'text/uri-list', 0, 5)
self.APP_ROOT = _DdType(self,'application/x-rootwin-drop', 0, 6)
# List of all the test types. These are types
# that can be interpreted as text.

View File

@ -26,7 +26,7 @@
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import pickle
import cPickle as pickle
#-------------------------------------------------------------------------
#

View File

@ -26,6 +26,8 @@
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import cPickle as pickle
import urlparse
#-------------------------------------------------------------------------
#
@ -33,6 +35,7 @@ from gettext import gettext as _
#
#-------------------------------------------------------------------------
import gtk
import os
#-------------------------------------------------------------------------
#
@ -44,6 +47,8 @@ import Utils
import ImgManip
import Mime
import Errors
import Mime
from DdTargets import DdTargets
from _ButtonTab import ButtonTab
#-------------------------------------------------------------------------
@ -61,10 +66,16 @@ def make_launcher(prog, path):
#-------------------------------------------------------------------------
class GalleryTab(ButtonTab):
_DND_TYPE = DdTargets.MEDIAOBJ
_DND_EXTRA = DdTargets.URI_LIST
def __init__(self, dbstate, uistate, track, media_list, update=None):
ButtonTab.__init__(self, dbstate, uistate, track, _('Gallery'), True)
self.media_list = media_list
self.update = update
self._set_dnd()
self.rebuild()
self.show_all()
@ -257,3 +268,163 @@ class GalleryTab(ButtonTab):
def edit_callback(self, media_ref, ref):
self.changed = True
self.rebuild()
def _set_dnd(self):
"""
Sets up drag-n-drop. The source and destionation are set by calling .target()
on the _DND_TYPE. Obviously, this means that there must be a _DND_TYPE
variable defined that points to an entry in DdTargets.
"""
if self._DND_EXTRA:
dnd_types = [ self._DND_TYPE.target(), self._DND_EXTRA.target() ]
else:
dnd_types = [ self._DND_TYPE.target() ]
self.iconlist.drag_dest_set(gtk.DEST_DEFAULT_ALL, dnd_types,
gtk.gdk.ACTION_COPY)
self.iconlist.drag_source_set(gtk.gdk.BUTTON1_MASK,
[self._DND_TYPE.target()],
gtk.gdk.ACTION_COPY)
self.iconlist.connect('drag_data_get', self.drag_data_get)
self.iconlist.connect('drag_data_received', self.drag_data_received)
def drag_data_get(self, widget, context, sel_data, info, time):
"""
Provide the drag_data_get function, which passes a tuple consisting of:
1) Drag type defined by the .drag_type field specfied by the value
assigned to _DND_TYPE
2) The id value of this object, used for the purpose of determining
the source of the object. If the source of the object is the same
as the object, we are doing a reorder instead of a normal drag
and drop
3) Pickled data. The pickled version of the selected object
4) Source row. Used for a reorder to determine the original position
of the object
"""
# get the selected object, returning if not is defined
obj = self.get_selected()
if not obj:
return
# pickle the data, and build the tuple to be passed
value = (self._DND_TYPE.drag_type, id(self), obj, self.find_index(obj))
data = pickle.dumps(value)
# pass as a string (8 bits)
sel_data.set(sel_data.target, 8, data)
def drag_data_received(self, widget, context, x, y, sel_data, info, time):
"""
Handle the standard gtk interface for drag_data_received.
If the selection data is define, extract the value from sel_data.data,
and decide if this is a move or a reorder.
"""
if sel_data and sel_data.data:
try:
(mytype, selfid, obj, row_from) = pickle.loads(sel_data.data)
# make sure this is the correct DND type for this object
if mytype == self._DND_TYPE.drag_type:
# determine the destination row
data = self.iconlist.get_dest_item_at_pos(x,y)
if data:
(path, pos) = data
row = path[0]
if pos == gtk.ICON_VIEW_DROP_LEFT:
row = max(row, 0)
elif pos == gtk.ICON_VIEW_DROP_RIGHT:
row = min(row, len(self.get_data()))
elif pos == gtk.ICON_VIEW_DROP_INTO:
row = min(row+1, len(self.get_data()))
else:
row = len(self.get_data())
# if the is same object, we have a move, otherwise,
# it is a standard drag-n-drop
if id(self) == selfid:
self._move(row_from, row, obj)
else:
self._handle_drag(row, obj)
self.rebuild()
elif self._DND_EXTRA and mytype == self._DND_EXTRA.drag_type:
self.handle_extra_type(mytype, obj)
except pickle.UnpicklingError:
d = Utils.fix_encoding(sel_data.data.replace('\0',' ').strip())
protocol,site,mfile,j,k,l = urlparse.urlparse(d)
if protocol == "file":
name = Utils.fix_encoding(mfile)
mime = Mime.get_type(name)
if not Mime.is_valid_type(mime):
return
photo = RelLib.MediaObject()
photo.set_path(name)
photo.set_mime_type(mime)
basename = os.path.basename(name)
(root,ext) = os.path.splitext(basename)
photo.set_description(root)
trans = self.dbstate.db.transaction_begin()
self.dbstate.db.add_object(photo, trans)
oref = RelLib.MediaRef()
oref.set_reference_handle(photo.get_handle())
self.get_data().append(oref)
self.changed = True
# self.dataobj.add_media_reference(oref)
self.dbstate.db.transaction_commit(trans,
_("Drag Media Object"))
self.rebuild()
# elif protocol != "":
# import urllib
# u = urllib.URLopener()
# try:
# tfile,headers = u.retrieve(d)
# except (IOError,OSError), msg:
# t = _("Could not import %s") % d
# ErrorDialog(t,str(msg))
# return
# tfile = Utils.fix_encoding(tfile)
# mime = GrampsMime.get_type(tfile)
# photo = RelLib.MediaObject()
# photo.set_mime_type(mime)
# photo.set_description(d)
# photo.set_path(tfile)
# trans = self.db.transaction_begin()
# self.db.add_object(photo,trans)
# self.db.transaction_commit(trans,_("Drag Media Object"))
# oref = RelLib.MediaRef()
# oref.set_reference_handle(photo.get_handle())
# self.dataobj.add_media_reference(oref)
# self.add_thumbnail(oref)
def handle_extra_type(self, objtype, obj):
pass
def _handle_drag(self, row, obj):
self.get_data().insert(row, obj)
self.changed = True
self.rebuild()
def _move(self, row_from, row_to, obj):
dlist = self.get_data()
if row_from < row_to:
dlist.insert(row_to, obj)
del dlist[row_from]
else:
del dlist[row_from]
dlist.insert(row_to-1, obj)
self.changed = True
self.rebuild()
def find_index(self, obj):
"""
returns the index of the object within the associated data
"""
return self.get_data().index(obj)