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:
parent
f528c0d750
commit
2368211ba1
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -26,7 +26,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gettext import gettext as _
|
||||
import pickle
|
||||
import cPickle as pickle
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user