1
'''module to define a class to present a list of thumbnails'''
2
# -*- coding: utf-8 -*-
4
# This file is part of emesene.
6
# emesene 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 3 of the License, or
9
# (at your option) any later version.
11
# emesene 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.
16
# You should have received a copy of the GNU General Public License
17
# along with emesene; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
from gui.gtkui import check_gtk3
29
from gui.base import MarkupParser
31
# Class that holds the iconview from the avatar chooser dialog
32
class IconView(gtk.HBox):
33
''' class representing a listview in icon mode
34
(using gtk.IconView + gtk.ListStore) '''
35
TYPE_SYSTEM_PICS, TYPE_CONTACTS_PICS, TYPE_SELF_PICS = range(3)
36
def __init__(self, label, path_list, on_remove_cb, on_accept_cb,
37
iconv_type, on_drag_data_accepted):
38
gtk.HBox.__init__(self)
41
self.on_remove_cb = on_remove_cb
42
self.on_accept_cb = on_accept_cb
43
self.on_drag_data_accepted = on_drag_data_accepted
44
self.iconv_type = iconv_type
46
self.model = gtk.ListStore(gtk.gdk.Pixbuf, str)
47
self.iconview = gtk.IconView(self.model)
50
target = ('text/uri-list', 0, 0)
52
#FIXME: this is not working in gtk3
53
target = gtk.TargetEntry.new('text/uri-list', 0, 0)
55
self.iconview.enable_model_drag_dest([target],
56
gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY)
57
self.iconview.connect("drag-data-received", self._drag_data_received)
58
self.iconview.set_pixbuf_column(0)
59
self.iconview.connect("item-activated", self._on_icon_activated)
60
self.iconview.connect("button_press_event", self.pop_up)
62
self.label = gtk.Label(label)
64
self.scroll = gtk.ScrolledWindow()
65
self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
66
self.scroll.set_shadow_type(gtk.SHADOW_IN)
67
self.scroll.add(self.iconview)
68
self.pack_start(self.scroll, True, True)
71
# Start a new thread to fill the iconview with images from path_list
72
thread.start_new_thread(self.fill, (path_list,))
74
def stop_and_clear(self):
75
''' stop the threads and clean the model '''
79
def fill(self, path_list):
80
'''fill the IconView with avatars from the list of pictures'''
81
for search_path in path_list:
82
if os.path.exists(search_path):
83
for path in os.listdir(search_path):
84
name = os.path.splitext(path)[0]
87
full_path = os.path.join(search_path, path)
88
if not name.endswith('_thumb') and \
89
not path.endswith(('tmp', 'xml', 'db', 'info',
90
'last', 'avatars')) and \
91
not os.path.isdir(full_path):
92
gtk.gdk.threads_enter()
93
self.add_picture(full_path)
94
# make update the iconview
95
self.iconview.queue_draw()
96
gtk.gdk.threads_leave()
98
# give some time to the main thread (for GUI updates)
100
# Force Garbage Collector to tidy objects
101
# see http://faq.pygtk.org/index.py?req=show&file=faq08.004.htp
104
def pop_up(self, iconview, event):
105
''' manage the context menu (?) '''
106
if event.button == 3 and self.iconv_type != IconView.TYPE_SYSTEM_PICS:
107
path = self.iconview.get_path_at_pos(int(event.x), int(event.y))
109
self.iconview.select_path(path)
111
if self.on_remove_cb != None:
112
remove_menu = gtk.Menu()
113
remove_item = gtk.ImageMenuItem(_('Delete'))
114
remove_item.set_image(gtk.image_new_from_stock(\
115
gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU))
116
remove_item.connect('activate', self.on_remove_cb)
117
remove_menu.append(remove_item)
118
remove_menu.popup(None, None, None, event.button,
120
remove_menu.show_all()
122
def _drag_data_received(self, treeview, context, posx, posy, \
123
selection, info, timestamp):
124
'''method called on an image dragged to the view'''
125
urls = selection.data.split('\n')
127
path = url.replace('file://', '')
128
path = path.replace('\r', '')
130
# the '\x00' value makes an error
131
path = path.replace(chr(0), '')
133
path = MarkupParser.urllib.url2pathname(path)
135
# this seems to be an error on ntpath but we take care :S
137
if os.path.exists(path):
138
self.on_drag_data_accepted(path,
139
gtk.gdk.PixbufAnimation(path).is_static_image())
140
except TypeError, error:
141
if self.on_drag_data_accepted is None:
142
print _("Could not add picture:\n %s") % \
143
_("Drag and drop to this IconView is not allowed.")
145
print _("Could not add picture:\n %s") % (str(error),)
147
def add_picture(self, path):
148
'''Adds an avatar into the IconView'''
150
if os.path.exists(path) and os.access(path, os.R_OK)\
151
and not self.is_in_view(path):
153
animation = gtk.gdk.PixbufAnimation(path)
154
if animation.is_static_image():
155
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
157
pixbuf = animation.get_static_image().scale_simple( \
158
64, 64, gtk.gdk.INTERP_BILINEAR)
159
except gobject.GError:
160
print _('image at %s could not be loaded') % (path, )
164
# On nt images are 128x128 (48x48 on xp)
165
# On kde, images are 64x64
166
if (self.iconv_type == IconView.TYPE_SYSTEM_PICS or \
167
self.iconv_type == IconView.TYPE_CONTACTS_PICS) and \
168
(pixbuf.get_width() != 96 or pixbuf.get_height() != 96):
169
pixbuf = pixbuf.scale_simple(96, 96,
170
gtk.gdk.INTERP_BILINEAR)
172
if self.model != None and not self.stop:
173
self.model.append([pixbuf, path])
174
# Esplicitely delete gtkpixbuf
177
print path, 'not readable'
178
except gobject.GError:
179
print "image at %s could not be loaded" % path
181
def is_in_view(self, filename):
182
'''return True if filename already on the iconview'''
184
# nt doesn't include os.path.samefile
187
for (pixbuf, path) in self.model:
188
if os.path.samefile(filename, path):
195
def _on_icon_activated(self, *args):
196
'''method called when a picture is double clicked'''
197
if self.on_accept_cb != None:
198
self.on_accept_cb(None)
200
def get_selected_items(self):
201
''' gets the selected pictures '''
202
return self.iconview.get_selected_items()