#!/usr/bin/env python

import gtk
import os
import sys
import subprocess
import time
import signal
import threading
import urllib2
import ConfigParser
import vte
from simpleconfig import SimpleConfig

#Initializing the gtk's thread engine
gtk.gdk.threads_init()

# Internationalization
import locale
import gettext
import gtk.glade
gettext.bindtextdomain("sourcery", "/usr/share/locale")
gettext.textdomain("sourcery")
gettext.install("sourcery", "/usr/share/locale", unicode=1)
gtk.glade.bindtextdomain("sourcery", "/usr/share/locale")
gtk.glade.textdomain("sourcery")

# configuration options
config_file = '/etc/sourcery.conf'
slaptsrcrc = '/etc/slapt-get/slapt-srcrc'
slackbuilds_data = '/usr/src/slapt-src/slackbuilds_data'
logdir = '/var/log/sourcery'
shareddir = '/usr/share/sourcery'

# create a copy of the default environment
initial_env = dict()
for i in os.environ:
	initial_env[i] = os.environ[i]

def threaded(f):
	def wrapper(*args):
		t = threading.Thread(target=f, args=args)
		t.start()
	return wrapper

class SourceryConfig:
	config = ConfigParser.RawConfigParser()

	def deps(self):
		try:
			self.config.read(config_file)
			dependencies = self.config.getboolean('Sourcery', 'dependencies')
		except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
			dependencies = True
		return dependencies
	
	def window_size(self):
		try:
			self.config.read(config_file)
			width = self.config.getint('Window', 'width')
			height = self.config.getint('Window', 'height')
		except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
			try:
				w = gtk.gdk.get_default_root_window()
				p = gtk.gdk.atom_intern('_NET_WORKAREA')
				workarea_width, workarea_height = w.property_get(p)[2][2:4]
				width = int(workarea_width*0.8)
				height = int(workarea_height*0.8)
			except TypeError:
				width = 700
				height= 500
		return width, height

	def write_config(self, dependencies, width, height):
		try:
			try:
				self.config.add_section('Sourcery')
			except ConfigParser.DuplicateSectionError:
				pass
			try:
				self.config.add_section('Window')
			except ConfigParser.DuplicateSectionError:
				pass
			self.config.set('Sourcery', 'dependencies', dependencies)
			self.config.set('Window', 'width', width)
			self.config.set('Window', 'height', height)
			with open(config_file, 'wb') as configfile:
				self.config.write(configfile)
		except IOError:
			pass

class Icon:
	avail = gtk.gdk.pixbuf_new_from_file(shareddir+'/pixmaps/pkg_action_available.png')
	installed = gtk.gdk.pixbuf_new_from_file(shareddir+'/pixmaps/pkg_action_installed.png')
	install = gtk.gdk.pixbuf_new_from_file(shareddir+'/pixmaps/pkg_action_install.png')
	reinstall = gtk.gdk.pixbuf_new_from_file(shareddir+'/pixmaps/pkg_action_reinstall.png')
	remove = gtk.gdk.pixbuf_new_from_file(shareddir+'/pixmaps/pkg_action_remove.png')

class PkgAction:
	DoNothing = 0
	Install = 1
	Reinstall = 2
	Remove = 3

