Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • trisquel/package-helpers
  • aklis/package-helpers
  • leny2010/package-helpers
  • fr33domlover/package-helpers
  • Legimet/package-helpers
  • ralphtheninja/package-helpers
  • damo22/package-helpers
  • wherrfrye/package-helpers
  • habs/package-helpers
  • pehjota/package-helpers
  • kpengboy/package-helpers
  • alvaro/package-helpers
  • salman/package-helpers
  • pabloyoyoista/package-helpers
  • mixalis/package-helpers
  • jorgesumle/package-helpers
  • a_slacker_here/package-helpers
  • chaosmonk/package-helpers
  • Beformed/package-helpers
  • dknight/package-helpers
  • proninyaroslav/package-helpers
  • adfeno/package-helpers
  • snd/package-helpers
  • davidpgil/package-helpers
  • diopon/package-helpers
  • ruben/package-helpers
  • bandali/package-helpers
  • joshaspinall/package-helpers
  • GNUtoo/package-helpers
  • Ark74/package-helpers
  • dragestil/package-helpers
  • bill-auger/package-helpers
  • andi89gi/package-helpers
  • Fikar/package-helpers
  • davidl/package-helpers
  • jas/package-helpers
  • parodper/package-helpers
  • David_Hedlund/package-helpers
  • dinomug/package-helpers
  • bf/package-helpers
  • hartkemd/package-helpers
  • del111/package-helpers
  • jxself/package-helpers
  • JacobK/package-helpers
