Δημοσιεύτηκε: 28 Ιούλ 2009, 19:46
από cyberpython
Μία μικρή εφαρμογή για το κατέβασμα wallpapers από το gnome-look.org.

Κώδικας:

Κώδικας:
Spoiler: show
Αρχείο wallpapers.py
Αρχείο wallpapers.glade:
- Κώδικας: Επιλογή όλων
#!/usr/bin/env python
#import sys
import pygtk
pygtk.require("2.0")
import gtk
import gobject # used by ProgressCellRenderer
import gtk.glade
import gconf #in order to set the wallpaper
import urllib2 #to download things
import threading #for freeze-less downloading and gui stuff
import mimetypes #to determine to what exactly a url points at
import os.path #file name handling
import webbrowser #to open files that are not images
import xml.dom.minidom #to manipulate the files obtained using gnome-look.org's REST API
from xml.dom.minidom import Node # to manipulate the files obtained using gnome-look.org's REST API
#--------------------------------------------------------------------------------------------------
# Class GnomeLookApiForWallpapers
#--------------------------------------------------------------------------------------------------
class GnomeLookApiForWallpapers:
#API_KEY = ""
API_KEY_BASE_64 = ""
available_sort_by_methods = [("date added","new"),("alphabetical order","alpha"),("highest rating","high"),("most downloads","down")]
def __init__(self):
self.categories = []
self.sort_by_method = ""
self.available_categories = []
self.fetch_categories()
def get_sort_by_methods(self):
return GnomeLookApiForWallpapers.available_sort_by_methods
def get_categories(self):
return self.categories
def fetch_categories(self):
theurl = "http://api.gnome-look.org/v1/content/categories"
categories_xml_file = self.download_file(theurl)
doc = xml.dom.minidom.parse(categories_xml_file)
self.categories=[]
for node in doc.getElementsByTagName("category"):
if(node.hasChildNodes()):
category_id = ""
category_name = ""
category_id = node.childNodes[1].childNodes[0].data
category_name = node.childNodes[3].childNodes[0].data
if(category_name.startswith("GNOME Wallpaper")):
self.categories.append( (category_id,category_name) )
def get_wallpapers_list(self, categories, sortmode, pagesize, pagenumber):
theurl = "http://api.gnome-look.org/v1/content/data?categories="+categories+"&sortmode="+sortmode+"&page="+pagenumber+"&pagesize="+pagesize
wallpapers_xml_file = self.download_file(theurl)
doc = xml.dom.minidom.parse(wallpapers_xml_file)
wallpapers = []
for node in doc.getElementsByTagName("content"):
if(node.hasChildNodes()):
nodes = node.childNodes
if(len(nodes) >= 30):
content_id = ""
wallpaper_name = ""
wallpaper_type = ""
wallpaper_thumb_url = ""
content_id = node.childNodes[1].childNodes[0].data
wallpaper_name = node.childNodes[3].childNodes[0].data
wallpaper_type = node.childNodes[13].childNodes[0].data
if(node.childNodes[29].hasChildNodes()):
wallpaper_thumb_url = node.childNodes[29].childNodes[0].data
wallpapers.append( (content_id, wallpaper_name, wallpaper_type, wallpaper_thumb_url) )
return wallpapers
def get_download_url(self, content_id):
theurl = "http://api.gnome-look.org/v1/content/download/"+content_id+"/1"
response = self.download_file(theurl)
doc = xml.dom.minidom.parse(response)
nodes = doc.getElementsByTagName("downloadlink")
link = nodes[0].childNodes[0].data
return link
def download_file(self, url):
req = urllib2.Request(url)
req.add_header("Authorization", "Basic "+GnomeLookApiForWallpapers.API_KEY_BASE_64)
return urllib2.urlopen(req)
#--------------------------------------------------------------------------------------------------
# End of class GnomeLookApiForWallpapers
#--------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------
# Class ThumbnailDownloader
#--------------------------------------------------------------------------------------------------
class ThumbnailDownloader(threading.Thread):
def __init__(self, progressbar, liststore, glwd, categories, sortmode, pagesize, pagenumber):
self.stopthread = threading.Event()
self.liststore = liststore
self.glwd = glwd
self.categories = categories
self.sortmode = sortmode
self.pagesize = pagesize
self.pagenumber = pagenumber
self.progressbar = progressbar
threading.Thread.__init__(self)
def run(self):
self.wallpapers_list = self.glwd.get_wallpapers_list(self.categories, self.sortmode, self.pagesize, self.pagenumber)
self.progressbar.set_fraction(0.0)
length = len(self.wallpapers_list)
i = 0
while (i<length) and (not self.stopthread.isSet()) :
wallpaper = self.wallpapers_list[i]
try:
tmp_file = urllib2.urlopen(wallpaper[3])
pixbuf_loader = gtk.gdk.PixbufLoader()
pixbuf_loader.write(tmp_file.read())
pixbuf = pixbuf_loader.get_pixbuf()
pixbuf_loader.close()
tooltip = "Name: "+wallpaper[1]+" \nType: "+wallpaper[2]
gtk.gdk.threads_enter()
self.liststore.append([wallpaper[0], wallpaper[1], tooltip, pixbuf])
gtk.gdk.threads_leave()
except:
pass
gtk.gdk.threads_enter()
self.progressbar.set_fraction(float(i)/float(length))
gtk.gdk.threads_leave()
i = i+1
self.progressbar.set_fraction(0.0)
def stop(self):
self.stopthread.set()
#--------------------------------------------------------------------------------------------------
# End of class ThumbnailDownloader
#--------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------
# Class DownloadHandler
#--------------------------------------------------------------------------------------------------
class DownloadHandler(threading.Thread):
def __init__(self, listview_model, filename, url, target_name):
self.listview_model = listview_model
self.url = url
self.download_filename = filename
self.target_name = target_name
threading.Thread.__init__(self)
def run(self):
STEP = 64
listview_item = [self.target_name, 0, self.url, self.download_filename]
gtk.gdk.threads_enter()
listview_item_iter = self.listview_model.append(listview_item)
gtk.gdk.threads_leave()
tmp_file = urllib2.urlopen(self.url)
file_size = int(tmp_file.info().getheaders("Content-Length")[0])
output = open(self.download_filename,'wb')
total = 0
bytes_read = tmp_file.read(STEP)
while (bytes_read != ""):
total = total + STEP
output.write(bytes_read)
bytes_read = tmp_file.read(STEP)
progress = min(100, int((float(total) / float(file_size))*100) )
gtk.gdk.threads_enter()
self.listview_model.set_value(listview_item_iter, 1, int(progress))
gtk.gdk.threads_leave()
output.close()
gtk.gdk.threads_enter()
self.listview_model.set_value(listview_item_iter, 1, 100)
gtk.gdk.threads_leave()
#--------------------------------------------------------------------------------------------------
# End of class DownloadHandler
#--------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------
# Class MainApp
#--------------------------------------------------------------------------------------------------
class MainApp:
GLADE_FILE = "wallpapers.glade"
COL_ID = 0
COL_NAME = 1
COL_TOOLTIP = 2
COL_PIXBUF = 3
APP_NAME = "Wallpapers Today"
APP_VERSION = "1.0"
APP_COPYRIGHT = "Copyright (c) 2009, Georgios Migdos"
APP_LICENSE = '''Copyright (c) 2009, Georgios Migdos
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the names of the authors nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'''
APP_AUTHORS = ["Georgios \"cyberpython\" Migdos <cyberpython@gmail.com>"]
def __init__(self):
self.glwd = GnomeLookApiForWallpapers()
self.thumbs_dloader = None
self.create_gui()
self.populate_wallpaper_type_combo(self.combo1, self.glwd)
self.populate_sort_by_combo(self.combo2, self.glwd)
#self.update_iconview_model()
def create_gui(self):
self.gladefile = MainApp.GLADE_FILE
self.wTree = gtk.glade.XML(self.gladefile)
self.window = self.wTree.get_widget("window1")
self.window.set_title(MainApp.APP_NAME)
self.vbox5 = self.wTree.get_widget("vbox5")
self.combo1 = gtk.combo_box_new_text()
self.vbox5.pack_start(self.combo1, True, True, 0)
self.vbox6 = self.wTree.get_widget("vbox6")
self.combo2 = gtk.combo_box_new_text()
self.vbox6.pack_start(self.combo2, True, True, 0)
self.listview_model = self.create_listview_model()
self.listview = gtk.TreeView(self.listview_model)
self.create_listview_columns(self.listview)
self.listview.set_rules_hint(True)
self.listview.get_selection().set_mode(gtk.SELECTION_SINGLE)
self.scrolled_window2 = self.wTree.get_widget("scrolledwindow2")
self.scrolled_window2.add(self.listview)
self.iconview_model = self.create_iconview_model()
self.iconview = gtk.IconView(self.iconview_model)
self.iconview.set_selection_mode(gtk.SELECTION_MULTIPLE)
self.iconview.set_text_column(-1)
self.iconview.set_pixbuf_column(MainApp.COL_PIXBUF)
self.iconview.set_tooltip_column(MainApp.COL_TOOLTIP)
self.scrolled_window1 = self.wTree.get_widget("scrolledwindow1")
self.scrolled_window1.add(self.iconview)
self.spin1 = self.wTree.get_widget("spinbutton1")
self.progressbar1 = self.wTree.get_widget("progressbar1")
self.expander1 = self.wTree.get_widget("expander1")
self.filechooser_button = self.wTree.get_widget("filechooserbutton2")
self.about_button = self.wTree.get_widget("button1")
self.close_button = self.wTree.get_widget("button2")
self.refresh_button = self.wTree.get_widget("button3")
self.save_button = self.wTree.get_widget("button4")
self.set_wallpaper_button = self.wTree.get_widget("button5")
self.clear_completed_button = self.wTree.get_widget("button6")
self.set_wallpaper_button.set_sensitive(False)
#GUI events:
self.about_button.connect("clicked", self.on_about_button_clicked)
self.close_button.connect("clicked", self.on_close_button_clicked)
self.refresh_button.connect("clicked", self.on_refresh_button_clicked)
self.save_button.connect("clicked", self.on_save_button_clicked)
self.set_wallpaper_button.connect("clicked", self.on_set_wallpaper_button_clicked)
self.clear_completed_button.connect("clicked", self.on_clear_completed_button_clicked)
self.listview.connect("cursor-changed", self.on_listview_cursor_changed)
treemodel = self.listview.get_model()
treemodel.connect("row-changed", self.on_listview_row_changed)
treemodel.connect("row-deleted", self.on_listview_row_deleted)
treemodel.connect("row-inserted", self.on_listview_row_inserted)
treemodel.connect("rows-reordered", self.on_listview_rows_reordered)
self.window.show_all()
if (self.window):
self.window.connect("destroy", self.main_quit)
def main_quit(self, obj):
gtk.gdk.threads_leave()
if(not (self.thumbs_dloader is None)):
self.thumbs_dloader.stop()
self.thumbs_dloader.join()
gtk.main_quit(self)
def populate_sort_by_combo(self, combo, glwd):
sort_by_methods = glwd.get_sort_by_methods()
if len(sort_by_methods)>0:
for item in sort_by_methods:
combo.append_text(item[0])
combo.set_active(0)
def populate_wallpaper_type_combo(self, combo, glwd):
categories = glwd.get_categories()
if len(categories)>0:
for item in categories:
combo.append_text(item[1])
combo.set_active(0)
def create_listview_model(self):
listview_model = gtk.ListStore(str, int, str, str)
return listview_model
def create_listview_columns(self, listview):
rendererText = gtk.CellRendererText()
column = gtk.TreeViewColumn("Name", rendererText, text=0)
column.set_sort_column_id(0)
column.set_resizable(True)
listview.append_column(column)
rendererProgress = ProgressCellRenderer()
column = gtk.TreeViewColumn("Progress", rendererProgress, percent=1)
column.set_sort_column_id(1)
column.set_resizable(True)
listview.append_column(column)
rendererText = gtk.CellRendererText()
column = gtk.TreeViewColumn("Url", rendererText, text=2)
column.set_sort_column_id(2)
column.set_resizable(True)
listview.append_column(column)
def remove_completed_from_listview_model(self):
item_iter = self.listview_model.get_iter_root()
while(item_iter!=None):
if(self.listview_model.iter_is_valid(item_iter)):
progress = self.listview_model.get_value(item_iter, 1)
if(progress == 100):
self.listview_model.remove(item_iter)
else:
item_iter = self.listview_model.get_iter_next(item_iter)
else:
item_iter = None
def on_listview_cursor_changed(self, widget):
self.update_set_wallpaper_button_state()
def on_listview_row_deleted(self, treemodel, path):
self.update_set_wallpaper_button_state()
def on_listview_row_changed(self, treemodel, path, iterator):
self.update_set_wallpaper_button_state()
def on_listview_row_inserted(self, treemodel, path, iterator):
self.update_set_wallpaper_button_state()
def on_listview_rows_reordered(self, treemodel, path, iterator, new_order):
self.update_set_wallpaper_button_state()
def update_set_wallpaper_button_state(self):
selection = self.listview.get_selection().get_selected()
if selection[1]!=None : #an item is selected
progress = selection[0].get_value(selection[1], 1)
if(progress == 100):
self.set_wallpaper_button.set_sensitive(True)
else:
self.set_wallpaper_button.set_sensitive(False)
else:
self.set_wallpaper_button.set_sensitive(False)
def create_iconview_model(self):
iconview_model = gtk.ListStore(str, str, str, gtk.gdk.Pixbuf)
return iconview_model
def fill_iconview_model(self, categories, sortmode, pagesize, pagenumber):
if(not (self.thumbs_dloader is None)):
self.thumbs_dloader.stop()
self.thumbs_dloader = ThumbnailDownloader(self.progressbar1, self.iconview_model, self.glwd, categories, sortmode, pagesize, pagenumber)
self.iconview_model.clear()
self.thumbs_dloader.start()
def update_iconview_model(self):
category = self.glwd.get_categories()[self.combo1.get_active()][0]
sortmode = self.glwd.get_sort_by_methods()[self.combo2.get_active()][1]
pagesize = str(self.spin1.get_value_as_int())
pagenumber = "0"
self.fill_iconview_model(category, sortmode, pagesize, pagenumber)
def set_as_wallpaper(self):
selection = self.listview.get_selection().get_selected()
if selection[1]!=None : #an item is selected
filename = selection[0].get_value(selection[1], 3)
client = gconf.client_get_default ()
client.set_string ("/desktop/gnome/background/picture_filename", filename)
def download_selected(self):
selected = self.iconview.get_selected_items()
self.expander1.set_expanded(True)
for path in selected :
result = None
content_id = self.iconview_model.get_value(self.iconview_model.get_iter(path), MainApp.COL_ID)
wallpaper_name = self.iconview_model.get_value(self.iconview_model.get_iter(path), MainApp.COL_NAME)
download_url = self.glwd.get_download_url(content_id)
mimetype = mimetypes.guess_type(download_url)
if(mimetype[0] != None):
extension = mimetypes.guess_extension(mimetype[0])
if(mimetype[0].startswith("image")):
target_file = wallpaper_name + extension
target_file = str.replace(target_file,"/","-")
target_file = str.replace(target_file,"\\","-")
download_filename = self.save_file_quick(target_file)
if(download_filename != None):
try:
tmp_file = urllib2.urlopen(download_url)
dh = DownloadHandler(self.listview_model, download_filename, download_url, target_file)
dh.start()
result = download_filename
except urllib2.URLError as error:
self.show_http_error(download_url, error)
else:
self.show_unknown_mimetype_dialog(download_url)
else:
self.show_unknown_mimetype_dialog(download_url)
return result
def save_file(self, target_name):
filename = self.show_save_dialog(target_name)
overwrite = False
while( (filename!=None) and os.path.exists(filename) and (not overwrite) ):
if(self.overwrite_file(filename)):
overwrite = True
else:
filename = self.show_save_dialog(target_name)
return filename
def save_file_quick(self, target_name):
filename = os.path.join(self.filechooser_button.get_filename(), target_name)
if(os.path.exists(filename)):
if(not self.overwrite_file(filename)):
return self.save_file(target_name)
return filename
#GUI Events:
def on_refresh_button_clicked(self, widget):
self.update_iconview_model()
def on_close_button_clicked(self, widget):
self.main_quit(widget)
def on_about_button_clicked(self, widget):
self.show_about_dialog()
def on_save_button_clicked(self, widget):
self.download_selected()
def on_set_wallpaper_button_clicked(self, widget):
self.set_as_wallpaper()
def on_clear_completed_button_clicked(self, widget):
self.remove_completed_from_listview_model()
#Dialogs stuff:
def show_save_dialog(self, current):
dialog = gtk.FileChooserDialog("Save..", self.window, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK))
dialog.set_default_response(gtk.RESPONSE_OK)
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
dialog.add_filter(filter)
filter = gtk.FileFilter()
filter.set_name("Images")
filter.add_mime_type("image/png")
filter.add_mime_type("image/jpeg")
filter.add_mime_type("image/gif")
filter.add_pattern("*.png")
filter.add_pattern("*.jpg")
filter.add_pattern("*.gif")
filter.add_pattern("*.tif")
filter.add_pattern("*.xpm")
dialog.add_filter(filter)
dialog.set_current_name(current)
response = dialog.run()
if response == gtk.RESPONSE_OK:
result = dialog.get_filename()
elif response == gtk.RESPONSE_CANCEL:
result = None
dialog.destroy()
return result
def overwrite_file(self, filename):
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, "The file: \n\n"+filename+"\n\nalready exists. Overwrite?")
response = dialog.run()
dialog.destroy()
if response == gtk.RESPONSE_YES:
return True
elif response == gtk.RESPONSE_NO:
return False
def show_unknown_mimetype_dialog(self, url):
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_YES_NO, None)
markup = "The url: \n\n<b>"+url+"</b>\n\ndoes not seem to point to a valid wallpaper image. Do you want to try to access it using your web browser?"
dialog.set_markup(markup)
response = dialog.run()
if response == gtk.RESPONSE_YES:
webbrowser.open(url)
dialog.destroy()
def show_http_error(self, url, error):
dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, None)
markup = "The following error occucred while thying to access \n"+url+" :\n\n<b>"+ str(error)+"</b>"
dialog.set_markup(markup)
response = dialog.run()
if response == gtk.RESPONSE_CLOSE:
dialog.destroy()
def show_about_dialog(self):
dialog = gtk.AboutDialog()
dialog.set_name(MainApp.APP_NAME)
dialog.set_version(MainApp.APP_VERSION)
dialog.set_copyright(MainApp.APP_COPYRIGHT)
dialog.set_license(MainApp.APP_LICENSE)
dialog.set_wrap_license(True)
dialog.set_authors(MainApp.APP_AUTHORS)
response = dialog.run()
dialog.destroy()
#------------------------------------------------------------------------------
# Class ProgressCellRenderer
# by: GustavoNiemeyer
# from: http://labix.org/snippets/progress-cell
#------------------------------------------------------------------------------
class ProgressCellRenderer(gtk.GenericCellRenderer):
__gproperties__ = {
"percent": (gobject.TYPE_INT, "Percent", "Progress percentage", 0, 100, 0, gobject.PARAM_READWRITE),}
def __init__(self):
self.__gobject_init__()
self.percent = 0
def do_set_property(self, pspec, value):
setattr(self, pspec.name, value)
def do_get_property(self, pspec):
return getattr(self, pspec.name)
def on_render(self, window, widget, background_area,
cell_area, expose_area, flags):
x_offset, y_offset, width, height = self.on_get_size(widget, cell_area)
widget.style.paint_box(window, gtk.STATE_NORMAL, gtk.SHADOW_IN,
None, widget, "trough",
cell_area.x+x_offset, cell_area.y+y_offset,
width, height)
xt = widget.style.xthickness
xpad = self.get_property("xpad")
space = (width-2*xt-2*xpad)*(self.percent/100.)
widget.style.paint_box(window, gtk.STATE_PRELIGHT, gtk.SHADOW_OUT,
None, widget, "bar",
cell_area.x+x_offset+xt,
cell_area.y+y_offset+xt,
int(space), height-2*xt)
def on_get_size(self, widget, cell_area):
xpad = self.get_property("xpad")
ypad = self.get_property("ypad")
if cell_area:
width = cell_area.width
height = cell_area.height
x_offset = xpad
y_offset = ypad
else:
width = self.get_property("width")
height = self.get_property("height")
if width == -1: width = 100
if height == -1: height = 30
width += xpad*2
height += ypad*2
x_offset = 0
y_offset = 0
return x_offset, y_offset, width, height
gobject.type_register(ProgressCellRenderer)
#------------------------------------------------------------------------------
# End of class ProgressCellRenderer
#------------------------------------------------------------------------------
gtk.gdk.threads_init()
hwg = MainApp()
gtk.main()
Αρχείο wallpapers.glade:
- Κώδικας: Επιλογή όλων
<?xml version="1.0"?>
<glade-interface>
<!-- interface-requires gtk+ 2.16 -->
<!-- interface-naming-policy project-wide -->
<widget class="GtkWindow" id="window1">
<property name="width_request">585</property>
<property name="height_request">480</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="border_width">10</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkVBox" id="vbox8">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkProgressBar" id="progressbar1">
<property name="visible">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="vbox5">
<property name="width_request">200</property>
<property name="visible">True</property>
<property name="border_width">4</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Wallpaper type:</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox6">
<property name="width_request">100</property>
<property name="visible">True</property>
<property name="border_width">4</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Sort by:</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="width_request">150</property>
<property name="visible">True</property>
<property name="border_width">4</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Number of wallpapers:</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkSpinButton" id="spinbutton1">
<property name="width_request">20</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">●</property>
<property name="adjustment">50 10 110 1 10 10</property>
<property name="climb_rate">10</property>
<property name="numeric">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button3">
<property name="label" translatable="yes">gtk-refresh</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="padding">5</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<property name="border_width">8</property>
<child>
<widget class="GtkHSeparator" id="hseparator1">
<property name="visible">True</property>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<child>
<widget class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">Save to: </property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkFileChooserButton" id="filechooserbutton2">
<property name="visible">True</property>
<property name="action">select-folder</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkFixed" id="fixed1">
<property name="width_request">30</property>
<property name="visible">True</property>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="spacing">2</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="button4">
<property name="label" translatable="yes">gtk-save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox7">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkExpander" id="expander1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkVBox" id="vbox9">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="height_request">200</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox3">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<widget class="GtkButton" id="button6">
<property name="label" translatable="yes">gtk-clear</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button5">
<property name="label" translatable="yes">Set as wallpaper</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes"><b>Downloads in progress:</b></property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="position">0</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes"><b>Wallpapers::gnome-look.org</b></property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="tab_fill">False</property>
<property name="type">tab</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">5</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">edge</property>
<child>
<widget class="GtkButton" id="button1">
<property name="label" translatable="yes">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button2">
<property name="label" translatable="yes">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>