summaryrefslogtreecommitdiff
path: root/geneticone/gui/gui_helper.py
diff options
context:
space:
mode:
Diffstat (limited to 'geneticone/gui/gui_helper.py')
-rw-r--r--geneticone/gui/gui_helper.py238
1 files changed, 238 insertions, 0 deletions
diff --git a/geneticone/gui/gui_helper.py b/geneticone/gui/gui_helper.py
new file mode 100644
index 0000000..5801d1a
--- /dev/null
+++ b/geneticone/gui/gui_helper.py
@@ -0,0 +1,238 @@
+#
+# File: geneticone/gui/gui_helper.py
+# This file is part of the Genetic/One-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2006 Necoro d.M.
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by Necoro d.M. <necoro@necoro.net>
+
+import geneticone
+from geneticone import flags
+
+from subprocess import *
+from threading import Thread
+
+import pty
+import vte
+
+class EmergeQueue:
+ """This class manages the emerge queue."""
+
+ def __init__ (self, tree = None, console = None, packages = None):
+ """Constructor.
+
+ @param tree: Tree to append all the items to. Default: None.
+ @type tree: gtk.TreeStore
+ @param console: Output is shown here. Default: None
+ @type console: vte.Terminal
+ @param packages: The list of packages sorted by categories. We will delete the appropriate category if we updated sth. Default: None
+ @type packages: dictionary: {category: list_of_packages}."""
+
+ self.mergequeue = []
+ self.unmergequeue = []
+ self.iters = {}
+ self.deps = {}
+ self.tree = tree
+ self.console = console
+ self.packages = packages
+
+ if self.tree:
+ self.emergeIt = self.tree.append(None, ["Emerge"])
+ self.unmergeIt = self.tree.append(None, ["Unmerge"])
+ else:
+ self.emergeIt = self.unmergeIt = None
+
+ def update_tree (self, it, cpv):
+ """This updates the tree recursivly.
+
+ @param it: iterator where to append
+ @type it: gtk.TreeIter
+ @param cpv: The package to append.
+ @type cpv: string (cat/pkg-ver)
+
+ @raise geneticone.BlockedException: When occured during dependency-calculation."""
+
+ # get depencies
+ if cpv in self.deps:
+ return # in list already
+ else:
+ deps = geneticone.find_packages("="+cpv)[0].get_dep_packages()
+ self.deps.update({cpv : deps})
+
+ subIt = self.tree.append(it, [cpv])
+
+ # recursive call
+ for d in deps:
+ try:
+ self.update_tree(subIt, d)
+ except geneticone.BlockedException, e:
+ # remove the project
+ while self.tree.iter_parent(subIt):
+ subIt = self.tree.iter_parent(subIt)
+ self.remove_children(subIt)
+ raise e
+
+ # add iter
+ self.iters.update({cpv: subIt})
+
+ def append (self, cpv, unmerge = False, update = False):
+ """Appends a cpv either to the merge queue or to the unmerge-queue.
+ Also updates the tree-view.
+
+ @param cpv: Package to add
+ @type cpv: string (cat/pkg-ver)
+ @param unmerge: Set to True if you want to unmerge this package - else False. Default: False
+ @type unmerge: boolean
+ @param update: Set to True if a package is going to be updated (e.g. if the use-flags changed). Default: False
+ @type update: boolean"""
+
+ if not unmerge:
+ try:
+ # insert dependencies
+ pkg = geneticone.find_packages("="+cpv)[0]
+ deps = pkg.get_dep_packages()
+
+ if update:
+ if deps == self.deps[cpv]:
+ return # nothing changed - return
+ else:
+ parentIt = self.tree.iter_parent(self.iters[cpv])
+ self.remove_children(self.iters[cpv], False) # this is needed to def delete everything
+ self.remove(self.iters[cpv], False)
+ self.update_tree(parentIt, cpv)
+ else: # not update
+ self.mergequeue.append(cpv)
+ if self.emergeIt: self.update_tree(self.emergeIt, cpv)
+
+ except geneticone.BlockedException, e : # there is sth blocked --> call blocked_dialog
+ blocks = e[0]
+ blocked_dialog(cpv, blocks)
+ return
+ else: # unmerge
+ self.unmergequeue.append(cpv)
+ if self.unmergeIt: # update tree
+ self.tree.append(self.unmergeIt, [cpv])
+
+ def _update_packages(self, packages, process = None):
+ """This updates the packages-list. It simply removes all affected categories so they have to be rebuilt.
+
+ @param packages: The packages which we emerged.
+ @type packages: list of cpvs
+ @param process: The process we have to wait for before we can do our work. Default: None.
+ @type process: subprocess.Popen"""
+
+ if process: process.wait()
+ for p in packages:
+ try:
+ cat = geneticone.split_package_name(p)[0] # get category
+ while cat[0] in ["=",">","<","!"]:
+ cat = cat[1:]
+ print "Category: "+cat ,
+ del self.packages[cat]
+ print "marked for refreshing"
+ except KeyError: # not in self.packages - ignore
+ pass
+
+ def _emerge (self, options, packages, it):
+ """Calls emerge and updates the terminal.
+
+ @param options: options to send to emerge
+ @type options: list
+ @param packages: packages to emerge
+ @type packages: list
+ @param it: Iterator which points to an entry whose children will be removed after completion.
+ @type it: gtk.TreeIter"""
+
+ # open tty
+ (master, slave) = pty.openpty()
+ self.console.set_pty(master)
+
+ # start emerge
+ process = Popen(["/usr/bin/python","/usr/bin/emerge"]+options+packages, stdout = slave, stderr = STDOUT, shell = False)
+ Thread(target=self._update_packages, args=(packages, process)).start()
+
+ # remove
+ self.remove_children(it)
+
+ def emerge (self, force = False):
+ """Emerges everything in the merge-queue.
+
+ @param force: If False, '-pv' is send to emerge. Default: False.
+ @type force: boolean"""
+
+ if len(self.mergequeue) == 0: return # nothing in queue
+
+ # prepare package-list
+ list = []
+ for k in self.mergequeue:
+ list += ["="+k]
+
+ s = []
+ if not force: s = ["-pv"]
+
+ self._emerge(s, list, self.emergeIt)
+
+ def unmerge (self, force = False):
+ """Unmerges everything in the umerge-queue.
+
+ @param force: If False, '-pv' is send to emerge. Default: False.
+ @type force: boolean"""
+
+ if len(self.unmergequeue) == 0: return # nothing in queue
+
+ list = self.unmergequeue[:] # copy the unmerge-queue
+
+ # set options
+ s = ["-C"]
+ if not force: s = ["-Cpv"]
+
+ self._emerge(s,list, self.unmergeIt)
+
+ def remove_children (self, parentIt, removeNewFlags = True):
+ """Removes all children of a given parent TreeIter recursivly.
+
+ @param parentIt: The iter from which to remove all children.
+ @type parentIt: gtk.TreeIter
+ @param removeNewFlags: True if new flags should be removed; False otherwise. Default: True.
+ @type removeNewFlags: boolean"""
+
+ childIt = self.tree.iter_children(parentIt)
+
+ while childIt:
+ if (self.tree.iter_has_child(childIt)): # recursive call
+ self.remove_children(childIt, removeNewFlags)
+ temp = childIt
+ childIt = self.tree.iter_next(childIt)
+ self.remove(temp, removeNewFlags)
+
+ def remove (self, it, removeNewFlags = True):
+ """Removes a specific item in the tree. This does not remove the top-entries.
+
+ @param it: Iterator which points to the entry we are going to remove.
+ @type it: gtk.TreeIter
+ @param removeNewFlags: True if new flags should be removed; False otherwise. Default: True.
+ @type removeNewFlags: boolean"""
+
+ if self.tree.iter_parent(it): # NEVER remove our top stuff
+ cpv = self.tree.get_value(it,0)
+ if self.tree.get_string_from_iter(it).split(":")[0] == self.tree.get_string_from_iter(self.emergeIt): # in Emerge
+ del self.iters[cpv]
+ del self.deps[cpv]
+ try:
+ self.mergequeue.remove(cpv)
+ except ValueError: # this is a dependency - ignore
+ pass
+ if removeNewFlags: flags.remove_new_use_flags(cpv)
+
+ else: # in Unmerge
+ self.unmergequeue.remove(cpv)
+
+ self.tree.remove(it)
+
+def blocked_dialog (blocked, blocks):
+ dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, blocked+" is blocked by "+blocks+".\nPlease unmerge the blocking package.")
+ dialog.run()
+ dialog.destroy()