44 results
Show changes
Commits on Source (3)
Showing
with 3347 additions and 0 deletions
Package: trisquel-app-install
Version: 0.5.2.8-0trisquel2.1
Architecture: all
Maintainer: Rubén Rodríguez <ruben@trisquel.uvigo.es>
Depends: app-install-data (>= 0.4.0), gconf2 (>= 2.10.1-2), gksu, gnome-icon-theme, python (>= 2.5), python (<< 2.6), python-apt (>= 0.7.4ubuntu4), python-central (>= 0.6.5), python-dbus, python-gconf, python-gdbm, python-glade2 (>= 2.4.0), python-gst0.10, python-gtk2 (>= 2.10.1), python-gtkhtml2, python-launchpad-integration, python-sexy, python-xdg (>= 0.8), synaptic (>= 0.57.8)
Section: gnome
Priority: optional
Conflicts: gnome-app-install
Description: GNOME Application Installer, Trisquel Version
A pretty application installer for GNOME. It can also search for mime
types or gstreamer codecs. This Trisquel version only shows free apps.
Original-Maintainer: Julian Andres Klode <jak@jak-linux.org>
Python-Version: 2.5
#!/bin/sh
set -e
# Automatically added by dh_pycentral
if which pycentral >/dev/null 2>&1; then
pycentral pkginstall trisquel-app-install
if grep -qs '^trisquel-app-install$' /var/lib/pycentral/delayed-pkgs; then
sed -i '/^trisquel-app-install$/d' /var/lib/pycentral/delayed-pkgs
fi
fi
# End automatically added section
# Automatically added by dh_scrollkeeper
if [ "$1" = "configure" ] && which scrollkeeper-update >/dev/null 2>&1; then
scrollkeeper-update -q >/dev/null 2>&1
fi
# End automatically added section
# Automatically added by dh_gconf
if [ "$1" = "configure" ]; then
gconf-schemas --register gnome-app-install.schemas
fi
# End automatically added section
# Automatically added by dh_icons
if which update-icon-caches >/dev/null 2>&1 ; then
update-icon-caches /usr/share/icons/hicolor
fi
# End automatically added section
if [ "$1" = "configure" ]; then
# cache the application data
/usr/sbin/update-app-install || true
fi
#!/bin/sh
set -e
if [ "$1" = "purge" ]; then
# remove the cached application data
rm -f /var/cache/app-install/*
fi
# Automatically added by dh_scrollkeeper
if [ "$1" = "remove" ] && which scrollkeeper-update >/dev/null 2>&1; then
scrollkeeper-update -q
fi
# End automatically added section
# Automatically added by dh_gconf
if [ "$1" = purge ]; then
OLD_DIR=/etc/gconf/schemas
SCHEMA_FILES="gnome-app-install.schemas "
if [ -d $OLD_DIR ]; then
for SCHEMA in $SCHEMA_FILES; do
rm -f $OLD_DIR/$SCHEMA
done
rmdir -p --ignore-fail-on-non-empty $OLD_DIR
fi
fi
# End automatically added section
# Automatically added by dh_icons
if which update-icon-caches >/dev/null 2>&1 ; then
update-icon-caches /usr/share/icons/hicolor
fi
# End automatically added section
#!/bin/sh
set -e
# Automatically added by dh_pycentral
case "$1" in remove|upgrade)
if which python >/dev/null 2>&1 && which pycentral >/dev/null 2>&1; then
pycentral pkgremove trisquel-app-install
else
flist=$(tempfile)
slist=$(tempfile)
dpkg -L trisquel-app-install | tee $flist | \
while read n; do
case "$n" in
/usr/share/pyshared/*)
n2=${n#/usr/share/pyshared/*}
case "$n" in
*.py) echo "p $n";;
*) [ -d "$n" ] && echo "d $n2" || echo "f $n2"
esac
;;
*) continue
esac
done > $slist
if [ -s $slist ]; then
for d in /usr/lib/python[0-9].[0-9]/????-packages; do
case "$d" in */python2.1/*|*/python2.2/*) continue; esac
while read t n; do
case "$t" in
p) rm -f $d/$n $d/${n}[co];;
d) rmdir $d/$n 2>/dev/null || true;;
*) rm -f $d/$n
esac
done < $slist
done
fi
awk '/\/usr\/share\/pyshared/ {next} /\.py$/ {print $0"c\n" $0"o"}' $flist \
| xargs -r rm -f >&2
rm -f $flist $slist
fi
esac
# End automatically added section
# Automatically added by dh_gconf
if [ "$1" = remove ] || [ "$1" = upgrade ]; then
gconf-schemas --unregister gnome-app-install.schemas
fi
# End automatically added section
#!/usr/bin/python
# Copyright (C) 2004-2005 Ross Burton <ross@burtonini.com>
# 2005-2007 Canonical
#
# Authors:
# Ross Burton
# Michael Vogt
# Sebastian Heinlein
# Ian Jackson
# Niran Babalola
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
from AppInstall.activation import main
if __name__ == "__main__":
main()
gnome-app-install
\ No newline at end of file
# (c) 2005 Canonical, GPL
import gtk
import gtkhtml2
import urllib
import urlparse
import gobject
import time
import subprocess
from gettext import gettext as _
class BrowserView(object):
""" abstract browser interface for AppInstall, the requirements are
very light, it must only support loading a html page for now
"""
def loadUri(self, uri):
pass
class DumpBrowserView(gtk.ScrolledWindow):
def __init__(self):
gtk.ScrolledWindow.__init__(self)
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.set_shadow_type(gtk.SHADOW_IN)
self.view = gtk.TextView()
self.add(self.view)
self.view.show_all()
def loadUri(self,uri):
parts = urlparse.urlparse(uri)
if parts[0] != "file":
return False
f = open(parts[2])
buf = self.view.get_buffer()
buf.set_text(f.read())
return True
# import gtkmozembed
# class MozEmbedBrowserView(gtkmozembed.MozEmbed):
# def __init__(self):
# gtkmozembed.MozEmbed.__init__(self)
# def loadUri(self, uri):
# self.load_url(uri)
class GtkHtml2BrowserView(gtk.ScrolledWindow):
__gsignals__ = {
'submit': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING))
}
# FIXME: this stuff is not threaded
# the problem is that for threading and/or async read support
# we need a URLOpener() that returns a object that can do
# async read()
# To do this, we need a e.g. GnomeVfsWorker that reacts on
# read(), keeps the gtk_stuff runing and can be canceled
def __init__(self):
gtk.ScrolledWindow.__init__(self)
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.set_shadow_type(gtk.SHADOW_IN)
self.view = gtkhtml2.View()
self.view.show()
self.currentUri = None
self._opener = urllib.FancyURLopener()
self.document = gtkhtml2.Document()
self.document.connect('request_url', self._request_url)
self.view.set_document(self.document)
self.add(self.view)
self.document.connect('link_clicked', self.linkClicked)
self.document.connect('submit', self.submit)
def linkClicked(self, document, link):
subprocess.Popen(["/usr/bin/gnome-open",link])
def submit(self, document, action, method, value):
"""A html form in the app description is used to add required
repositories. So send the corresponding signal"""
self.emit("submit", action, method, value)
def loadUri(self, uri):
#print "loadUri(%s)" % uri
self.content = None
if uri == "about:blank":
self.document.clear()
return
# load it
try:
f = self._open_uri(uri)
except (OSError, IOError):
print "failed to open", uri
self.content = _("Failed to open '%s'") % uri
lock.release()
return
self.currentUri = self._resolve_uri(uri)
self.headers = f.info()
self.content = f.read()
self.document.open_stream('text/html')
self.document.write_stream(self.content)
self.document.close_stream()
def _open_uri(self, uri):
#print "_resolv_uri: %s " % uri
uri = self._resolve_uri(uri)
return self._opener.open(uri)
def _resolve_uri(self, uri):
if self._is_relative_to_server(uri):
return urlparse.urljoin(self.currentUri, uri)
return uri
def _request_url(self, document, url, stream):
f = self._open_uri(url)
stream.write(f.read())
def _is_relative_to_server(self, url):
parts = urlparse.urlparse(url)
if parts[0] or parts[1]:
return False
return True
gobject.type_register(GtkHtml2BrowserView)
if __name__ == "__main__":
win = gtk.Window()
view = GtkHtml2BrowserView()
view.set_size_request(600,400)
win.add(view)
win.show_all()
view.loadUri("http://www.skype.com/company/legal/eula/")
gtk.main()
# (c) 2005-2007 Canonical - GPL
#
# Authors:
# Michael Vogt
import warnings
warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
import apt
import os
class MyCache(apt.Cache):
def __init__(self, progress=None):
apt.Cache.__init__(self, progress)
# cache the arch we use
pipe = os.popen("dpkg --print-architecture")
self._arch = pipe.read().strip()
del pipe
assert self._depcache.BrokenCount == 0
def pkgDependsOn(self, pkgname, depends_name):
""" check if a given pkg depends on a given dependencie """
if not self.has_key(pkgname):
return False
pkg = self[pkgname]
candver = self._depcache.GetCandidateVer(pkg._pkg)
if candver == None:
return False
dependslist = candver.DependsList
for dep in dependslist.keys():
if dep == "Depends" or dep == "PreDepends":
# get the list of each dependency object
for depVerList in dependslist[dep]:
for z in depVerList:
# get all TargetVersions of
# the dependency object
for tpkg in z.AllTargets():
if depends_name == tpkg.ParentPkg.Name:
return True
return False
def clean(self):
self._depcache.Init()
# FIXME: those assert may be a bit too strong,
# we may just rebuild the cache if something is
# wrong
if self._depcache.BrokenCount > 0:
print " ".join([pkg.name for pkg in self if self._depcache.IsNowBroken(pkg._pkg)])
# desperately try again to init the damm cache
self._depcache.Init()
if self._depcache.DelCount > 0:
print " ".join([pkg.name for pkg in self if pkg.markedDelete])
# desperately try again to init the damm cache
self._depcache.Init()
# broken packages can happen (e.g. when java install is canceled)
# ignore it
#assert self._depcache.BrokenCount == 0
assert self._depcache.DelCount == 0
def getArch(self):
""" Return the cpu architecture of the system"""
return self._arch
def getDependantAutoDeps(self, to_rm):
""" return the installed automatic dependencies for the selected set
of packages that are going to be removed """
auto_deps = set()
for pkg in to_rm:
self[pkg].markDelete()
for pkg in self:
if not pkg.markedDelete and self._depcache.IsGarbage(pkg._pkg):
#print "%s is garbage" % pkg.name
for rm_package in to_rm:
# check if pkg.name is a dependency of rm_package
if self.pkgDependsOn(rm_package, pkg.name):
print "%s is garbage and a dep of %s" % (pkg.name, rm_package)
auto_deps.add(pkg.name)
#print auto_deps
return auto_deps
# (c) 2005-2007 Canonical - GPL
# (c) 2006-2007 Sebastian Heinlein
#
# Authors:
# Michael Vogt
# Sebastian Heinlein
#
import xdg.Menu
import sys
import os
import pickle
import glob
from Util import *
from gettext import gettext as _
class CoreApplicationMenu(object):
"""This class provides basic menu handling that is required to
initialize the app-install cache"""
debug = 0
def __init__(self, datadir):
self.menudir = datadir+"/desktop"
# a set of seen desktop entries
self.desktopEntriesSeen = set()
# a dictonary that provides a mapping from a pkg to the
# application names it provides
self.pkg_to_app = {}
# cache
self.pickle = {}
self.popcon_max = 10
def createMenuCache(self, targetdir, fname="menu.p"):
self.desktopEntriesSeen.clear()
self.pkg_to_app.clear()
for mpath in glob.glob(os.path.join(self.menudir, "*.menu")):
menu = xdg.Menu.parse(mpath)
self._populateFromEntry(menu)
pickle.dump(self.pickle, open('%s/%s' % (targetdir,fname),'w'), 2)
def _populateFromEntry(self, node, parent=None, progress=None):
# for some reason xdg hiddes some entries, but we don't like that
for entry in node.getEntries(hidden=True):
self._dbg(2, "entry: %s" % (entry))
if isinstance(entry, xdg.Menu.Menu):
# we found a toplevel menu
name = xmlescape(entry.getName())
self._dbg(1, "we have a sub-menu %s " % name)
item = Category(self, name, entry.getIcon())
#print "adding: %s" % name
self.pickle[item] = []
self._populateFromEntry(entry, item, progress=progress)
elif isinstance(entry, xdg.Menu.MenuEntry):
# more debug output
self._dbg(3, node.getPath() + "/\t" + entry.DesktopFileID + "\t" + entry.DesktopEntry.getFileName())
# we found a application
name = xmlescape(entry.DesktopEntry.getName())
self._dbg(1, "we have a application %s (%s) " % (name,entry.DesktopFileID))
if name and entry.DesktopEntry.hasKey("X-AppInstall-Package"):
self._dbg(2,"parent is %s" % parent.name)
# check for duplicates, caused by e.g. scribus that has:
# Categories=Application;Graphics;Qt;Office;
# so it appears in Graphics and Office
if entry.DesktopFileID in self.desktopEntriesSeen:
#print "already seen %s (%s)" % (name, entry)
continue
self.desktopEntriesSeen.add(entry.DesktopFileID)
item = Application(name)
# save the desktop entry to get the translations back later
item.desktop_entry = entry.DesktopEntry
pkgname = entry.DesktopEntry.get("X-AppInstall-Package")
item.pkgname = pkgname
# figure component and support status
item.component = entry.DesktopEntry.get("X-AppInstall-Section")
supported = entry.DesktopEntry.get("X-AppInstall-Supported")
if supported != "":
item.supported = bool(supported)
else:
if item.component == "main" or \
item.component == "restricted":
item.supported = True
# check for free software
if item.component == "main" or item.component == "universe":
item.free = True
else:
item.free = False
# check for third party apps
item.channel = entry.DesktopEntry.get("X-AppInstall-Channel")
item.isv = entry.DesktopEntry.get("X-AppInstall-ISV")
thirdparty = entry.DesktopEntry.get("X-AppInstall-Proprietary")
if thirdparty != "":
item.thirdparty = bool(thirdparty)
item.licenseUri = entry.DesktopEntry.get("X-AppInstall-LicenseUri")
# Supported architectures
archs = entry.DesktopEntry.get("X-AppInstall-Architectures", list=True)
if archs:
item.architectures.extend(archs)
# save replaces (e.g. totem-gstreamer replaces totem-xine)
replaces = entry.DesktopEntry.get("X-AppInstall-Replaces", list=True)
if replaces:
item.replaces = replaces
# Icon
item.iconname = entry.DesktopEntry.get("X-AppInstall-Icon", "") or entry.DesktopEntry.getIcon() or "applications-other"
if item.iconname.endswith(".png") or item.iconname.endswith(".xpm") or item.iconname.endswith(".svg"):
item.iconname = item.iconname[:-4]
item.comment = entry.DesktopEntry.getComment()
item.mime = entry.DesktopEntry.get('MimeType', list=True)
item.codecs = entry.DesktopEntry.get("X-AppInstall-Codecs").split(';')
item.patentBadness = entry.DesktopEntry.get("X-AppInstall-PatentBadness", type='boolean')
# popcon data
popcon_str = entry.DesktopEntry.get("X-AppInstall-Popcon")
if popcon_str != "":
popcon = int(popcon_str)
item.popcon = popcon
if popcon > self.popcon_max:
self.popcon_max = popcon
item.execCmd = entry.DesktopEntry.getExec()
item.needsTerminal = entry.DesktopEntry.getTerminal()
# we map "Settings" to "Other" in the g-a-i GUI but
# not in the real gnome-menu. so do not display a
# menu path here (FIXME: guess it from the category)
if not "Settings" in entry.DesktopEntry.getCategories():
item.menupath = [_("Applications"),parent.name]
else:
item.menupath = None
self.pickle[parent].append(item)
elif name:
try:
print "Skipped %s: not associated with a package" % entry
except UnicodeEncodeError:
pass
else:
try:
print "Skipped %s: does not include a menu name" % entry
except UnicodeEncodeError:
pass
elif isinstance(entry, xdg.Menu.Header):
print "got header"
def _dbg(self, level, msg):
"""Write debugging output to sys.stderr."""
if level <= self.debug:
print >> sys.stderr, msg
class MenuItem(object):
" base class for a object in the menu "
def __init__(self, name, iconname="applications-other"):
# the name that is displayed
self.name = name
# the icon that is displayed
self.iconname = iconname
self.icontheme = None
def __repr__(self):
return "MenuItem: %s" % self.name
class Category(MenuItem):
""" represents a category """
def __init__(self, parent, name, iconname="applications-other"):
MenuItem.__init__(self, name, iconname)
class Application(MenuItem):
""" this class represents a application """
def __init__(self, name, iconname="applications-other"):
MenuItem.__init__(self, name, iconname)
# the apt-pkg name that belongs to the app
self.pkgname = None
# the desktop file comment
self.comment = ""
# mime type
self.mime = None
# exec
self.execCmd = None
# needsTerminal
self.needsTerminal = False
# component the package is in (main, universe, multiverse, restricted)
self.component = None
# channel the pacakge is in (e.g. skype)
self.channel = None
# Name of the independent software vendor
self.isv = None
# states
self.popcon = 1 # the raw popcon data
self.rank = 1 # used by the ranking algo
# licence and support
self.free = False
self.licenseUri = None
self.supported = False
self.thirdparty = False
self.architectures = []
# textual menu path
self.menupath = ""
# install status
self.toInstall = None
# (c) 2005 Canonical, GPL
from SimpleGladeApp import SimpleGladeApp
import gtk
import gobject
import os
from gettext import ngettext
from gettext import gettext as _
from Util import *
from widgets.AppListView import AppListView
class AppListViewComplete(AppListView):
def __init__(self, cache=None, menu=None, icons=None, executable=False):
AppListView.__init__(self, style=1)
self.executable = executable
self.connect("row-activated", self.on_row_activated)
def set_executable(self, value):
self.executable = value
def on_row_activated(self, treeview_packages, path, column):
if self.executable != True:
return False
if os.getuid() == 0:
return False
store = self.get_model()
treeiter = store.get_iter(path)
(name, item, popcon) = store[treeiter]
cmd_parts = []
command = item.execCmd
terminal = item.needsTerminal
if command == "": return
for part in command.split():
while True:
# two consecutive '%' characters represent an actual '%'
if len(part) >= 2 and part[:2] == '%%':
cmd_parts.append('%')
part = part[2:]
continue
# we're running the command without any options, so strip
# out placeholders
if part[0] == '%': break
# if the last part was an actual '%', we don't want to join
# it with a space, so do it by hand
if cmd_parts[-1:] == '%':
part = '%' + part
cmd_parts[-1:] = part
break
cmd_parts.append(part)
break
if terminal:
command = " ".join(cmd_parts)
command = "gnome-terminal --command=\"" + command + "\""
cmd_parts = command.split()
# run program
os.spawnvp(os.P_NOWAIT, cmd_parts[0], cmd_parts)
class DialogComplete(SimpleGladeApp):
def __init__(self, datadir, parent, to_add, to_rm, cache, auto_close=False):
def add_apps_to_store(apps, store):
for app in apps:
store.append([app.name, app, 0])
SimpleGladeApp.__init__(self,
path="/usr/share/gnome-app-install/gnome-app-install.glade",
root="window_complete",
domain="gnome-app-install")
self.cache = cache
self.auto_close = auto_close
self.store = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)
if parent:
self.window_complete.set_transient_for(parent)
self.treeview = AppListViewComplete()
self.scrolledwindow_complete.add(self.treeview)
self.treeview.set_headers_visible(False)
self.treeview.set_model(self.store)
self.treeview.show()
# Identify failed and exectuable applications and extras
# (stuff without execCmd lines like codecs)
failed_apps = []
failed_extras = []
installed_apps = []
installed_extras = []
self.install_failures = False
for app in to_add:
pkg = app.pkgname
available = cache.has_key(pkg)
installed = available and cache[pkg].isInstalled
if not available:
if app.execCmd != "":
failed_apps.append(app)
else:
failed_extras.append(app)
elif not installed:
if app.execCmd != "":
failed_apps.append(app)
else:
failed_extras.append(app)
elif installed and app.execCmd != '':
installed_apps.append(app)
elif installed and app.execCmd == '':
installed_extras.append(app)
for app in to_rm:
pkg = app.pkgname
if self.cache.has_key(pkg) and self.cache[pkg].isInstalled:
if app.execCmd != "":
failed_apps.append(app)
else:
failed_extras.append(app)
# record if anything failed (for auto_close)
if failed_extras or failed_apps:
self.install_failures = True
# Connect the signals
self.button_complete_retry.connect("clicked",
self.on_button_retry_clicked)
self.button_complete_more.connect("clicked",
self.on_button_more_clicked)
self.button_complete_close.connect("clicked",
self.on_button_close_clicked)
self.window_complete.connect("delete-event",
self.on_delete)
# Adjust the dialog text
if (len(failed_apps) > 0 or len(failed_extras) > 0) and len(to_rm) == 0:
if len(failed_extras) > 0:
header = _("Software installation failed")
body = _("There has been a problem during the installation "
"of the following pieces of software.")
self.button_complete_more.set_label(_("Add/Remove More Software"))
else:
header = _("Application installation failed")
body = _("There has been a problem during the installation "
"of the following applications.")
add_apps_to_store(failed_apps, self.store)
self.image_complete_icon.set_from_stock(gtk.STOCK_DIALOG_ERROR,
gtk.ICON_SIZE_DIALOG)
self.button_complete_retry.show()
elif (len(failed_apps) > 0 or len(failed_extras)> 0) and\
len(to_add) == 0:
if len(failed_extras) > 0:
header = _("Software could not be removed")
body = _("There has been a problem during the removal "
"of the following pieces of software.")
self.button_complete_more.set_label(_("Add/Remove More Software"))
else:
header = _("Not all applications could be removed")
body = _("There has been a problem during the removal "
"of the following applications.")
add_apps_to_store(failed_apps, self.store)
add_apps_to_store(failed_extras, self.store)
self.image_complete_icon.set_from_stock(gtk.STOCK_DIALOG_ERROR,
gtk.ICON_SIZE_DIALOG)
self.button_complete_retry.show()
elif len(failed_extras) > 0 or len(failed_apps) > 0:
#FIXME: perhaps separate widgets would make more sence
if len(failed_extras) > 0:
header = _("Installation and removal of software failed")
body = _("There has been a problem during the installation or "
"removal of the following pieces of software.")
self.button_complete_more.set_label(_("Add/Remove More Software"))
else:
header = _("Installation and removal of applications failed")
body = _("There has been a problem during the installation or "
"removal of the following applications.")
add_apps_to_store(failed_apps, self.store)
add_apps_to_store(failed_extras, self.store)
self.button_complete_retry.show()
self.image_complete_icon.set_from_stock(gtk.STOCK_DIALOG_ERROR,
gtk.ICON_SIZE_DIALOG)
elif len(installed_apps) > 0:
header = ngettext(_("New application has been installed"),
_("New applications have been installed"),
len(installed_apps))
add_apps_to_store(installed_apps, self.store)
# we do not support launching apps when runing as root
if os.getuid() == 0:
body = _("To start a newly installed application, "
"choose it from the applications menu.")
else:
body = _("To start a newly installed application "
"double click on it.")
self.treeview.set_executable(True)
elif len(installed_extras) > 0:
header = _("Software has been installed successfully")
body = _("Do you want to install or remove further " \
"software?")
self.scrolledwindow_complete.hide()
self.button_complete_more.set_label(_("Add/Remove More Software"))
else:
header = _("Applications have been removed successfully")
body = _("Do you want to install or remove further " \
"applications?")
self.scrolledwindow_complete.hide()
self.label_complete.set_markup("<b><big>%s</big></b>\n\n%s" % (header,
body))
def run(self):
if (self.auto_close and self.install_failures == False):
return gtk.RESPONSE_CLOSE
self.window_complete.show()
gtk.main()
return self._response
def _finish(self):
self.window_complete.hide()
gtk.main_quit()
def on_button_close_clicked(self, button):
self._response = gtk.RESPONSE_CLOSE
self._finish()
def on_button_retry_clicked(self, button):
self._response = 1
self._finish()
def on_button_more_clicked(self, button):
self._response = 2
self._finish()
def on_delete(self, widget, event):
self._response = gtk.RESPONSE_CLOSE
self._finish()
return gtk.TRUE
if __name__ == "__main__":
from AppInstall.CoreMenu import CoreApplicationMenu
from AppInstall.DialogComplete import DialogComplete
import gtk
import apt
import cPickle
import pdb
cache = apt.Cache()
progress = apt.progress.OpTextProgress()
to_add = []
datadir = "/usr/share/app-install"
desktopdir = "/usr/share/app-install"
cachedir = "/var/cache/app-install"
treeview_categories = gtk.TreeView()
treeview_packages = gtk.TreeView()
menu = CoreApplicationMenu(datadir)
menu.pickle = cPickle.load(open("/var/cache/app-install/menu.p"))
available = []
available_extras = []
installed = []
installed_extras = []
print menu.pickle.keys()
for app in menu.pickle[menu.pickle.keys()[0]]:
if cache.has_key(app.pkgname) and cache[app.pkgname].isInstalled:
if app.execCmd:
installed.append(app)
else:
installed_extras.append(app)
else:
if app.execCmd:
available.append(app)
else:
available_extras.append(app)
to_rm = []
while True:
pdb.set_trace()
dia = DialogComplete(datadir, None, to_add, to_rm, cache)
dia.run()
# (c) 2005 Canonical, GPL
from SimpleGladeApp import SimpleGladeApp
import gtk
import gobject
import os
from Util import *
from gettext import gettext as _
from widgets.AppListView import AppListView
class DialogMultipleApps(SimpleGladeApp):
def __init__(self, datadir, parent, multiple_items_list, name, remove):
SimpleGladeApp.__init__(self,
path=datadir+"/gnome-app-install.glade",
root="dialog_multiple_apps",
domain="gnome-app-install")
self.store = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)
for elm in multiple_items_list:
self.store.append((elm.name, elm, 0))
self.dialog_multiple_apps.set_transient_for(parent)
# Setup the application list
self.treeview_apps = AppListView(style=1)
self.scrolledwindow_multiple_apps.add(self.treeview_apps)
self.treeview_apps.set_headers_visible(False)
self.treeview_apps.set_model(self.store)
self.treeview_apps.show()
# Create the dialog message text
if remove == True:
header = (_("Remove %s and bundled applications?") % name)
msg = _("%s is part of a software collection. If you remove "
"%s, you will remove all bundled applications as well.") %\
(name, name)
label = _("_Remove All")
else:
header = (_("Install %s and bundled applications?") % name)
msg = _("%s is part of a software collection. If you install "
"%s, you will install all bundled applications as well.") %\
(name, name)
label = _("_Install All")
self.label_multiple.set_markup("<b><big>%s</big></b>\n\n%s" %\
(header, msg))
self.button_multiple_action.set_label(label)
def run(self):
return self.dialog_multiple_apps.run()
def hide(self):
self.dialog_multiple_apps.hide()
# (c) 2005 Canonical, GPL
from SimpleGladeApp import SimpleGladeApp
import gtk
import gobject
import os
from Util import *
from widgets.AppListView import AppListView
class DialogPendingChanges(SimpleGladeApp):
def __init__(self, datadir, parent, to_add, to_rm):
SimpleGladeApp.__init__(self,
path=datadir+"/gnome-app-install.glade",
root="dialog_pending_changes",
domain="gnome-app-install")
self.add_store = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)
self.remove_store = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)
for elm in to_add:
self.add_store.append([elm.name, elm, 0])
for elm in to_rm:
self.remove_store.append([elm.name, elm ,0])
self.dialog_pending_changes.realize()
self.dialog_pending_changes.set_transient_for(parent)
self.button_confirm_changes.grab_default()
self.dialog_pending_changes.window.set_functions(gtk.gdk.FUNC_MOVE)
# Setup the app list viewers
self.treeview_add = AppListView(style=1)
self.treeview_remove = AppListView(style=1)
self.scrolledwindow_add.add(self.treeview_add)
self.scrolledwindow_remove.add(self.treeview_remove)
self.treeview_add.set_headers_visible(False)
self.treeview_remove.set_headers_visible(False)
self.treeview_add.set_model(self.add_store)
self.treeview_remove.set_model(self.remove_store)
self.treeview_add.show()
self.treeview_remove.show()
def run(self):
if len(self.add_store) == 0:
self.vbox_add.hide()
if len(self.remove_store) == 0:
self.vbox_remove.hide()
return self.dialog_pending_changes.run()
def hide(self):
self.dialog_pending_changes.hide()
# (c) 2005 Canonical, GPL
from SimpleGladeApp import SimpleGladeApp
import gtk
import gobject
import os
from gettext import gettext as _
import gettext
from BrowserView import GtkHtml2BrowserView as BrowserView
class DialogProprietary(SimpleGladeApp):
def __init__(self, datadir, parent, item):
SimpleGladeApp.__init__(self,
path=datadir+"/gnome-app-install.glade",
root="dialog_proprietary",
domain="gnome-app-install")
# Create the text of the dialog
if item.isv:
vendor = item.isv
else:
vendor = item.channel
header = _("Enable the installation of software "
"from %s?") % vendor
body = _("%s is provided by a third party vendor.") % item.name
internet = _("You need a working internet connection to continue.")
msg = "<b><big>%s</big></b>\n\n%s\n\n%s" % (header, body, internet)
self.dialog_proprietary.set_transient_for(parent)
self.dialog_proprietary.realize()
self.dialog_proprietary.window.set_functions(gtk.gdk.FUNC_MOVE)
self.label_proprietary.set_markup(msg)
self.item = item
self.button_add_channel.set_label(_("_Enable"))
def run(self):
if self.item.licenseUri:
msg = self.label_proprietary.get_label()
msg += "\n\n"
msg += _("The application comes with the following license "
"terms and conditions. Click on the "
"'Enable' button to accept them:")
self.label_proprietary.set_markup(msg)
self.tooltips = gtk.Tooltips()
self.tooltips.set_tip(self.button_add_channel, \
_("Accept the license terms and install "\
"the software"))
self.browser.show()
self.browser.loadUri(self.item.licenseUri)
else:
self.browser.hide()
self.button_add_channel.grab_default()
return self.dialog_proprietary.run()
def hide(self):
self.dialog_proprietary.hide()
def create_proprietary_browser_view(self, s1, s2, i1, i2):
#print "create_custom_browser_view()"
self.browser = BrowserView()
return self.browser
if __name__ == "__main__":
import sys
class Item(object):
pass
item = Item()
item.licenseUri = sys.argv[1]
item.channel = sys.argv[1]
dia = DialogProprietary("../data/", None, item)
dia.run()
# (c) 2005-2007 Canonical - GPL
# (c) 2006-2007 Sebastian Heinlein
#
# Authors:
# Michael Vogt
# Sebastian Heinlein
#
import gtk
import gtk.gdk
import gobject
import xdg.Menu
import sys
import os
import gettext
import gst
from warnings import warn
from gettext import gettext as _
from Util import *
from CoreMenu import *
# possible filter states for the application list - match the layout in
# data/gnome-app-install.schemas.in
( SHOW_ALL,
SHOW_ONLY_FREE,
UNUSED_1,
SHOW_ONLY_SUPPORTED,
SHOW_ONLY_THIRD_PARTY,
UNUSED_2,
SHOW_ONLY_INSTALLED,
SHOW_ONLY_MAIN,
SHOW_ONLY_PROPRIETARY,
) = range(9)
PIMP_APPS = ["gstreamer0.10-plugins-ugly",
"gstreamer0.10-ffmpeg",
"sun-java5-plugin",
"flashplugin-nonfree",
"ubuntu-restricted-extras"]
class NullActivationStyleForMenu:
# See class ActivationStyle in gnome-app-install; that class
# would do just fine here except that it's upside-down from a
# layering POV.
def __init__(self):
self.selectFilter = None
self.menuFilter = None
def isApproved(self, component, pkgname): return True
def menuCacheName(self): return "menu.p"
class ApplicationMenu(CoreApplicationMenu):
""" this represents the application menu, the interessting bits are:
- store that can be attached to a TreeView
- pkg_to_app a dictionary that maps the apt pkgname to the application
items
"""
debug = 0
def __init__(self, datadir, cachedir, cache,
treeview_packages, progress,
filter=SHOW_ONLY_SUPPORTED, dontPopulate=False,
activation_style=NullActivationStyleForMenu()):
CoreApplicationMenu.__init__(self, datadir)
self.cache = cache
self.treeview_packages = treeview_packages
self.activationStyle = activation_style
# icon theme
self.icons = gtk.icon_theme_get_default()
self.icons.append_search_path(os.path.join(datadir, "icons"))
# search
self.searchTerms = []
# properties for the view
if self.activationStyle.menuFilter is not None:
self.filter = self.activationStyle.menuFilter
else:
self.filter = filter
# the categories
self.real_categories_store = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT)
if dontPopulate:
return
# populate the tree
# use cached self.pickle (should be renamed to self.categories)
# and cache self.pkgs_to_app
cacheLoaded = False
cname = activation_style.menuCacheName()
if cachedir is not None and os.path.exists("%s/%s" % (cachedir,cname)):
progress.label_action.set_label(_("Loading cache..."))
import cPickle
try:
self.pickle = cPickle.load(open("%s/%s" % (cachedir,cname)))
cacheLoaded = True
except:
pass
if not cacheLoaded:
progress.label_action.set_label(_("Collecting application data..."))
self.desktopEntriesSeen.clear()
menu = xdg.Menu.parse(os.path.join(self.menudir, "applications.menu"))
self._populateFromEntry(menu)
# refresh based on the pickled information
self.refresh(progress)
self.store = self.real_categories_store
def get_categories_store(self):
return self.real_categories_store
# helpers
def _refilter(self):
# we need to disconnect the model from the view when we
# do a refilter, otherwise we get random crashes in the search
# (to reproduce:
# 1. open "accessability" 2. unselect "show unsupported"
# 3. search for "apt" 4. turn "show unsupported" on/off -> BOOM
model = self.treeview_packages.get_model()
# save the cursor position (or rather, the name of the app selected)
name = None
(path, colum) = self.treeview_packages.get_cursor()
if path:
name = model.get_value(model.get_iter(path), COL_NAME)
#print "found: %s (%s) " % (name, path)
# this is the actual refiltering
self.treeview_packages.set_model(None)
if model != None:
model.get_model().refilter()
self.treeview_packages.set_model(model)
# redo the cursor
if name != None:
for it in iterate_list_store(model, model.get_iter_first()):
aname = model.get_value(it, COL_NAME)
if name == aname:
#print "selecting: %s (%s)" % (name, model.get_path(it))
#self.treeview_packages.expand_to_path(model.get_path(it))
self.treeview_packages.set_cursor(model.get_path(it))
return
elif len(model) > 0:
self.treeview_packages.set_cursor(0)
def _ranking_sort_func(self, model, iter1, iter2):
"""
Sort by the search result rank
"""
#print "_sort_func()"
item1 = model.get_value(iter1, COL_ITEM)
item2 = model.get_value(iter2, COL_ITEM)
if item1 == None or item2 == None:
return 0
if item1.rank < item2.rank: return 1
elif item1.rank > item2.rank: return -1
else: return 0
def _visible_filter(self, model, iter):
item = model.get_value(iter, COL_ITEM)
#print "_visible_filter: ", item
if item:
# check for the various view settings
if not self.activationStyle.isApproved(
item.component, item.pkgname):
return False
if self.filter == SHOW_ONLY_MAIN and item.component != "main":
return False
if self.filter == SHOW_ONLY_SUPPORTED and item.supported != True:
return False
if self.filter == SHOW_ONLY_FREE and item.free == False:
return False
if self.filter == SHOW_ONLY_PROPRIETARY and item.free == True:
return False
if self.filter == SHOW_ONLY_THIRD_PARTY and item.thirdparty != True:
return False
if self.filter == SHOW_ONLY_INSTALLED and not \
self.itemIsInstalled(item):
return False
# Allow to only show a subset by the activation filter
if (self.activationStyle.selectFilter is not None and
not self._activationStyleFilter(item)):
return False
# if we search, do the ranking updates
if len(self.searchTerms) > 0:
rank = self._filterAndRank(item)
if rank == None:
return False
else:
item.rank = rank
return True
def _filterAndRank(self, item):
"""
Watch out, Google!
"""
trigger = ""
rank = 100 * item.popcon / self.popcon_max
# the normal case
for term in self.searchTerms:
hit = False
if term == item.name.lower() or \
term == item.pkgname.lower():
rank += 100
hit = True
if term in item.name.lower():
rank += 30
trigger += " name"
hit = True
if term in item.pkgname.lower():
rank += 30
trigger += " pkg_name"
hit = True
if self._mimeMatch(item, term, fuzzy=True):
rank += 25
trigger += " mime"
hit = True
if self._codecMatch(item, term, fuzzy=True):
rank += 15
trigger += " codec"
hit = True
if self.cache.has_key(item.pkgname) and \
term in self.cache[item.pkgname].description.lower():
rank += 10
trigger += " pkg_desc"
hit = True
if hit == False:
return None
if item.pkgname.lower() in PIMP_APPS:
rank += 75
#print "found %s (%s/%s): %s" % (item.name, item.popcon, rank, trigger)
return rank
def _mimeMatch(self, item, term, fuzzy=False):
for pattern in item.mime:
if fuzzy and term in pattern:
return True
elif not fuzzy and pattern == term:
return True
return False
def _codecMatch(self, item, term, fuzzy=False):
#print "_codecMatch for pkg '%s' (term: %s) " % (item.pkgname, term)
if ":" in term:
term = term.split(":")[1]
search_cap = gst.caps_from_string(term)
#print "search_cap: ", search_cap
for codec in item.codecs:
if ":" in codec:
codec = codec.split(":")[1]
if fuzzy and term in codec:
return True
else:
cap = gst.caps_from_string(codec)
#print "codec: ",codec
#print "cap: ",cap
if (cap and search_cap and
(search_cap & cap)):
return True
return False
def _activationStyleFilter(self, item):
#print "_activationStyleFilter(): ",item
filter = self.activationStyle.selectFilter(self)
if (self.activationStyle.isInstallerOnly and
self.itemIsInstalled(item)):
return False
for term in self.activationStyle.searchTerms():
if filter(item, term):
return True
return False
def doMimeSearch(self, mime_type, fuzzy=False):
res = set()
model = self.real_categories_store.get_value(self.all_category_iter, COL_CAT_ITEM).all_applications
for it in iterate_list_store(model, model.get_iter_first()):
item = model.get_value(it, COL_ITEM)
for re_pattern in item.mime:
# mvo: we get a list of regexp from
# pyxdg.DesktopEntry.getMimeType, but it does not
# use any special pattern at all, so we use the plain
# pattern (e.g. text/html, audio/mp3 here)
pattern = re_pattern.pattern
if fuzzy and mime_type in pattern:
res.add(item)
elif not fuzzy and re_pattern.match(mime_type):
res.add(item)
return res
def refreshAfterCacheChange(self, progress):
#print "refreshAfterCacheChange"
# FIXME: progress information here?
for cat in self.pickle:
for item in self.pickle[cat]:
#print item
item.toInstall = (self.cache.has_key(item.pkgname) and
self.cache[item.pkgname].isInstalled)
def refresh(self, progress):
self.real_categories_store.clear()
progress.subOp = _("Loading applications...")
progress.update(0)
# add "All" category
self.all_category_iter = self.real_categories_store.append()
item = Category(self, "<b>%s</b>" % _("All"), "distributor-logo")
self.initListStores(item, self)
self.real_categories_store.set(self.all_category_iter,
COL_CAT_NAME, "<b>%s</b>" % _("All"),
COL_CAT_ITEM, item)
# now go for the categories
i=0
lenx=len(self.pickle.keys())
keys = self.pickle.keys()
keys.sort(cmp=lambda x,y: cmp(x.name.lower(), y.name.lower()))
for category in keys:
progress.subOp = _("Loading %s...")% category.name
self.initListStores(category, self)
self.real_categories_store.set(self.real_categories_store.append(),
COL_CAT_NAME, category.name,
COL_CAT_ITEM, category,)
i += 1
progress.update(i/float(lenx)*100.0)
for item in self.pickle[category]:
# add to category
category.all_applications.append([item.name,
item,
item.popcon])
# add to all
store = self.real_categories_store.get_value(self.all_category_iter, COL_ITEM).all_applications
store.append([item.name, item, item.popcon])
# do the popcon_max calculation
if item.popcon > self.popcon_max:
self.popcon_max = item.popcon
# populate the pkg_to_app data structure
pkgname = item.pkgname
if not self.pkg_to_app.has_key(pkgname):
self.pkg_to_app[pkgname] = set()
self.pkg_to_app[pkgname].add(item)
# now update the cache dependant part
self.refreshAfterCacheChange(progress)
def itemAvailable(self, item):
""" returns True if the item is available in the current
apt cache """
return self.cache.has_key(item.pkgname)
def itemIsInstalled(self, item):
""" returns True if the item is currently installed """
return (self.cache.has_key(item.pkgname) and
self.cache[item.pkgname].isInstalled)
def initListStores(self, category, parent):
# if that category has applications, add them to the
# store here
category.all_applications = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_INT)
# set the visible filter
category.filtered_applications = category.all_applications.filter_new()
category.filtered_applications.set_visible_func(parent._visible_filter)
category.applications = gtk.TreeModelSort(category.filtered_applications)
def getChanges(self, get_paths=False):
""" return the selected changes in the tree
TODO: what is get_paths?
"""
to_inst = set()
to_rm = set()
for (name, item) in self.store:
for (name,item,popcon) in item.all_applications:
if self.itemIsInstalled(item) and not item.toInstall:
to_rm.add(item)
if not self.itemIsInstalled(item) and item.toInstall:
to_inst.add(item)
#print "to_add: %s" % to_inst
#print "to_rm: %s" % to_rm
return (to_inst, to_rm)
def isChanged(self):
""" check if there are changes at all """
for (cat_name, cat) in self.store:
for (name,item,popcon) in cat.all_applications:
if item.toInstall != self.itemIsInstalled(item):
return True
return False
def _dbg(self, level, msg):
"""Write debugging output to sys.stderr."""
if level <= self.debug:
print >> sys.stderr, msg
if __name__ == "__main__":
print "testing the menu"
desktopdir = "/usr/share/app-install"
from Util import MyCache
cache = MyCache()
treeview = gtk.TreeView()
menu = ApplicationMenu(desktopdir, cache, treeview, treeview, apt.progress.OpProgress())
#matches = menu.doMimeSearch("mp3",fuzzy=True)
#print matches
#matches = menu.doMimeSearch("audio/mp3")
#print matches
# (c) 2005-2007 Canonical, GPL
import apt_pkg
import subprocess
import gtk
import gtk.gdk
import thread
import time
import os
import tempfile
from gettext import gettext as _
class PackageWorker:
"""
A class which does the actual package installing/removing.
"""
# synaptic actions
(INSTALL, UPDATE) = range(2)
def __init__(self, addon_cd=None):
self.addon_cd=addon_cd
def run_synaptic(self, id, lock, to_add=None,to_rm=None, action=INSTALL):
#apt_pkg.PkgSystemUnLock()
#print "run_synaptic(%s,%s,%s)" % (id, lock, selections)
cmd = []
if os.getuid() != 0:
cmd = ["/usr/bin/gksu",
"--desktop", "/usr/share/applications/synaptic.desktop",
"--"]
cmd += ["/usr/sbin/synaptic",
"--hide-main-window",
"--non-interactive",
"-o", "Synaptic::closeZvt=true",
"--parent-window-id", "%s" % (id) ]
# create tempfile for install (here because it must survive
# durng the synaptic call
f = tempfile.NamedTemporaryFile()
if action == self.INSTALL:
# setup the cdrom
if self.addon_cd:
cmd += ["-o","Acquire::cdrom::mount=%s" % self.addon_cd]
# install the stuff
for item in to_add:
f.write("%s\tinstall\n" % item)
#print item.pkgname
for item in to_rm:
f.write("%s\tuninstall\n" % item)
cmd.append("--set-selections-file")
cmd.append("%s" % f.name)
f.flush()
elif action == self.UPDATE:
#print "Updating..."
cmd.append("--update-at-startup")
self.return_code = subprocess.call(cmd)
lock.release()
f.close()
def plug_removed(self, w, (win,socket)):
# plug was removed, but we don't want to get it removed, only hiden
# unti we get more
win.hide()
return True
def plug_added(self, sock, win):
while gtk.events_pending():
win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
win.show()
#print "huhu"
gtk.main_iteration()
def get_plugged_win(self, window_main):
win = gtk.Window()
win.realize()
win.window.set_functions(gtk.gdk.FUNC_MOVE)
win.set_border_width(6)
win.set_transient_for(window_main)
win.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
win.set_title("")
win.set_resizable(False)
win.set_property("skip-taskbar-hint", True)
win.set_property("skip-taskbar-hint", True)
# prevent the window from closing with the delete button (there is
# a cancel button in the window)
win.connect("delete_event", lambda e,w: True);
# create the socket
socket = gtk.Socket()
socket.show()
win.add(socket)
socket.connect("plug-added", self.plug_added, win)
socket.connect("plug-removed", self.plug_removed, (win,socket))
return win, socket
def perform_action(self, window_main, cache, to_add=None, to_rm=None, action=INSTALL):
window_main.set_sensitive(False)
window_main.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
lock = thread.allocate_lock()
lock.acquire()
t = thread.start_new_thread(self.run_synaptic,(window_main.window.xid,lock,to_add, to_rm, action))
while lock.locked():
while gtk.events_pending():
gtk.main_iteration()
time.sleep(0.05)
window_main.set_sensitive(True)
window_main.window.set_cursor(None)
return self.return_code
# (c) 2005-2007 Canonical - GPL
#
# Authors:
# Michael Vogt
import warnings
warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
import apt
import apt_pkg
import gtk
# intervals of the start up progress
# 4x caching and menu creation
STEPS_UPDATE_CACHE = [ 12, 25, 37, 50, 100 ]
class GtkOpProgressWindow(apt.progress.OpProgress):
def __init__(self, glade, parent, steps=STEPS_UPDATE_CACHE):
self.steps = steps[:]
self.base = 0
self.old = 0
self.next = int(self.steps.pop(0))
self.window_progress = glade.get_widget("window_progress")
self.progressbar_cache = glade.get_widget("progressbar_cache")
self.label_action = glade.get_widget("label_action")
self.window_progress.realize()
self.window_progress.window.set_functions(gtk.gdk.FUNC_MOVE)
# make both GtkWindow and GdkWindow parents possible
if hasattr(parent, "window"):
parent = parent.window
if parent is not None:
self.window_progress.window.set_transient_for(parent)
def update(self, percent):
self.window_progress.show()
# if the old percent was higher, a new progress was started
if self.old > percent:
# set the borders to the next interval
self.base = self.next
try:
self.next = int(self.steps.pop(0))
except:
pass
progress = self.base + percent/100 * (self.next - self.base)
self.old = percent
self.progressbar_cache.set_fraction(progress/100)
if self.subOp != "":
self.label_action.set_markup("<i>"+"%s" % self.subOp+"</i>")
while gtk.events_pending():
gtk.main_iteration()
# using __del__ here sucks (because of eventual GC lazines)
# but there is no "complete" callback in apt yet and "Done"
# is called for each subOp
def __del__(self):
self.window_progress.hide()
class GtkCdromProgress(apt.progress.CdromProgress):
""" Report the cdrom add progress
Subclass this class to implement cdrom add progress reporting
"""
def __init__(self, parent):
self.progress = parent.progressbar_cache
self.status = parent.label_action
self.parent = parent
parent.window_progress.realize()
parent.window_progress.window.set_functions(gtk.gdk.FUNC_MOVE)
parent.window_progress.show()
parent.window_progress.set_transient_for(parent.window_main)
while gtk.events_pending():
gtk.main_iteration()
def update(self, text, step):
""" update is called regularly so that the gui can be redrawn """
if text:
self.status.set_text(text)
self.progress.set_fraction(step/float(self.totalSteps))
while gtk.events_pending():
gtk.main_iteration()
def askCdromName(self):
return (False, "")
def changeCdrom(self):
return False
"""
SimpleGladeApp.py
Module that provides an object oriented abstraction to pygtk and libglade.
Copyright (C) 2004 Sandino Flores Moreno
"""
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
import os
import sys
import re
import tokenize
import gtk
import gtk.glade
import weakref
import inspect
__version__ = "1.0"
__author__ = 'Sandino "tigrux" Flores-Moreno'
def bindtextdomain(app_name, locale_dir=None):
"""
Bind the domain represented by app_name to the locale directory locale_dir.
It has the effect of loading translations, enabling applications for different
languages.
app_name:
a domain to look for translations, tipically the name of an application.
locale_dir:
a directory with locales like locale_dir/lang_isocode/LC_MESSAGES/app_name.mo
If omitted or None, then the current binding for app_name is used.
"""
try:
import locale
import gettext
locale.setlocale(locale.LC_ALL, "")
gtk.glade.bindtextdomain(app_name, locale_dir)
gettext.install(app_name, locale_dir, unicode=1)
except (IOError,locale.Error), e:
print "Warning", app_name, e
__builtins__.__dict__["_"] = lambda x : x
class SimpleGladeApp:
def __init__(self, path, root=None, domain=None, **kwargs):
"""
Load a glade file specified by glade_filename, using root as
root widget and domain as the domain for translations.
If it receives extra named arguments (argname=value), then they are used
as attributes of the instance.
path:
path to a glade filename.
If glade_filename cannot be found, then it will be searched in the
same directory of the program (sys.argv[0])
root:
the name of the widget that is the root of the user interface,
usually a window or dialog (a top level widget).
If None or ommited, the full user interface is loaded.
domain:
A domain to use for loading translations.
If None or ommited, no translation is loaded.
**kwargs:
a dictionary representing the named extra arguments.
It is useful to set attributes of new instances, for example:
glade_app = SimpleGladeApp("ui.glade", foo="some value", bar="another value")
sets two attributes (foo and bar) to glade_app.
"""
if os.path.isfile(path):
self.glade_path = path
else:
glade_dir = os.path.dirname( sys.argv[0] )
self.glade_path = os.path.join(glade_dir, path)
for key, value in kwargs.items():
try:
setattr(self, key, weakref.proxy(value) )
except TypeError:
setattr(self, key, value)
self.glade = None
self.install_custom_handler(self.custom_handler)
self.glade = self.create_glade(self.glade_path, root, domain)
if root:
self.main_widget = self.get_widget(root)
else:
self.main_widget = None
self.normalize_names()
self.add_callbacks(self)
self.new()
def __repr__(self):
class_name = self.__class__.__name__
if self.main_widget:
root = gtk.Widget.get_name(self.main_widget)
repr = '%s(path="%s", root="%s")' % (class_name, self.glade_path, root)
else:
repr = '%s(path="%s")' % (class_name, self.glade_path)
return repr
def new(self):
"""
Method called when the user interface is loaded and ready to be used.
At this moment, the widgets are loaded and can be refered as self.widget_name
"""
pass
def add_callbacks(self, callbacks_proxy):
"""
It uses the methods of callbacks_proxy as callbacks.
The callbacks are specified by using:
Properties window -> Signals tab
in glade-2 (or any other gui designer like gazpacho).
Methods of classes inheriting from SimpleGladeApp are used as
callbacks automatically.
callbacks_proxy:
an instance with methods as code of callbacks.
It means it has methods like on_button1_clicked, on_entry1_activate, etc.
"""
self.glade.signal_autoconnect(callbacks_proxy)
def normalize_names(self):
"""
It is internally used to normalize the name of the widgets.
It means a widget named foo:vbox-dialog in glade
is refered self.vbox_dialog in the code.
It also sets a data "prefixes" with the list of
prefixes a widget has for each widget.
"""
for widget in self.get_widgets():
widget_name = gtk.Widget.get_name(widget)
prefixes_name_l = widget_name.split(":")
prefixes = prefixes_name_l[ : -1]
widget_api_name = prefixes_name_l[-1]
widget_api_name = "_".join( re.findall(tokenize.Name, widget_api_name) )
gtk.Widget.set_name(widget, widget_api_name)
if hasattr(self, widget_api_name):
raise AttributeError("instance %s already has an attribute %s" % (self,widget_api_name))
else:
setattr(self, widget_api_name, widget)
if prefixes:
gtk.Widget.set_data(widget, "prefixes", prefixes)
def add_prefix_actions(self, prefix_actions_proxy):
"""
By using a gui designer (glade-2, gazpacho, etc)
widgets can have a prefix in theirs names
like foo:entry1 or foo:label3
It means entry1 and label3 has a prefix action named foo.
Then, prefix_actions_proxy must have a method named prefix_foo which
is called everytime a widget with prefix foo is found, using the found widget
as argument.
prefix_actions_proxy:
An instance with methods as prefix actions.
It means it has methods like prefix_foo, prefix_bar, etc.
"""
prefix_s = "prefix_"
prefix_pos = len(prefix_s)
is_method = lambda t : callable( t[1] )
is_prefix_action = lambda t : t[0].startswith(prefix_s)
drop_prefix = lambda (k,w): (k[prefix_pos:],w)
members_t = inspect.getmembers(prefix_actions_proxy)
methods_t = filter(is_method, members_t)
prefix_actions_t = filter(is_prefix_action, methods_t)
prefix_actions_d = dict( map(drop_prefix, prefix_actions_t) )
for widget in self.get_widgets():
prefixes = gtk.Widget.get_data(widget, "prefixes")
if prefixes:
for prefix in prefixes:
if prefix in prefix_actions_d:
prefix_action = prefix_actions_d[prefix]
prefix_action(widget)
def custom_handler(self,
glade, function_name, widget_name,
str1, str2, int1, int2):
"""
Generic handler for creating custom widgets, internally used to
enable custom widgets (custom widgets of glade).
The custom widgets have a creation function specified in design time.
Those creation functions are always called with str1,str2,int1,int2 as
arguments, that are values specified in design time.
Methods of classes inheriting from SimpleGladeApp are used as
creation functions automatically.
If a custom widget has create_foo as creation function, then the
method named create_foo is called with str1,str2,int1,int2 as arguments.
"""
try:
handler = getattr(self, function_name)
return handler(str1, str2, int1, int2)
except AttributeError:
return None
def gtk_widget_show(self, widget, *args):
"""
Predefined callback.
The widget is showed.
Equivalent to widget.show()
"""
widget.show()
def gtk_widget_hide(self, widget, *args):
"""
Predefined callback.
The widget is hidden.
Equivalent to widget.hide()
"""
widget.hide()
def gtk_widget_grab_focus(self, widget, *args):
"""
Predefined callback.
The widget grabs the focus.
Equivalent to widget.grab_focus()
"""
widget.grab_focus()
def gtk_widget_destroy(self, widget, *args):
"""
Predefined callback.
The widget is destroyed.
Equivalent to widget.destroy()
"""
widget.destroy()
def gtk_window_activate_default(self, window, *args):
"""
Predefined callback.
The default widget of the window is activated.
Equivalent to window.activate_default()
"""
widget.activate_default()
def gtk_true(self, *args):
"""
Predefined callback.
Equivalent to return True in a callback.
Useful for stopping propagation of signals.
"""
return True
def gtk_false(self, *args):
"""
Predefined callback.
Equivalent to return False in a callback.
"""
return False
def gtk_main_quit(self, *args):
"""
Predefined callback.
Equivalent to self.quit()
"""
self.quit()
def main(self):
"""
Starts the main loop of processing events.
The default implementation calls gtk.main()
Useful for applications that needs a non gtk main loop.
For example, applications based on gstreamer needs to override
this method with gst.main()
Do not directly call this method in your programs.
Use the method run() instead.
"""
gtk.main()
def quit(self):
"""
Quit processing events.
The default implementation calls gtk.main_quit()
Useful for applications that needs a non gtk main loop.
For example, applications based on gstreamer needs to override
this method with gst.main_quit()
"""
gtk.main_quit()
def run(self):
"""
Starts the main loop of processing events checking for Control-C.
The default implementation checks wheter a Control-C is pressed,
then calls on_keyboard_interrupt().
Use this method for starting programs.
"""
try:
self.main()
except KeyboardInterrupt:
self.on_keyboard_interrupt()
def on_keyboard_interrupt(self):
"""
This method is called by the default implementation of run()
after a program is finished by pressing Control-C.
"""
pass
def install_custom_handler(self, custom_handler):
gtk.glade.set_custom_handler(custom_handler)
def create_glade(self, glade_path, root, domain):
return gtk.glade.XML(self.glade_path, root, domain)
def get_widget(self, widget_name):
return self.glade.get_widget(widget_name)
def get_widgets(self):
return self.glade.get_widget_prefix("")
# misc utils
# (c) 2005-2007 Canonical, GPL
# Authors:
# Michael Vogt
import os
# Column enumeration
# Columns of the categories store
(COL_CAT_NAME,
COL_CAT_ITEM) = range(0,2)
# Columns of the packages store
(COL_NAME,
COL_ITEM,
COL_POPCON) = range(3)
def xmlescape(s):
from xml.sax.saxutils import escape
if s==None:
return ""
else:
return escape(s)
def iterate_list_store(store, it):
""" iterate over a gtk tree-model, returns a gtk.TreeIter for each element
"""
if not it:
raise StopIteration
yield it
while True:
it = store.iter_next(it)
if it == None:
raise StopIteration
yield it
# class SimpleFilteredCache(apt.cache.FilteredCache):
# """ a simpler version of the filtered cache that will not react to
# cache changed (no need, we are only interessted in text)
# """
# def filterCachePostChange(self):
# pass
# def runFilter(self):
# self._reapplyFilter()
# class SearchFilter(apt.cache.Filter):
# """ a filter class that just searchs insensitive in name/description """
# def SetSearchTerm(self, term):
# self._term = term.lower()
# def apply(self, pkg):
# if self._term in pkg.name.lower() or \
# self._term in pkg.description.lower():
# return True
# else:
# return False
# def __init__(self, query=None):
# if query != None:
# self.SetSearchTerm(query)
VERSION="0.5.2.8-0ubuntu1"