def remove_folder(self):
if self.folder_tree.get_selection() is not None:
self.icon_view.clear()
folder_paths, iter = self.folder_tree.get_selection().get_selected()
if iter:
path = folder_paths[iter][STORE_PATH]
self.collection_store.remove(iter)
for item in self.user_backgrounds:
if item[STORE_PATH] == path:
self.user_backgrounds.remove(item)
self.update_folder_list()
break
def update_folder_list(self):
path = os.path.expanduser("~/.cinnamon/backgrounds")
if not os.path.exists(path):
rec_mkdir(path)
path = os.path.expanduser("~/.cinnamon/backgrounds/user-folders.lst")
if len(self.user_backgrounds) == 0:
file_data = ""
else:
first_path = self.user_backgrounds[0][STORE_PATH]
file_data = first_path + "\n"
for folder in self.user_backgrounds:
if folder[STORE_PATH] == first_path:
continue
else:
file_data += "%s\n" % folder[STORE_PATH]
with open(path, "w") as f:
f.write(file_data)
def update_icon_view(self, path=None, type=None):
if path != self.shown_collection:
self.shown_collection = path
picture_list = []
if os.path.exists(path):
if type == BACKGROUND_COLLECTION_TYPE_DIRECTORY:
files = os.listdir(path)
files.sort()
for i in files:
filename = os.path.join(path, i)
if commands.getoutput("file -bi \"%s\"" % filename).startswith("image/"):
picture_list.append({"filename": filename})
elif type == BACKGROUND_COLLECTION_TYPE_XML:
picture_list += self.parse_xml_backgrounds_list(path)
self.icon_view.set_pictures_list(picture_list, path)
if self._slideshow_schema.get_boolean("slideshow-enabled"):
self.icon_view.set_sensitive(False)
else:
self.icon_view.set_sensitive(True)
def splitLocaleCode(self, localeCode):
loc = localeCode.partition("_")
loc = (loc[0], loc[2])
return loc
def getLocalWallpaperName(self, names, loc):
result = ""
mainLocFound = False
for wp in names:
wpLoc = wp[0]
wpName = wp[1]
if wpLoc == ("", ""):
if not mainLocFound:
result = wpName
elif wpLoc[0] == loc[0]:
if wpLoc[1] == loc[1]:
return wpName
elif wpLoc[1] == "":
result = wpName
mainLocFound = True
return result
def parse_xml_backgrounds_list(self, filename):
try:
locAttrName = "{http://www.w3.org/XML/1998/namespace}lang"
loc = self.splitLocaleCode(locale.getdefaultlocale()[0])
res = []
subLocaleFound = False
f = open(filename)
rootNode = lxml.etree.fromstring(f.read())
f.close()
if rootNode.tag == "wallpapers":
for wallpaperNode in rootNode:
if wallpaperNode.tag == "wallpaper" and wallpaperNode.get("deleted") != "true":
wallpaperData = {"metadataFile": filename}
names = []
for prop in wallpaperNode:
if type(prop.tag) == str:
if prop.tag != "name":
wallpaperData[prop.tag] = prop.text
else:
propAttr = prop.attrib
wpName = prop.text
locName = self.splitLocaleCode(propAttr.get(locAttrName)) if propAttr.has_key(locAttrName) else ("", "")
names.append((locName, wpName))
wallpaperData["name"] = self.getLocalWallpaperName(names, loc)
if "filename" in wallpaperData and wallpaperData["filename"] != "" and os.path.exists(wallpaperData["filename"]) and os.access(wallpaperData["filename"], os.R_OK):
if wallpaperData["name"] == "":
wallpaperData["name"] = os.path.basename(wallpaperData["filename"])
res.append(wallpaperData)
return res
except:
return []
class PixCache(object):
def __init__(self):
self._data = {}
def get_pix(self, filename, size = None):
try:
mimetype = subprocess.check_output(["file", "-bi", filename]).split(";")[0]
if not mimetype.startswith("image/"):
print "Not trying to convert %s : not a recognized image file" % filename
return None
except Exception, detail:
print "Failed to detect mimetype for %s: %s" % (filename, detail)
return None
if not filename in self._data:
self._data[filename] = {}
if size in self._data[filename]:
pix = self._data[filename][size]
else:
try:
if mimetype == "image/svg+xml":
tmp_pix = GdkPixbuf.Pixbuf.new_from_file(filename)
tmp_fp, tmp_filename = tempfile.mkstemp()
os.close(tmp_fp)
tmp_pix.savev(tmp_filename, "png", [], [])
img = Image.open(tmp_filename)
os.unlink(tmp_filename)
else:
img = Image.open(filename)
(width, height) = img.size
if img.mode != 'RGB':
img = img.convert('RGB')
if size:
img.thumbnail((size, size), Image.ANTIALIAS)
img = imtools.round_image(img, {}, False, None, 3, 255)
img = imtools.drop_shadow(img, 4, 4, background_color=(255, 255, 255, 0), shadow_color=0x444444, border=8, shadow_blur=3, force_background_color=False, cache=None)
# Convert Image -> Pixbuf (save to file, GTK3 is not reliable for that)
f = tempfile.NamedTemporaryFile(delete=False)
temp_filename = f.name
f.close()
img.save(temp_filename, "png")
pix = [GdkPixbuf.Pixbuf.new_from_file(temp_filename), width, height]
os.unlink(temp_filename)
except Exception, detail:
print "Failed to convert %s: %s" % (filename, detail)
pix = None
if pix:
self._data[filename][size] = pix
return pix
PIX_CACHE = PixCache()
class ThreadedIconView(Gtk.IconView):
def __init__(self):
Gtk.IconView.__init__(self)
self.set_item_width(BACKGROUND_ICONS_SIZE * 1.1)
self._model = Gtk.ListStore(object, GdkPixbuf.Pixbuf, str, str)
self._model_filter = self._model.filter_new()
self._model_filter.set_visible_func(self.visible_func)
self.set_model(self._model_filter)
area = self.get_area()
self.current_path = None
pixbuf_renderer = Gtk.CellRendererPixbuf()
text_renderer = Gtk.CellRendererText(ellipsize=Pango.EllipsizeMode.END)
text_renderer.set_alignment(.5, .5)
area.pack_start(pixbuf_renderer, True, False, False)
area.pack_start(text_renderer, True, False, False)
self.add_attribute (pixbuf_renderer, "pixbuf", 1)
self.add_attribute (text_renderer, "markup", 2)
text_renderer.set_property("alignment", Pango.Alignment.CENTER)
self._loading_queue = []
self._loading_queue_lock = thread.allocate_lock()
self._loading_lock = thread.allocate_lock()
self._loading = False
self._loaded_data = []
self._loaded_data_lock = thread.allocate_lock()
def visible_func(self, model, iter, data=None):
item_path = model.get_value(iter, 3)
return item_path == self.current_path
def set_pictures_list(self, pictures_list, path = None):
self.clear()
self.current_path = path
for i in pictures_list:
self.add_picture(i, path)
def clear(self):
self._loading_queue_lock.acquire()
self._loading_queue = []
self._loading_queue_lock.release()
self._loading_lock.acquire()
is_loading = self._loading
self._loading_lock.release()
while is_loading:
time.sleep(0.1)
self._loading_lock.acquire()
is_loading = self._loading
self._loading_lock.release()
self._model.clear()
def add_picture(self, picture, path):
self._loading_queue_lock.acquire()
self._loading_queue.append(picture)
self._loading_queue_lock.release()
start_loading = False
self._loading_lock.acquire()
if not self._loading:
self._loading = True
start_loading = True
self._loading_lock.release()
if start_loading:
GLib.timeout_add(100, self._check_loading_progress)
thread.start_new_thread(self._do_load, (path,))
def _check_loading_progress(self):
self._loading_lock.acquire()
self._loaded_data_lock.acquire()
res = self._loading
to_load = []
while len(self._loaded_data) > 0:
to_load.append(self._loaded_data[0])
self._loaded_data = self._loaded_data[1:]
self._loading_lock.release()
self._loaded_data_lock.release()
for i in to_load:
self._model.append(i)
return res
def _do_load(self, path):
finished = False
while not finished:
self._loading_queue_lock.acquire()
if len(self._loading_queue) == 0:
finished = True
else:
to_load = self._loading_queue[0]
self._loading_queue = self._loading_queue[1:]
self._loading_queue_lock.release()
if not finished:
filename = to_load["filename"]
if filename.endswith(".xml"):
filename = self.getFirstFileFromBackgroundXml(filename)
pix = PIX_CACHE.get_pix(filename, BACKGROUND_ICONS_SIZE)
if pix != None:
if "name" in to_load:
label = to_load["name"]
else:
label = os.path.split(to_load["filename"])[1]
if "artist" in to_load:
artist = "%s\n" % to_load["artist"]
else:
artist = ""
dimensions = "%dx%d" % (pix[1], pix[2])
self._loaded_data_lock.acquire()
self._loaded_data.append((to_load, pix[0], "<b>%s</b>\n<sub>%s<span foreground='#555555'>%s</span></sub>" % (label, artist, dimensions), path))
self._loaded_data_lock.release()
self._loading_lock.acquire()
self._loading = False
self._loading_lock.release()
def getFirstFileFromBackgroundXml(self, filename):
try:
f = open(filename)
rootNode = lxml.etree.fromstring(f.read())
f.close()
if rootNode.tag == "background":
for backgroundNode in rootNode:
if backgroundNode.tag == "static":
for staticNode in backgroundNode:
if staticNode.tag == "file":
return staticNode.text
print "Could not find filename in %s" % filename
return None
except Exception, detail:
print "Failed to read filename from %s: %s" % (filename, detail)
return None