class Sourcery:
	win_width = 0
	win_height = 0
	canceltask = False
	pending = []
	options = dict()

	def set_default_window_size(self):
		config = SourceryConfig()
		width, height = config.window_size()
		self.window.set_default_size(width, height)

	def slaptsrclist(self, searchstring):
		if os.path.isfile(slackbuilds_data):
			if len(searchstring) == 0:
				args = ['slapt-src', '--list']
			else:
				args = ['slapt-src', '-s', searchstring]
			process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
			pkglist_output = process.communicate()[0]
			status = process.returncode
			pkglist_lines = pkglist_output.splitlines()
			# the pkglist array holds [name, ver, desc], while the pkglist_namever array holds
			# [name, ver] only. If more than one SlackBuilds exist for the same package, the
			# description could be different for each one.
			pkglist = []
			pkglist_namever = []
			if status == 0:
				for i in pkglist_lines:
					nameandver, sep, desc = i.partition(' - ')
					name = nameandver.rpartition(':')[0]
					ver = nameandver.rpartition(':')[2]
					if [name, ver] not in pkglist_namever:
						pkglist.append([name, ver, desc])
						pkglist_namever.append([name, ver])
			pkglistlen = len(pkglist)
			if pkglistlen == 0:
				msg = _('No SlackBuilds found')
			elif pkglistlen == 1:
				msg = _('One SlackBuild found')
			else:
				msg = _('%(num)i SlackBuilds found') % {'num' : len(pkglist)}
		else:
			status = 0
			pkglist = []
			msg = _('Could not retrieve SlackBuild data')
		self.lb_statusbar.set_text(msg)
		return status, pkglist

	def pkg_installed(self):
		pkg_installed = []
		for i in os.listdir('/var/log/packages'):
			pkg_installed.append(i.rpartition('-')[0].rpartition('-')[0].rpartition('-')[0])
		return pkg_installed

	def setoptions(self, pkgname, pkgver, options):
		key = pkgname+':'+pkgver
		self.options[key] = options

	def deloptions(self, pkgname, pkgver):
		key = pkgname+':'+pkgver
		try:
			del self.options[key]
		except KeyError:
			pass
	
	def getoptions(self, pkgname, pkgver):
		key = pkgname+':'+pkgver
		if key in self.options:
			opt = self.options[key]
		else:
			opt = ''
		return opt

	@threaded
	def refresh_pkglist(self):
		gtk.gdk.threads_enter()
		self.ls_pkg.clear()
		# The list is cleared, no item is selected, so all menu
		# options for package actions should be disabled
		self.mi_unmark.set_sensitive(False)
		self.mi_install.set_sensitive(False)
		self.mi_reinstall.set_sensitive(False)
		self.mi_remove.set_sensitive(False)
		self.mi_setoptions.set_sensitive(False)
		self.mi_getinfo.set_sensitive(False)
		gtk.gdk.threads_leave()
		cmdstatus, pkglist = self.slaptsrclist(self.entry_search.get_text())
		if cmdstatus == 0:
			pkg_installed = self.pkg_installed()
			for i in pkglist:
				action = 0
				pkgname, pkgver, pkgdesc = i
				for i in self.pending:
					if pkgname == i[0] and pkgver == i[1]:
						action = i[2]
						break
				if pkgname in pkg_installed:
					icon = Icon.installed
					installed = True
				else:	
					icon = Icon.avail
					installed = False
				if [pkgname, pkgver, PkgAction.Install] in self.pending:
					icon = Icon.install
					installed = False
				elif [pkgname, pkgver, PkgAction.Reinstall] in self.pending:
					icon = Icon.reinstall
					installed = True
				elif [pkgname, pkgver, PkgAction.Remove] in self.pending:
					icon = Icon.remove
					installed = True
				gtk.gdk.threads_enter()
				self.ls_pkg.append([icon, pkgname,
					pkgver, pkgdesc,
					installed, action])
				gtk.gdk.threads_leave()
		else:
			gtk.gdk.threads_enter()
			self.dlg_updateerror.show()
			gtk.gdk_threads_leave()

	def get_pkgver(self, pkg):
		f = open(slackbuilds_data)
		done = False
		found = False
		while not done:
			line = f.readline()
			if line == 'SLACKBUILD NAME: '+pkg+'\n':
				found = True
				continue
			if found is True:
				if line.startswith('SLACKBUILD VERSION:'):
					version = line.partition('SLACKBUILD VERSION: ')[2].partition('\n')[0]
					done = True
		f.close()
		return version

	def get_deps(self, pkglist):
		deps = []
		DEVNULL = open('/dev/null', 'w')
		for pkg, pkgver in pkglist:
			args1 = ['yes', 'n']
			p1 = subprocess.Popen(args1, stdout=subprocess.PIPE, stderr=DEVNULL)
			args2 = ['slapt-src', '-i', pkg+':'+pkgver]
			env = dict()
			for i in initial_env:
				env[i] = initial_env[i]
			env['LANG'] = 'C'
			p2 = subprocess.Popen(args2, stdin=p1.stdout, stdout=subprocess.PIPE, stderr=DEVNULL,env=env)
			p1.stdout.close()
			output = p2.communicate()[0]
			found = False
			data = ''
			for line in output.splitlines():
				if line.startswith('The following dependent slackbuilds'):
					found = True
					continue
				if found is True:
					if line.startswith('Do you want to continue'):
						break
					else:
						data = ' '.join([data, line])
			newdeps = data.replace('\n', ' ').strip(' ').split(' ')
			for i in newdeps:
				if i is not '':
					if i not in deps:
						deps.append(i)
		DEVNULL.close()
		return deps

	def get_pkg_info(self, pkg, pkgver):
		# just to be on the safe side
		sourceurl = None
		location = None
		files = None
		deps = None
		
		self.pb_fetchpkginfo.set_fraction(0)
		self.dlg_fetchpkginfo.show()
		while gtk.events_pending():
			gtk.main_iteration()
		data = ''
		f = open(slackbuilds_data)
		done = False
		found = False
		while not done:
			line = f.readline()
			if line == 'SLACKBUILD NAME: '+pkg+'\n':
				found = True
			if found is True:
				if line.startswith('SLACKBUILD'):
					data = ''.join([data, line])
				else:
					done = True
		f.close()
		self.pb_fetchpkginfo.set_fraction(0.1)
		while gtk.events_pending():
			gtk.main_iteration()
		# I don't see a way status can be anything other than 0
		# here. pkg and pkgver will always be correct since they
		# are passed from the gui
		pkginfo = data.splitlines()
		for i in pkginfo:
			if 'SLACKBUILD SOURCEURL: ' in i:
				sourceurl = i.partition('SOURCEURL: ')[2]
			elif 'SLACKBUILD LOCATION: ' in i:
				location = i.partition('LOCATION: ')[2]
			elif 'SLACKBUILD FILES: ' in i:
				files = i.partition('FILES: ')[2].rsplit(' ')
			elif 'SLACKBUILD REQUIRES: ' in i:
				deps = i.partition('REQUIRES: ')[2].replace(',',' ').rsplit(' ')
		self.pb_fetchpkginfo.set_fraction(0.2)
		while gtk.events_pending():
			gtk.main_iteration()
		if 'slack-desc' in files:
			try:
				f = urllib2.urlopen(sourceurl+location+'slack-desc')
				slackdescfull = f.read().splitlines()
				slackdesc = []
				for i in slackdescfull:
					if i.startswith(pkg+':'):
						slackdesc.append(i.partition(pkg+':')[2])
			except urllib2.httperror:
				slackdesc = None
		else:
			slackdesc = None
		self.pb_fetchpkginfo.set_fraction(0.6)
		while gtk.events_pending():
			gtk.main_iteration()
		if 'README' in files:
			try:
				f = urllib2.urlopen(sourceurl+location+'README')
				readme = f.read().splitlines()
			except urllib2.httperror:
				readme = None
		else:
			readme = None
		self.pb_fetchpkginfo.set_fraction(1)
		self.dlg_fetchpkginfo.hide()
		self.dlg_pkginfo.set_title(_('SlackBuild information for')+' '+pkg+' '+pkgver)
		self.lb_pkginfo_name.set_text(pkg)
		self.lb_pkginfo_ver.set_text(pkgver)
		self.lb_pkginfo_source.set_text(sourceurl)
		self.lb_pkginfo_location.set_text(location)
		self.lb_pkginfo_files.set_text("\n".join(files))
		self.lb_pkginfo_deps.set_text("\n".join(deps))
		if slackdesc == None:
			self.lb_pkginfo_slackdesc.set_text(_('Not available.'))
		else:
			try:
				self.lb_pkginfo_slackdesc.set_text("\n".join(slackdesc).decode('utf8'))
			except UnicodeDecodeError:
				self.lb_pkginfo_slackdesc.set_text("\n".join(slackdesc).decode('latin1'))
		if readme == None:
			self.txt_pkginfo_readme.set_text(_('Not available.'))
		else:
			try:
				self.txt_pkginfo_readme.set_text("\n".join(readme).decode('utf8'))
			except UnicodeDecodeError:
				self.txt_pkginfo_readme.set_text("\n".join(readme).decode('latin1'))
		self.dlg_pkginfo.show()
		while gtk.events_pending():
			gtk.main_iteration()

	def on_toolbutton_update_clicked(self, widget):
		self.canceltask = False
		self.dlg_cacheupdate.show()
		self.pb_cacheupdate.pulse()
		process = subprocess.Popen(['slapt-src','-u'], shell=False, close_fds=True, preexec_fn=os.setsid)
		while not self.canceltask:
			while gtk.events_pending():
				gtk.main_iteration()
			self.pb_cacheupdate.pulse()
			status = process.poll()
			time.sleep(0.1)
			if status != None:
				self.dlg_cacheupdate.hide()
				break
		if status == None:
			os.killpg(process.pid, signal.SIGKILL)
		if status != 0:
			self.dlg_errorcache.show()
		else:
			self.refresh_pkglist()
		self.canceltask = False

	@threaded
	def on_toolbutton_exec_clicked(self, widget):
		gtk.gdk.threads_enter()
		self.dlg_wait.show()
		gtk.gdk.threads_leave()
		config = SourceryConfig()

		if config.deps() == True:
			requested_pkg = []
			# get a list of all dependencies for all
			# requested packages
			for i in self.pending:
				if i[2] == PkgAction.Install:
					requested_pkg.append([i[0], i[1]])
			# add all dependencies to the processing
			# liststore
			for pkg in self.get_deps(requested_pkg):
				pkgver = self.get_pkgver(pkg)
				desc = _('%(pkg)s %(pkgver)s is going to be installed as a dependency') % {'pkg' : pkg, 'pkgver' : pkgver}
				self.ls_summary.append([desc, pkg, pkgver, PkgAction.Install])
				# if a package is already going to be
				# installed as a dependency, remove it
				# from the pending list, it's going to
				# be installed anyway
				if [pkg, pkgver, PkgAction.Install] in self.pending:
					self.pending.remove([pkg, pkgver, PkgAction.Install])
		for i in self.pending:
			if i[2] == PkgAction.Install:
				desc = _('%(pkg)s %(pkgver)s is going to be installed') %{'pkg' : i[0], 'pkgver' : i[1]}
			elif i[2] == PkgAction.Reinstall:
				desc = _('%(pkg)s %(pkgver)s is going to be reinstalled') %{'pkg' : i[0], 'pkgver' : i[1]}
			elif i[2] == PkgAction.Remove:
				desc = _('%(pkg)s %(pkgver)s is going to be removed') %{'pkg' : i[0], 'pkgver' : i[1]}
			self.ls_summary.append([desc, i[0], i[1], i[2]])
		gtk.gdk.threads_enter()
		self.dlg_wait.hide()
		self.dlg_summary.show()
		gtk.gdk.threads_leave()
	
	def on_toolbutton_clearsearch_clicked(self, widget):
		if len(self.entry_search.get_text()) != 0:
			self.entry_search.set_text(None)
			self.refresh_pkglist()

	def on_entry_search_activate(self, widget):
		self.refresh_pkglist()	

	def on_entry_search_icon_release(self, widget, icon, event):
		if icon.value_name == 'GTK_ENTRY_ICON_PRIMARY':
			if len(self.entry_search.get_text()) != 0:
				self.entry_search.set_text('')
				while gtk.events_pending():
					gtk.main_iteration()
		self.refresh_pkglist()

	def on_button_setoptions_ok_clicked(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		pkg = self.ls_pkg.get_value(iter, 1)
		ver = self.ls_pkg.get_value(iter, 2)
		options = self.entry_setoptions.get_text().strip(' ')
		if options == '':
			self.deloptions(pkg, ver)
		else:
			test = self.dict_options(options)
			if test is False:
				self.dlg_setoptions_error.show()
			else:
				self.setoptions(pkg, ver, options)
		self.dlg_setoptions.hide()

	def on_button_setoptions_cancel_clicked(self, widget):
		self.dlg_setoptions.hide()

	def dict_options(self, options):
		options_list = []
		for i in options.split(' '):
			opt = i.strip(' ')
			if opt != '':
				options_list.append(opt.split('='))
		try:
			options_dict = dict(options_list)
		except ValueError:
			options_dict = False
		return options_dict

	def update_menus(self):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		pkg = self.ls_pkg.get_value(iter, 1)
		ver = self.ls_pkg.get_value(iter, 2)
		installed = self.ls_pkg.get_value(iter, 4)
		action = self.ls_pkg.get_value(iter, 5)
		pkg_installed = self.pkg_installed()
		self.mi_setoptions.set_sensitive(False)
		self.mi_pkg_setoptions.hide()
		self.mi_getinfo.set_sensitive(True)
		if installed:
			self.mi_install.set_sensitive(False)
			self.mi_pkg_install.hide()
			self.mi_reinstall.set_sensitive(True)
			self.mi_pkg_reinstall.show()
			self.mi_remove.set_sensitive(True)
			self.mi_pkg_remove.show()
		else:
			self.mi_install.set_sensitive(True)
			self.mi_pkg_install.show()
			self.mi_reinstall.set_sensitive(False)
			self.mi_pkg_reinstall.hide()
			self.mi_remove.set_sensitive(False)
			self.mi_pkg_remove.hide()
		if action == PkgAction.DoNothing:
			self.mi_unmark.set_sensitive(False)
			self.mi_pkg_unmark.hide()
			if [pkg, ver, PkgAction.Install] in self.pending:
				self.pending.remove([pkg, ver, PkgAction.Install])
			if [pkg, ver, PkgAction.Reinstall] in self.pending:
				self.pending.remove([pkg, ver, PkgAction.Reinstall])
			if [pkg, ver, PkgAction.Remove] in self.pending:
				self.pending.remove([pkg, ver, PkgAction.Remove])
			if pkg in pkg_installed:
				self.ls_pkg.set_value(iter, 0, Icon.installed)
			else:
				self.ls_pkg.set_value(iter, 0, Icon.avail)
		elif action == PkgAction.Install:
			self.mi_unmark.set_sensitive(True)
			self.mi_pkg_unmark.show()
			self.mi_install.set_sensitive(False)
			self.mi_pkg_install.hide()
			self.mi_setoptions.set_sensitive(True)
			self.mi_pkg_setoptions.show()
			if [pkg, ver, PkgAction.Install] in self.pending:
				pass
			else:
				self.pending.append([pkg, ver, PkgAction.Install])
			self.ls_pkg.set_value(iter, 0, Icon.install)
		elif action == PkgAction.Reinstall:
			self.mi_unmark.set_sensitive(True)
			self.mi_pkg_unmark.show()
			self.mi_reinstall.set_sensitive(False)
			self.mi_setoptions.set_sensitive(True)
			self.mi_pkg_setoptions.show()
			self.mi_pkg_reinstall.hide()
			if [pkg, ver, PkgAction.Reinstall] in self.pending:
				pass
			else:
				self.pending.append([pkg, ver, PkgAction.Reinstall])
			if [pkg, ver, PkgAction.Remove] in self.pending:
				self.pending.remove([pkg, ver, PkgAction.Remove])
			self.ls_pkg.set_value(iter, 0, Icon.reinstall)
		elif action == PkgAction.Remove:
			self.mi_unmark.set_sensitive(True)
			self.mi_pkg_unmark.show()
			self.mi_remove.set_sensitive(False)
			self.mi_pkg_remove.hide()
			if [pkg, ver, PkgAction.Remove] in self.pending:
				pass
			else:
				self.pending.append([pkg, ver, PkgAction.Remove])
			if [pkg, ver, PkgAction.Reinstall] in self.pending:
				self.pending.remove([pkg, ver, PkgAction.Reinstall])
			self.ls_pkg.set_value(iter, 0, Icon.remove)
		if self.pending == []:
			self.mi_unmarkall.set_sensitive(False)
			self.tb_exec.set_sensitive(False)
			self.mi_exec.set_sensitive(False)
		else:
			self.mi_unmarkall.set_sensitive(True)
			self.tb_exec.set_sensitive(True)
			self.mi_exec.set_sensitive(True)

	def on_treeview_pkg_button_press_event(self, widget, event):
		x = int(event.x)
		y = int(event.y)
		time = event.time
		pthinfo = self.tv_pkg.get_path_at_pos(x,y)
		if pthinfo is not None:
			path, col, cellx , celly = pthinfo
			self.tv_pkg.grab_focus()
			self.tv_pkg.set_cursor(path, col, 0)
			if col.get_title() == _('Status') or event.button == 3:
				self.menu_pkgaction.popup(None, None, None, event.button, time)
		return True
	
	def on_treeview_pkg_cursor_changed(self, widget):
		self.update_menus()

	def on_treeview_pkg_key_release_event(self, widget, event):
		button = gtk.gdk.keyval_name(event.keyval) 
		if button == 'Menu':
			self.menu_pkgaction.popup(None, None, None, 1, event.time)

	def on_menuitem_unmarkall_activate(self, widget):
		self.pending = []
		self.options.clear()
		self.mi_unmarkall.set_sensitive(False)
		self.tb_exec.set_sensitive(False)
		self.mi_exec.set_sensitive(False)
		self.refresh_pkglist()

	def on_menuitem_prefs_activate(self, widget):
		# read sources and working dir
		c = SimpleConfig(slaptsrcrc)
		self.ls_sources.clear()
		for i in c.get_all('SOURCE'):
			self.ls_sources.append([i])
		self.entry_workingdir.set_text(c.get('BUILDDIR'))
		# check if dependency checkbox should be on/off
		config = SourceryConfig()
		self.cb_prefs_deps.set_active(config.deps())
		self.dlg_prefs.show()

	def on_menuitem_unmark_activate(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		self.ls_pkg.set_value(iter, 5, PkgAction.DoNothing)
		self.update_menus()
	
	def on_menuitem_install_activate(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		pkg = self.ls_pkg.get_value(iter, 1)
		ver = self.ls_pkg.get_value(iter, 2)
		self.ls_pkg.set_value(iter, 5, PkgAction.Install)
		self.update_menus()

	def on_menuitem_reinstall_activate(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		self.ls_pkg.set_value(iter, 5, PkgAction.Reinstall)
		self.update_menus()

	def on_menuitem_remove_activate(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		self.ls_pkg.set_value(iter, 5, PkgAction.Remove)
		self.update_menus()

	def on_menuitem_setoptions_activate(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		pkg = self.ls_pkg.get_value(iter, 1)
		ver = self.ls_pkg.get_value(iter, 2)
		self.dlg_setoptions.set_title(_("Set options for %(pkg)s %(ver)s") % {'pkg' : pkg, 'ver' : ver})
		options = self.getoptions(pkg, ver)
		self.entry_setoptions.set_text(options)
		self.dlg_setoptions.show()

	def on_menuitem_getinfo_activate(self, widget):
		selectedline = self.tv_pkg.get_selection()
		self.ls_pkg, iter = selectedline.get_selected()
		pkg = self.ls_pkg.get_value(iter, 1)
		ver = self.ls_pkg.get_value(iter, 2)
		self.get_pkg_info(pkg, ver)

	def on_menuitem_legend_activate(self, widget):
		self.dlg_iconlegend.show()

	def on_menuitem_logs_activate(self, widget):
		self.ls_loglist.clear()
		if os.path.isdir(logdir):
			for file in os.listdir(logdir):
				self.ls_loglist.append(file.rsplit('-', 1))
		self.dlg_loglist.show()

	def on_menuitem_about_activate(self, widget):
		self.dlg_about.show()

	def on_dialog_errorcache_delete_event(self, widget, event):
		self.dlg_errorcache.hide()
		return True

	def on_button_errorcache_close_clicked(self, widget):
		self.dlg_errorcache.hide()

	def on_dialog_summary_delete_event(self, widget, event):
		self.dlg_summary.hide()
		self.ls_summary.clear()
		return True

	def on_button_summary_apply_clicked(self, widget):
		self.dlg_summary.hide()
		self.dlg_exec.show()
		self.execute_pending()

	def on_dialog_prefs_delete_event(self, widget, event):
		self.dlg_prefs.hide()
		return True

	def on_button_prefs_apply_clicked(self, widget):
		# write sources and working dir configs to file if
		# changed
		c = SimpleConfig(slaptsrcrc)
		changed = False
		old_sources = c.get_all('SOURCE')
		new_sources = list()
		item = self.ls_sources.get_iter_first()
		while (item is not None):
			new_sources.append(self.ls_sources.get_value(item, 0))
			item = self.ls_sources.iter_next(item)
		if old_sources != new_sources:
			c.remove_all('SOURCE')
			for i in new_sources:
				c.add('SOURCE', i)
			changed = True
		old_builddir = c.get('BUILDDIR')
		new_builddir = self.entry_workingdir.get_text()
		if old_builddir != new_builddir:
			c.set('BUILDDIR', new_builddir)
			changed = True
		c.write()
		# write dependency config to file
		config = SourceryConfig()
		config.write_config(self.cb_prefs_deps.get_active(),
				self.win_width, self.win_height)
		self.dlg_prefs.hide()
		# if repository/working dir info has changed, prompt to
		# rebuild icon cache
		if changed:
			self.dlg_ask_for_update.show()

	def on_button_prefs_cancel_clicked(self, widget):
		self.dlg_prefs.hide()

	def fetchpkg(self, pkg, pkgver):
		self.canceltask = False

		logfile = logdir+'/'+pkg+'-'+pkgver
		f = open(logfile, 'w')
		args = ['slapt-src', '-y', '-f', pkg+':'+pkgver]
		options = self.getoptions(pkg, pkgver)
		options_dict = self.dict_options(options)
		env = dict()
		for i in initial_env:
			env[i] = initial_env[i]
		for i in options_dict:
			env[i] = options_dict[i]
		process = subprocess.Popen(args, stdout = f, stderr = f,
				shell=False, close_fds=True,
				preexec_fn=os.setsid, env=env)
		self.vte_term.feed_child('clear\ntail --pid '+str(process.pid)+' -f '+logfile+' 2>/dev/null & clear\n')
		while not self.canceltask:
			while gtk.events_pending():
				gtk.main_iteration()
			self.pb_exec.pulse()
			status = process.poll()
			time.sleep(0.1)
			if status != None:
				break
		f.close()
		self.vte_term.feed_child('clear\n')
		if status == None:
			os.killpg(process.pid, signal.SIGKILL)
		if self.canceltask:
			self.canceltask = False
			return 127
		elif status != 0:
			self.canceltask = False
			return 2
		else:
			self.canceltask = False
			return 0

	def installpkg(self, pkg, pkgver):
		self.canceltask = False
		# The "yes n" part is added because there are some
		# SlackBuilds that actually ask questions during
		# configuration, however stupid that may seem. A good
		# example is Eterm: if libast is not installed, it will
		# ask if it should download it... It's better to just
		# fail by default in such cases and check the logs for
		# what happened.
		logfile = logdir+'/'+pkg+'-'+pkgver
		f = open(logfile, 'a')
		DEVNULL = open('/dev/null', 'w')

		config = SourceryConfig()

		args = ['yes', 'n']
		pyes = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = DEVNULL)
		if config.deps() == True:
			args = ['slapt-src', '-y', '-i', pkg+':'+pkgver]
		else:
			args = ['slapt-src', '-y', '-n', '-i', pkg+':'+pkgver]
		options = self.getoptions(pkg, pkgver)
		options_dict = self.dict_options(options)
		env = dict()
		for i in initial_env:
			env[i] = initial_env[i]
		for i in options_dict:
			env[i] = options_dict[i]
		process = subprocess.Popen(args, stdin=pyes.stdout,
				stdout = f, stderr = f, shell=False,
				close_fds=True, preexec_fn=os.setsid,
				env=env)
		self.vte_term.feed_child('clear\ntail --pid '+str(process.pid)+' -f '+logfile+' 2>/dev/null & clear\n')
		while not self.canceltask:
			while gtk.events_pending():
				gtk.main_iteration()
			self.pb_exec.pulse()
			status = process.poll()
			time.sleep(0.1)
			if status != None:
				break
		f.close()
		DEVNULL.close()
		self.vte_term.feed_child('clear\n')
		pyes.stdout.close()
		if status == None:
			os.killpg(process.pid, signal.SIGKILL)
		if self.canceltask:
			self.canceltask = False
			return 127
		elif status != 0:
			self.dlg_pkglog.set_title(_('Build log for')+' '+pkg+'-'+pkgver)
			self.canceltask = False
			return 1
		else:
			self.canceltask = False
			return 0

	def removepkg(self, pkg):
		error = False
		logfile = '/tmp/sourcery-removepkg'
		try:
			os.remove(logfile)
		except OSError:
			pass
		f = open(logfile, 'w')
		args = ['slapt-get', '-y', '--remove', '--no-dep', pkg]
		process = subprocess.Popen(args, stdout = f, stderr = f, shell=False, close_fds=True, preexec_fn=os.setsid)
		self.vte_term.feed_child('clear\ntail --pid '+str(process.pid)+' -f '+logfile+' 2>/dev/null & clear\n')
		while True:
			while gtk.events_pending():
				gtk.main_iteration()
			self.pb_exec.pulse()
			status = process.poll()
			time.sleep(0.1)
			if status != None:
				break
		f.close()
		self.vte_term.feed_child('clear\n')
		try:
			os.remove(logfile)
		except OSError:
			pass
		if error:
			return 1
		else:
			return 0

	def execute_pending(self):
		while gtk.events_pending():
			gtk.main_iteration()
		totaltasks = len(self.ls_summary)
		currentpos = 0
		step = 1/float(totaltasks*2)
		self.pb_execoverall.set_fraction(0)
		self.pb_exec.set_fraction(0)
		for i in self.ls_summary:
			pkg, pkgver, action = i[1], i[2], i[3]
			if action == PkgAction.Install:
				self.lb_exec.set_text(_('Downloading source files for')+' '+pkg+'-'+pkgver+'...')
				retval = self.fetchpkg(pkg, pkgver)
				currentpos = currentpos + step
				self.pb_execoverall.set_fraction(currentpos)
				if retval == 0:
					self.lb_exec.set_text(_('Compiling')+' '+pkg+'-'+pkgver+'...')
					retval = self.installpkg(pkg, pkgver)
			elif action == PkgAction.Reinstall:
				self.lb_exec.set_text(_('Downloading source files for')+' '+pkg+'-'+pkgver+'...')
				retval = self.fetchpkg(pkg, pkgver)
				currentpos = currentpos + step
				self.pb_execoverall.set_fraction(currentpos)
				if retval == 0:
					self.lb_exec.set_text(_('Compiling')+' '+pkg+'-'+pkgver+'...')
					retval = self.installpkg(pkg, pkgver)
			elif action == PkgAction.Remove:
				self.lb_exec.set_text(_('Removing')+' '+pkg+'...')
				retval = self.removepkg(pkg)
				currentpos = currentpos + step
				self.pb_execoverall.set_fraction(currentpos)
			if retval != 0:
				break
			currentpos = currentpos + step
			self.pb_execoverall.set_fraction(currentpos)
		while gtk.events_pending():
			gtk.main_iteration()
		self.pending = []
		self.ls_summary.clear()
		self.dlg_exec.hide()
		if retval == 0:
			self.refresh_pkglist()
			self.dlg_success.show()
		# retval = 1 means there was an error during building
		# the package
		elif retval == 1:
			self.btn_pkginstallerror_log.set_sensitive(True)
			self.lb_pkginstallerror.set_text(_('There was an error while compiling %(pkg)s %(pkgver)s. All pending actions will be purged from the processing queue. You can review the log file for any errors during compiling.') % {'pkg' : pkg, 'pkgver' : pkgver})
			self.show_pkg_install_error_dlg(pkg, pkgver)
			self.on_menuitem_unmarkall_activate(None)
		# retval = 2 means there was an error during downloading
		# the sources
		elif retval == 2:
			self.btn_pkginstallerror_log.set_sensitive(False)
			self.lb_pkginstallerror.set_text(_('There was an error while downloading source files for %(pkg)s %(pkgver)s. All pending actions will be purged from the processing queue.') % {'pkg' : pkg, 'pkgver' : pkgver})
			self.show_pkg_install_error_dlg(pkg, pkgver)
			self.on_menuitem_unmarkall_activate(None)
		else:
			self.dlg_canceled.show()
			self.on_menuitem_unmarkall_activate(None)

	def on_button_summary_cancel_clicked(self, widget):
		self.ls_summary.clear()
		self.dlg_summary.hide()

	def on_button_exec_cancel_clicked(self, widget):
		self.canceltask = True
		self.dlg_exec.hide()

	def on_button_success_ok_clicked(self, widget):
		self.dlg_success.hide()

	def on_button_canceled_ok_clicked(self, widget):
		self.dlg_canceled.hide()
	
	def on_button_updateerror_ok_clicked(self, widget):
		self.dlg_updateerror.hide()

	def show_pkg_install_error_dlg(self, pkg, pkgver):
		self.dlg_pkginstallerror.show()

	def on_button_pkginstallerror_close_clicked(self, widget):
		self.dlg_pkginstallerror.hide()
		# Unmark all pending actions if an error has occured
		self.on_menuitem_unmarkall_activate(None)

	def on_button_pkginstallerror_log_clicked(self, widget):
		# get the pkg name and ver from the window title
		# weird, but it works
		logfile = logdir+'/'+self.dlg_pkglog.get_title().partition(_('Build log for')+' ')[2]
		try:
			f = open(logfile)
			try:
				log = f.read().decode('utf8')
			except UnicodeDecodeError:
				log = f.read().decode('latin1')
			self.txt_pkglog.set_text(log)
			f.close()
		except IOError:
			self.txt_pkglog.set_text(_('Not available'))
		self.dlg_pkginstallerror.hide()
		self.dlg_pkglog.show()

	def on_button_cacheupdate_cancel_clicked(self, widget):
		self.canceltask = True
		self.dlg_cacheupdate.hide()

	def on_dialog_pkginfo_delete_event(self, widget, event):
		self.dlg_pkginfo.hide()
		return True

	def on_button_pkginfo_close_clicked(self, widget):
		self.dlg_pkginfo.hide()

	def on_button_pkglog_close_clicked(self, widget):
		self.dlg_pkglog.hide()

	def on_dialog_pkglog_delete_event(self, widget, event):
		self.dlg_pkglog.hide()
		return True
	
	def on_dialog_iconlegend_delete_event(self, widget, event):
		self.dlg_iconlegend.hide()
		return True
	
	def on_button_iconlegend_close_clicked(self, widget):
		self.dlg_iconlegend.hide()

	def on_dialog_loglist_delete_event(self, widget, event):
		self.dlg_loglist.hide()
		return True

	def on_button_loglist_view_clicked(self, widget):
		try:
			selectedlog = self.tv_loglist.get_selection()
			self.ls_loglist, iter = selectedlog.get_selected()
			pkg = self.ls_loglist.get_value(iter, 0)
			ver = self.ls_loglist.get_value(iter, 1)
			self.dlg_loglist.hide()
			self.dlg_pkglog.set_title(_('Build log for')+' '+pkg+'-'+ver)
			logfile = logdir+'/'+pkg+'-'+ver
			try:
				f = open(logfile)
				try:
					log = f.read().decode('utf8')
				except UnicodeDecodeError:
					log = f.read().decode('latin1')
				self.txt_pkglog.set_text(log)
				f.close()
			except IOError:
				self.txt_pkglog.set_text(_('Error reading log file.'))
			self.dlg_pkglog.show()
		except TypeError:
			pass

	def on_button_loglist_del_clicked(self, widget):
		try:
			selectedlog = self.tv_loglist.get_selection()
			self.ls_loglist, iter = selectedlog.get_selected()
			pkg = self.ls_loglist.get_value(iter, 0)
			ver = self.ls_loglist.get_value(iter, 1)
			logfile = logdir+'/'+pkg+'-'+ver
			try:
				os.remove(logfile)
			except OSError:
				pass
			self.ls_loglist.clear()
			if os.path.isdir(logdir):
				for file in os.listdir(logdir):
					self.ls_loglist.append(file.rsplit('-', 1))
		except TypeError:
			pass

	def on_button_loglist_close_clicked(self, widget):
		self.dlg_loglist.hide()

	def on_treeview_loglist_key_release_event(self, widget, event):
		button = gtk.gdk.keyval_name(event.keyval)
		if button == 'Return':
			self.on_button_loglist_view_clicked(self)
		elif button == 'Delete':
			self.on_button_loglist_del_clicked(self)

	def on_button_firstrun_cancel_clicked(self, widget):
		self.dlg_firstrun.hide()
		self.window.show()

	def on_button_firstrun_create_clicked(self, widget):
		self.dlg_firstrun.hide()
		self.window.show()
		self.on_toolbutton_update_clicked(self)

	def on_aboutdialog_response(self, widget, data=None):
		self.dlg_about.hide()

	def on_aboutdialog_delete_event(self, widget, event):
		self.dlg_about.hide()
		return True

	def on_dialog_exec_delete_event(self, widget, event):
		self.dlg_exec.hide()
		return True

	def on_dialog_success_delete_event(self, widget, event):
		self.dlg_success.hide()
		return True

	def on_dialog_canceled_delete_event(self, widget, event):
		self.dlg_canceled.hide()
		return True

	def on_dialog_updateerror_delete_event(self, widget, event):
		self.dlg_updateerror.hide()
		return True
	
	def on_dialog_pkginstallerror_delete_event(self, widget, event):
		self.dlg_pkginstallerror.hide()
		return True

	def on_dialog_cacheupdate_delete_event(self, widget, event):
		self.dlg_cacheupdate.hide()
		return True

	def on_dialog_fetchpkginfo_delete_event(self, widget, event):
		self.dlg_fetchpkginfo.hide()
		return True
	
	def on_dialog_firstrun_delete_event(self, widget, event):
		self.dlg_firstrun.hide()
		return True
	
	def on_dialog_ask_for_update_delete_event(self, widget, event):
		self.dlg_ask_for_update.hide()
		return True
	
	def on_dialog_add_source_delete_event(self, widget, event):
		self.dlg_add_source.hide()
		return True
	
	def on_dialog_edit_source_delete_event(self, widget, event):
		self.dlg_edit_source.hide()
		return True
	
	def on_dialog_clear_cache_delete_event(self, widget, event):
		self.dlg_clear_cache.hide()
		return True

	def on_dialog_setoptions_delete_event(self, widget, event):
		self.dlg_setoptions.hide()
		return True

	def on_dialog_setoptions_error_delete_event(self, widget, event):
		self.dlg_setoptions_error.hide()
		self.dlg_setoptions.show()
		return True
	
	def on_messagedialog_setoptionserror_response(self, widget, event):
		self.dlg_setoptions_error.hide()
		self.dlg_setoptions.show()

	def on_button_ask_for_update_rebuild_clicked(self, widget):
		self.dlg_ask_for_update.hide()
		self.on_toolbutton_update_clicked(self)

	def on_button_ask_for_update_cancel_clicked(self, widget):
		self.dlg_ask_for_update.hide()

	def on_button_source_add_clicked(self, widget):
		self.entry_add_source.set_text("")
		self.entry_add_source.grab_focus()
		self.dlg_add_source.show()

	def on_button_source_edit_clicked(self, widget):
		try:
			selectedline = self.tv_sources.get_selection()
			self.ls_sources, iter = selectedline.get_selected()
			source = self.ls_sources.get_value(iter, 0)
			self.entry_edit_source.set_text(source)
			self.entry_edit_source.grab_focus()
			self.dlg_edit_source.show()
		except TypeError:
			pass

	def on_button_source_del_clicked(self, widget):
		try:
			selectedline = self.tv_sources.get_selection()
			self.ls_sources, iter = selectedline.get_selected()
			pkg = self.ls_sources.get_value(iter, 0)
			self.ls_sources.remove(iter)
		except TypeError:
			pass

	def on_button_clear_cache_clicked(self, widget):
		self.canceltask = False
		self.dlg_clear_cache.show()
		while gtk.events_pending():
			gtk.main_iteration()
		time.sleep(0.5)	
		process = subprocess.Popen(['slapt-src','--clean'], shell=False, close_fds=True, preexec_fn=os.setsid)
		while not self.canceltask:
			self.pb_clear_cache.pulse()
			while gtk.events_pending():
				gtk.main_iteration()
			status = process.poll()
			time.sleep(0.1)
			if status != None:
				self.dlg_clear_cache.hide()
				break
		self.dlg_clear_cache.hide()
		self.canceltask = False

	def on_button_add_source_add_clicked(self, widget):
		source = self.entry_add_source.get_text().lstrip(' ').rstrip(' ')
		if source != "":
			self.ls_sources.append([source])
		self.dlg_add_source.hide()

	def on_button_add_source_cancel_clicked(self, widget):
		self.dlg_add_source.hide()

	def on_button_edit_source_apply_clicked(self, widget):
		selectedline = self.tv_sources.get_selection()
		self.ls_sources, iter = selectedline.get_selected()
		source = self.entry_edit_source.get_text().lstrip(' ').rstrip(' ')
		self.ls_sources.set_value(iter, 0, source)
		self.dlg_edit_source.hide()

	def on_button_edit_source_cancel_clicked(self, widget):
		self.dlg_edit_source.hide()

	def on_sourcery_configure_event(self, widget, data=None):
		self.win_width, self.win_height = self.window.get_size()

	def gtk_main_quit(self, widget, data=None):
		config = SourceryConfig()
		deps = config.deps()
		config.write_config(deps, self.win_width, self.win_height)
		gtk.main_quit()

	def __init__(self):
		builder = gtk.Builder()
		if os.path.exists('sourcery.glade'):
			builder.add_from_file('sourcery.glade')
		elif os.path.exists('/usr/share/sourcery/sourcery.glade'):
			builder.add_from_file('/usr/share/sourcery/sourcery.glade')

		#
		# Main window objects
		#
		self.window = builder.get_object('sourcery')
		self.tv_pkg = builder.get_object('treeview_pkg')
		self.tv_pkg.set_rules_hint(True)
		self.tvc_status = builder.get_object('treeviewcolumn_status')
		self.tvc_status.set_title(_('Status'))
		self.cr_status = builder.get_object('cellrendererpixbuf_status')
		self.tvc_pkgname = builder.get_object('treeviewcolumn_pkgname')
		self.tvc_pkgname.set_title(_('Name'))
		self.tvc_version = builder.get_object('treeviewcolumn_version')
		self.tvc_version.set_title(_('Version'))
		self.tvc_desc = builder.get_object('treeviewcolumn_desc')
		self.tvc_desc.set_title(_('Description'))
		self.ls_pkg = builder.get_object('liststore_pkg')
		self.tb_update = builder.get_object('toolbutton_update')
		self.tb_exec = builder.get_object('toolbutton_exec')
		self.entry_search = builder.get_object('entry_search')
		self.lb_statusbar = builder.get_object('label_statusbar')
		# File menu
		self.mi_exec = builder.get_object('menuitem_exec')
		# Edit menu
		self.mi_unmarkall = builder.get_object('menuitem_unmarkall')
		self.mi_prefs = builder.get_object('menuitem_prefs')
		# Package menu
		self.mi_unmark = builder.get_object('menuitem_unmark')
		self.mi_install = builder.get_object('menuitem_install')
		self.mi_reinstall = builder.get_object('menuitem_reinstall')
		self.mi_remove = builder.get_object('menuitem_remove')
		self.mi_setoptions = builder.get_object('menuitem_setoptions')
		self.mi_getinfo = builder.get_object('menuitem_getinfo')
		# View menu
		self.mi_logs = builder.get_object('menuitem_logs')
		# right click menu
		self.menu_pkgaction = builder.get_object('menu_pkgaction')
		self.mi_pkg_unmark = builder.get_object('menuitem_pkg_unmark')
		self.mi_pkg_install = builder.get_object('menuitem_pkg_install')
		self.mi_pkg_reinstall = builder.get_object('menuitem_pkg_reinstall')
		self.mi_pkg_remove = builder.get_object('menuitem_pkg_remove')
		self.mi_pkg_setoptions = builder.get_object('menuitem_pkg_setoptions')
		self.mi_pkg_getinfo = builder.get_object('menuitem_pkg_getinfo')

		#
		# Update cache progress window
		#
		self.dlg_cacheupdate = builder.get_object('dialog_cacheupdate')
		self.pb_cacheupdate = builder.get_object('progressbar_cacheupdate')
		self.btn_cacheupdate_cancel = builder.get_object('button_cacheupdate_cancel')

		#
		# Error updating cache dialog
		#
		self.dlg_errorcache = builder.get_object('dialog_errorcache')
		self.btn_errorcacheok = builder.get_object('button_errorcacheok')

		#
		# Summary dialog
		#
		self.dlg_summary = builder.get_object('dialog_summary')
		self.btn_summary_apply = builder.get_object('button_summary_apply')
		self.btn_summary_cancel = builder.get_object('button_summary_cancel')
		self.tv_summary = builder.get_object('treeview_summary')
		self.ls_summary = builder.get_object('liststore_summary')

		#
		# Execute dialog
		#
		self.dlg_exec = builder.get_object('dialog_exec')
		self.btn_exec_cancel = builder.get_object('button_exec_cancel')
		self.lb_exec = builder.get_object('label_exec')
		self.pb_exec = builder.get_object('progressbar_exec')
		self.tv_exec = builder.get_object('treeview_exec')
		self.pb_execoverall = builder.get_object('progressbar_execoverall')
		self.dlg_exec_vbox = builder.get_object('dialog_exec_vbox')
		self.vte_term = vte.Terminal()
		self.dlg_exec_vbox.add(self.vte_term)
		self.vte_term.fork_command('bash')
		self.vte_term.feed_child('unset PS1\nclear\n')
		self.vte_term.set_sensitive(False)
		self.vte_term.set_size(80, 20)
		self.vte_term.set_font_from_string('Terminus')
		self.vte_term.show()

		#
		# Set options dialog
		#
		self.dlg_setoptions = builder.get_object('dialog_setoptions')
		self.entry_setoptions = builder.get_object('entry_setoptions')
		self.dlg_setoptions_error = builder.get_object('messagedialog_setoptionserror')
	
		#
		# Success dialog
		#
		self.dlg_success = builder.get_object('messagedialog_success')
		self.btn_success_ok = builder.get_object('button_success_ok')

		#
		# Canceled tasks dialog
		#
		self.dlg_canceled = builder.get_object('messagedialog_canceled')
		self.btn_canceled_ok = builder.get_object('button_canceled_ok')

		#
		# Update error dialog
		#
		self.dlg_updateerror = builder.get_object('messagedialog_updateerror')
		self.btn_updateerror_ok = builder.get_object('button_updateerror_ok')

		#
		# Install package error dialog
		#
		self.dlg_pkginstallerror = builder.get_object('dialog_pkginstallerror')
		self.btn_pkginstallerror_close = builder.get_object('button_pkginstallerror_close')
		self.btn_pkginstallerror_log = builder.get_object('button_pkginstallerror_log')
		self.lb_pkginstallerror = builder.get_object('label_pkginstallerror')

		#
		# Fetch pkg info dialog
		#
		self.dlg_fetchpkginfo = builder.get_object('dialog_fetchpkginfo')
		self.pb_fetchpkginfo = builder.get_object('progressbar_fetchpkginfo')
	
		#
		# Display pkg info dialog
		#
		self.dlg_pkginfo = builder.get_object('dialog_pkginfo')
		self.btn_pkginfo_close = builder.get_object('button_pkginfo_close')
		self.lb_pkginfo_name = builder.get_object('label_pkginfo_name')
		self.lb_pkginfo_ver = builder.get_object('label_pkginfo_ver')
		self.lb_pkginfo_source = builder.get_object('label_pkginfo_source')
		self.lb_pkginfo_location = builder.get_object('label_pkginfo_location')
		self.lb_pkginfo_files = builder.get_object('label_pkginfo_files')
		self.lb_pkginfo_deps = builder.get_object('label_pkginfo_deps')
		self.lb_pkginfo_slackdesc = builder.get_object('label_pkginfo_slackdesc')
		self.txt_pkginfo_readme = builder.get_object('textbuffer_pkginfo_readme')
	
		#
		# Icon legend dialog
		#
		self.dlg_iconlegend = builder.get_object('dialog_iconlegend')
		self.btn_iconlegend_close = builder.get_object('button_iconlegend_close')
		self.im_legend_notinstalled = builder.get_object('image_legend_notinstalled')
		self.im_legend_notinstalled.set_from_pixbuf(Icon.avail)
		self.im_legend_installed = builder.get_object('image_legend_installed')
		self.im_legend_installed.set_from_pixbuf(Icon.installed)
		self.im_legend_tobeinstalled = builder.get_object('image_legend_tobeinstalled')
		self.im_legend_tobeinstalled.set_from_pixbuf(Icon.install)
		self.im_legend_tobereinstalled = builder.get_object('image_legend_tobereinstalled')
		self.im_legend_tobereinstalled.set_from_pixbuf(Icon.reinstall)
		self.im_legend_toberemoved = builder.get_object('image_legend_toberemoved')
		self.im_legend_toberemoved.set_from_pixbuf(Icon.remove)

		#
		# Pkg log dialog
		#
		self.dlg_pkglog = builder.get_object('dialog_pkglog')
		self.btn_pkglog_close = builder.get_object('button_pkglog_close')
		self.txt_pkglog = builder.get_object('textbuffer_pkglog')

		#
		# Log list dialog
		#
		self.dlg_loglist = builder.get_object('dialog_loglist')
		self.ls_loglist = builder.get_object('liststore_loglist')
		self.ls_loglist.set_sort_column_id(0, gtk.SORT_ASCENDING)
		self.tv_loglist = builder.get_object('treeview_loglist')
		self.tvc_loglist_name = builder.get_object('treeviewcolumn_loglist_name')
		self.tvc_loglist_ver = builder.get_object('treeviewcolumn_loglist_ver')
		self.tvc_loglist_name.set_title(_('Name'))
		self.tvc_loglist_ver.set_title(_('Version'))
		self.cr_loglist_name = builder.get_object('cellrenderer_loglist_name')
		self.cr_loglist_ver = builder.get_object('cellrenderer_loglist_ver')

		#
		# Preferences dialog
		#
		# sources tab
		self.tv_sources = builder.get_object('treeview_sources')
		self.ls_sources = builder.get_object('liststore_sources')
		self.btn_source_add = builder.get_object('button_source_add')
		self.btn_source_edit = builder.get_object('button_source_edit')
		self.btn_source_del = builder.get_object('button_source_del')
		# working dir tab
		self.entry_workingdir = builder.get_object('entry_workingdir')
		self.btn_clear_cache = builder.get_object('button_clear_cache')
		# dependencies tab
		self.dlg_prefs = builder.get_object('dialog_prefs')
		self.cb_prefs_deps = builder.get_object('checkbutton_prefs_deps')
		# buttons
		self.btn_prefs_apply = builder.get_object('button_prefs_apply')
		self.btn_prefs_cancel = builder.get_object('button_prefs_cancel')

		#
		# Add new source dialog
		#
		self.dlg_add_source = builder.get_object('dialog_add_source')
		self.entry_add_source = builder.get_object('entry_add_source')
		self.btn_add_source_add = builder.get_object('button_add_source_add')
		self.btn_add_source_cancel = builder.get_object('button_add_source_cancel')

		#
		# Edit source dialog
		#
		self.dlg_edit_source = builder.get_object('dialog_edit_source')
		self.entry_edit_source = builder.get_object('entry_edit_source')
		self.btn_edit_source_apply = builder.get_object('button_edit_source_apply')
		self.btn_edit_source_cancel = builder.get_object('button_edit_source_cancel')

		#
		# Ask for update (after changing preferences) dialog
		#
		self.dlg_ask_for_update = builder.get_object('dialog_ask_for_update')
		self.btn_ask_for_update_rebuild = builder.get_object('button_ask_for_update_rebuild')
		self.btn_ask_for_update_cancel = builder.get_object('button_ask_for_update_cancel')

		#
		# Clear cache dialog
		#
		self.dlg_clear_cache = builder.get_object('dialog_clear_cache')
		self.pb_clear_cache = builder.get_object('progressbar_clear_cache')
		self.btn_clear_cache_cancel = builder.get_object('button_clear_cache_cancel')

		#
		# First run dialog
		#
		self.dlg_firstrun = builder.get_object('dialog_firstrun')
		self.btn_firstrun_cancel = builder.get_object('button_firstrun_cancel')
		self.btn_firstrun_create = builder.get_object('button_firstrun_create')

		#
		# Please wait dialog
		#
		self.dlg_wait = builder.get_object('dialog_wait')

		#
		# About dialog
		#
		self.dlg_about = builder.get_object('aboutdialog')

		# Set default window size
		self.set_default_window_size()
		
		# Connect all signals
		builder.connect_signals(self)
		if os.path.isfile(slackbuilds_data):
			self.window.show()
			self.refresh_pkglist()
		else:
			self.window.hide()
			self.dlg_firstrun.show()

if __name__ == "__main__":
	app = Sourcery()
	gtk.main()
