Commits

Moises Henriquez committed 5aca1ae

Implementing uninstall functions and error reporting. Merged dialog.py widgets into message.py

Comments (0)

Files changed (5)

 from utils import repository
 from utils import vl
 from view import widgets
-from view import dialog
 from view import message
 import os
 import tempfile as tmp
     """ Top-level window for the vectorlinux multimedia
     add-on"""
     def _get_menubar(self):
+        """ returns the main menu bar used in the top-level window"""
         mb = gtk.MenuBar()
         filemenu = gtk.Menu()
         filem = gtk.MenuItem('_%s'% _('File'))
         filem.set_submenu(filemenu)
-        exit = gtk.MenuItem('_%s'% _('Exit'))
-        exit.connect('activate', self.exit)
-        filemenu.append(exit)
 
+        agr = gtk.AccelGroup()
+        self.add_accel_group(agr)
+        mquit = gtk.ImageMenuItem(gtk.STOCK_QUIT, agr)
+        key, mod = gtk.accelerator_parse("Q")
+        mquit.add_accelerator('activate', agr, key,
+                mod, gtk.ACCEL_VISIBLE)
+        mquit.connect('activate', self.exit)
+        filemenu.append(mquit)
         mb.append(filem)
-
         return mb
 
     def __init__(self):
         self.set_title(_('Vectorlinux Multimedia Bonus Disc'))
         self.connect('destroy', self.exit)
         self.set_position(gtk.WIN_POS_CENTER)
+        wicon = self.render_icon(gtk.STOCK_CDROM, gtk.ICON_SIZE_MENU)
+        self.set_icon(wicon)
 
         body = gtk.VBox()
         menu = self._get_menubar()
 
         pane = gtk.HPaned()
         pane.set_position(150)
-        body.pack_start(pane, True, True, 0)
+        body.pack_start(pane, True, True, 2)
         self.body = body
 
         # Create temporary slapt-getrc
         app_display = widgets.FancyAppList()
         self.display = app_display
         scrolled.add(app_display)
-        rpane.pack_start(scrolled, True, True, 0)
-        cache = vl.PackageCache()
+        rpane.pack_start(scrolled, True, True, 2)
+        cache = vl.PackageManager().cache
 
         lpane = widgets.CategoryPanel(
                 app_pool,
         lpane.add_category(icon = 'data/icons/Other.png',
                 label = _('Bonus'), overlay = False)
         lpane.add_category(icon = 'data/icons/applications-other.png',
-                label = _('Installed Only'),
+                label = _('Show Installed'),
                 overlay = True)
         self.categoriespanel = lpane
-        vpanel = gtk.VBox()
-        vpanel.pack_start(lpane, True, True, 0)
+#        vpanel = gtk.VBox()
+#        vpanel.pack_start(lpane, True, True, 0)
 
-        pane.pack1(vpanel)
+        pane.pack1(self.categoriespanel)
         pane.pack2(rpane)
         self._catpanel = lpane
         bottombar = gtk.HBox()
         bottombar.pack_end(btInstallSelected, False, False, 2)
 
         self.statusbar = gtk.Statusbar()
-        body.pack_start(self.statusbar, False, False, 0)
+        body.pack_start(self.statusbar, False, False, 2)
 
         self.resize(600, 400)
         self._stop_monitor = False
                     len(model), _('items displayed')))
                 self.actionbtn.set_property('sensitive', False)
                 gtk.gdk.threads_leave()
-            if self.categoriespanel._get_selected() == _('Installed Only'):
+            if self.categoriespanel._get_selected() == _('Show Installed'):
                 gtk.gdk.threads_enter()
                 self.actionbtn.set_property('label', _('Uninstall Selected'))
                 self.actionbtn.set_image(rimg)
 
     def install_btn_event(self, widget):
         todo = self._do_get_selected_items()
-        if self.categoriespanel._get_selected() == _('Installed Only'):
-            #        if widget.get_label() in (_('Installed Only')):
-            #           if _('Installed') in widget.get_label():
-            dia = message.Error(parent = self,
-                    text = _('Uninstall function not yet implemented'))
+        if _('Installed') in self.categoriespanel._get_selected():
+            dia = message.UninstallDialog(parent = self, pkglist = todo,
+                    categories = self.categoriespanel,
+                    view = self.display)
         else:
-            dia = dialog.InstallWindow(
-                    parent = self,
-                    pkglist = todo,
-                    slaptconfig = self.slaptgetrc)
+           dia = message.InstallDialog(parent = self, pkglist = todo, 
+                    slaptconfig = self.slaptgetrc.name, 
+                    categories = self.categoriespanel,
+                    view = self.display)
         if dia.run():
             self.body.set_property('sensitive', False)
+            self.categoriespanel.refresh_view()
             dia.destroy()
-#        gtk.gdk.threads_enter()
+
         self.body.set_property('sensitive', True)
-        self.categoriespanel.cache = vl.PackageCache()
-        self.categoriespanel.refresh_view()
+#        self.categoriespanel.cache = vl.PackageCache()
+#        self.categoriespanel.refresh_view()
         self.selbtn.set_property('label', _('Select All'))
-#        gtk.gdk.threads_leave()
 
     def _do_get_selected_items(self):
         ret = []
 import os
 import subprocess as sp
 
-try:
-    from ..view import message
-except:
-    import sys
-    sys.path.append(os.path.join(os.getcwd(), '..'))
+#try:
+#    from ..view import message
+#except:
+#    import sys
+#    sys.path.append(os.path.join(os.getcwd(), '..'))
+#    from view import message
 
-from view import message
+#        from view import message
 
 _author__ = 'Moises Henriquez'
 __author_email__ = 'moc.liamg@xnl.E0M'[::-1]
             self.configfile = configfile
 
         if not os.path.exists(self.manager):
-           dia = message.Error(
-                   text = _('slapt-get not installed in the system')
-                   )
-           if dia.run():
-               dia.destroy()
-
+            # FIXME: Raise an exception here instead of this
+            print 'ERROR: slapt-get binary not found'
 
     def update_cache(self):
         proc = _get_popen(
             raise NotImplemented
         else:
             proc = _get_popen("removepkg %s"% package)
-            out = proc.communicate(), proc.returncode
-            return out
+            return proc.communicate(), proc.returncode
+#            out = proc.communicate(), proc.returncode
+#            return out
 
     def restore_package(self, pkgname):
         """

view/dialog.py

-#!/usr/bin/env python
-
-#    This file is part of the vectorlinux multimedia bonus disc.
-#
-#    This file is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License v2 as published by
-#    the Free Software Foundation.
-#
-#    This file 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 file.  If not, see <http://www.gnu.org/licenses/>.
-
-import gtk
-import time
-import threading
-import sys
-import os
-import message
-
-try:
-    sys.path.append(os.path.join(os.getcwd(),'..'))
-except:
-    pass
-
-try:
-    from utils import vl
-except:
-    pass
-
-
-__author__ = 'Moises Henriquez'
-__author_email__ = 'moc.liamg@xnl.E0M'[::-1]
-
-
-def _(str):
-    return str
-
-class InstallWindow(gtk.Dialog):
-    def __init__(self, parent = None, pkglist = [], slaptconfig = None):
-        gtk.Dialog.__init__(self, parent = parent)
-        self.pkglist = pkglist
-        self.set_title(_('Installing Packages'))
-        if parent is None:
-            self.set_position(gtk.WIN_POS_CENTER)
-
-        content = self.get_content_area()
-        action = self.get_action_area()
-
-        banner = gtk.Label(
-                _('Please wait while the following tasks complete')
-                )
-        self.banner = banner
-        blank = gtk.Label()
-        self.progress = gtk.ProgressBar()
-        self.status = gtk.Label()
-
-        for item in (banner, blank, self.status, self.progress):
-            content.pack_start(item, False, False, 4)
-
-        btnCancel = gtk.Button(stock = gtk.STOCK_CANCEL)
-        btnCancel.connect('clicked', self.exit)
-        self.btCancel = btnCancel
-
-        action.pack_start(btnCancel, False, False, 4)
-        self.stopbar = False
-        self.monitor = threading.Thread(target = self.move)
-        self.resize(400, 150)
-        self.current = ""
-        self.failed_installs = []
-
-        self.show_all()
-        self._icurrent = 0.0
-        self.packagemanager = vl.PackageManager(
-                configfile = slaptconfig.name)
-
-    def change_cancel_button(self):
-        """ Change the cancel button to read close, 
-        and also change its icon.
-        This is to be triggered when the install process
-        is finished successful or not"""
-        wid = self.btCancel
-        wid.set_use_stock(False)
-        img = gtk.Image()
-        img.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_BUTTON)
-        wid.set_property('label', _('Close'))
-        wid.set_image(img)
-        return
-
-    def run(self):
-        """ Append our start_process() method to the dialog's
-        .run method"""
-        self.start_process()
-#        return gtk.Dialog.run(self)
-
-    def start_process(self, widget = None):
-        """ Start installation process"""
-        self.stopbar = False
-        self.monitor.start()
-        ins = threading.Thread(target = self.installation, args=(self.pkglist,))
-        ins.start()
-
-
-    def installation(self, pkgs):
-        """ Installation method. This method is not to be called
-        directly, but rather inside a thread"""
-        # First, update the cache:
-        self._icurrent = -1.0
-        gtk.gdk.threads_enter()
-        self.status.set_property('label',
-                _('Updating Package Cache')
-                )
-        gtk.gdk.threads_leave()
-        i = self.packagemanager.update_cache()
-
-        # FIXME: ^^ Error checking ??? ^^
-       # ====== Brief error checking ======
-        if i[1] > 0:
-            # Something went wrong during cache update
-            # FIXME: Error out at this point or proceed? 
-            pass
-
-        self._icurrent = 0.0
-        for pkg in self.pkglist:
-            self.current = pkg
-            gtk.gdk.threads_enter()
-            self.status.set_property('label', 'Installing %s'% pkg)
-            gtk.gdk.threads_leave()
-            # FIXME: Instead of this wait time, call the slapt-get
-            # install method to install the package and process the
-            # output.
-            ret = self.packagemanager.install_package(pkg)
-
-            # === Brief Error Checking ========
-            if ret[1] > 0 or 'unmet dependencies' in ret[0][1]:
-                self.failed_installs.append((pkg, ret[0][1]))
-            self._icurrent += 1
-
-        # When done, stop the monitor thread
-        self.stopbar = True
-        # Change the cancel button to 'Close'
-        time.sleep(0.5)
-        if len(self.failed_installs) > 0:
-            dia = message.FailedPackagesDialog(
-                    self.failed_installs)
-            gtk.gdk.threads_enter()
-            if dia.run():
-                dia.destroy()
-            gtk.gdk.threads_leave()
-        else:
-            gtk.gdk.threads_enter()
-            self.change_cancel_button()
-            gtk.gdk.threads_leave()
-
-    def exit(self, widget=None):
-        """ Do a clean exit when closing the dialog
-        and returning to the main gui"""
-        self.stopbar = True
-        time.sleep(0.25)
-        self.destroy()
-
-    def move(self):
-        """ Move the progressbar according to the progress made"""
-        val = 0.0
-        while not self.stopbar:
-            time.sleep(0.1)
-            gtk.gdk.threads_enter()
-            self.progress.pulse()
-            gtk.gdk.threads_leave()
-
-#            gtk.gdk.threads_enter()
-#            self.progress.pulse()
-#            gtk.threads_leave()
-#            time.sleep(0.25)
-#            time.sleep(0.125)
-#            while self._icurrent == -1.0:
-                #                gtk.gdk.threads_enter()
-#                self.progress.set_text(_('Updating Cache'))
-#                self.progress.pulse()
-#                gtk.gdk.threads_leave()
-#                time.sleep(0.25)
-#                val = float(float(self._icurrent) / float(len(self.pkglist)))
-#                valstr = str(int(val) * 100)
-#                gtk.gdk.threads_enter()
-#                self.progress.pulse()
-#                self.progress.set_fraction(val)
-#                gtk.gdk.threads_leave()
-#            self.progress.set_fraction(val)
-#            gtk.gdk.threads_leave()
-#            time.sleep(0.125)
-
-        time.sleep(0.5)
-
-
-        gtk.gdk.threads_enter()
-        self.progress.set_text('%i'% (val * 100) + ' %')
-        if len(self.failed_installs) > 0:
-            self.banner.set_property('label',
-                    _('Install process complete'))
-            self.progress.set_text('')
-            self.status.set_property('label',
-                    _('WARNING: Some packages failed to install.'))
-        else:
-            self.banner.set_property('label',
-                    _('Installation complete'))
-            self.progress.set_text('100 %')
-            self.status.set_property('label',
-                    _('All packages installed successfully'))
-        time.sleep(0.125)
-        self.progress.set_fraction(1.0)
-        gtk.gdk.threads_leave()
-
 import gtk
 import threading
 import time
+import os
+import sys
+try:
+    from .utils import vl
+except:
+    sys.path.append(os.path.join(os.getcwd(), '..'))
+    from utils import vl
+
+
 __author__ = 'Moises Henriquez'
 __author_email__ = 'moc.liamg@xnl.E0M'[::-1]
 
 def _(str):
     return str
 
+class UninstallDialog(gtk.Dialog):
+    """ Dialog shown when uninstalling package
+    Arguments:
+    pkglist - a list of packages to be removed.
+    parent - A gtk.Window object. Defaults to None"""
+    def __init__(self, parent = None, pkglist = [],
+            categories = None, view = None):
+        gtk.Dialog.__init__(self, parent = parent)
+        self.pkglist = pkglist
+        self.set_title(_('Uninstalling Packages'))
+        if parent is None:
+            self.set_position(gtk.WIN_POS_CENTER)
+        content = self.get_content_area()
+        action = self.get_action_area()
+        banner = gtk.Label(
+                _('Please wait while packages are being uninstalled'))
+        self.banner = banner
+        blank = gtk.Label()
+        self.progress = gtk.ProgressBar()
+        self.status = gtk.Label()
+
+        for item in (banner, blank, self.status, self.progress):
+            content.pack_start(item, False, False, 2)
+
+        btnCancel = gtk.Button(stock = gtk.STOCK_CANCEL)
+        btnCancel.connect('clicked', self.exit)
+        self.btnCancel = btnCancel
+
+        action.pack_start(btnCancel, False, False, 2)
+        self.stopbar = False
+        self.monitor = threading.Thread(target = self._pulse_bar)
+        self.resize(400, 150)
+        self.current = ""
+        self.failed = []
+
+        self._icurrent = 0.0
+        self.pkgmanager = vl.PackageManager()
+        self._catpanel = categories
+        self._view = view
+
+        self.show_all()
+
+    def exit(self, widget = None):
+        self.stopbar = True
+        self._catpanel.refresh_view()
+        return self.destroy()
+
+    def _pulse_bar(self):
+        val = 0.0
+        while not self.stopbar:
+            time.sleep(0.1)
+            gtk.gdk.threads_enter()
+            self.progress.pulse()
+            gtk.gdk.threads_leave()
+
+        # After the bar is done moving.
+
+        time.sleep(0.5)
+        self._show_postproc_labels()
+
+    def _show_postproc_labels(self):
+        if len(self.failed) > 0:
+            state = _('WARNING: Some packages failed to uninstall')
+        else:
+            state = _('The selected packages have been successfully removed')
+        gtk.gdk.threads_enter()
+        self.status.set_property('label', state)
+        self.progress.set_fraction(1.0)
+        gtk.gdk.threads_leave()
+
+    def change_cancel_button(self):
+        wid = self.btnCancel
+        wid.set_use_stock(False)
+        img = gtk.Image()
+        img.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_BUTTON)
+        wid.set_property('label', _('Close'))
+        wid.set_image(img)
+        return
+
+    def run(self):
+        """ Start our custom run process rather than the original"""
+        return self._do_run()
+
+    def _do_run(self):
+        """ Actual package removal process"""
+        self.stopbar = False
+        self.monitor.start()
+        removal = threading.Thread(
+                target= self._do_remove_pkgs,
+                args  = (self.pkglist,))
+        removal.start()
+
+    def _do_remove_pkgs(self, pkgs):
+        """ This is the removal function. Not to be called
+        directly, but rather to be parsed as a target to
+        a threading object"""
+        self.failed = []
+
+        # Update cache first.
+        self._icurrent = -1.0
+        gtk.gdk.threads_enter()
+        self.status.set_property('label',
+                _('Updating package cache')
+                )
+        gtk.gdk.threads_leave()
+        i = self.pkgmanager.update_cache()
+        if i[1] > 0:
+            #FIXME: cache failed to update... error out here???
+            pass
+
+        self._icurrent = 0.0
+        for pkg in pkgs:
+            self.current = pkg
+            gtk.gdk.threads_enter()
+            self.status.set_property('label','%s %s'% (
+                _('Uninstalling'), pkg))
+            gtk.gdk.threads_leave()
+
+            ret = self.pkgmanager.remove_package(pkg)
+            # ==== error check ===
+            if ret[1] > 0:
+                if len(ret[0][1].strip()) == 0:
+                    msg = ret[0][0].strip()
+                else:
+                    msg = ret[0][1].strip()
+                self.failed.append((pkg, msg))
+
+            self._icurrent += 1
+
+        # When done, stop the monitor thread
+        self.stopbar = True
+
+        # Check if any packages failed to uninstall, and
+        # present the appropriate dialog message.
+        if len(self.failed) > 0:
+            ## FIXME: Add the correct failed dialog with
+            ## list.
+            dia = FailedPackagesDialog(list_reason = self.failed)
+            dia.banner.set_property('label',
+                    _('Some packages failed to uninstall.') + ' ' +\
+                    _('See details below.'))
+
+
+#            dia = Error(
+#                    text = _('Some packages failed to uninstall.'))
+        else:
+            dia = Info(
+                    text = _('The selected packages have been uninstalled'))
+        gtk.gdk.threads_enter()
+        if dia.run():
+            dia.destroy()
+        self.change_cancel_button()
+        gtk.gdk.threads_leave()
+
+class InstallDialog(UninstallDialog):
+    """ A dialog shown while installing packages
+    Arguments:
+    parent = a gtk.Window object, defaults to None
+    pkglist = a list of packages to be installed"""
+    def __init__(self, parent = None, pkglist = [], slaptconfig = None, 
+            categories = None, view = None):
+        UninstallDialog.__init__(self, parent = parent, pkglist = pkglist,
+                categories = categories,
+                view = view)
+        self.slaptconfig = slaptconfig
+        self.pkglist = pkglist
+        self.set_title(_('Install Packages'))
+        self.banner.set_property('label',
+                _('Please wait while the following operations are completed'))
+        if slaptconfig is None:
+            self.slaptconfig = '/etc/slapt-getrc'
+        else:
+            self.slaptconfig = slaptconfig
+#        self.slaptconfig = '/etc/slapt-getrc'
+
+        self.pkgmanager = vl.PackageManager(configfile = self.slaptconfig)
+
+    def _show_postproc_labels(self):
+        if len(self.failed) > 0:
+            state = _('WARNING: Some packages failed to install')
+        else:
+            state = _('All selected packages were successfully installed')
+        gtk.gdk.threads_enter()
+        self.status.set_property('label', state)
+        self.banner.set_property('label',
+                _('All operations complete'))
+        self.progress.set_fraction(1.0)
+        self.change_cancel_button()
+        gtk.gdk.threads_leave()
+
+    def _do_run(self):
+        """ Fork off the package installation process"""
+        self.stopbar = False
+        self.monitor.start()
+        inst = threading.Thread(
+                target = self._do_install_pkgs,
+                args = (self.pkglist,))
+        inst.start()
+
+    def _do_install_pkgs(self, pkgs):
+        """ This method should be started in a thread ONLY"""
+        # Update cache first.
+        self._icurrent = -1.0
+        gtk.gdk.threads_enter()
+        self.status.set_property('label', _('Updating package cache'))
+        gtk.gdk.threads_leave()
+        i = self.pkgmanager.update_cache()
+        if i[1] > 0:
+            # FIXME: Cache failed to update... Error out or continue?
+            pass
+        self._icurrent = 0.0
+        for pkg in pkgs:
+            self.current = pkg
+            gtk.gdk.threads_enter()
+            self.status.set_property('label','%s %s'% (
+                _('Installing'), pkg))
+            gtk.gdk.threads_leave()
+
+            ret = self.pkgmanager.install_package(pkg)
+
+            # error check -----
+            # WARNING: slapt-get returns 0 even when the package did not
+            # install due to missing deps.
+            if ret[1] > 0 or 'unmet dependencies' in ret[0][1]:
+                if len(ret[0][1].strip()) == 0:
+                    msg = ret[0][0].strip()
+                else:
+                    msg = ret[0][1].strip()
+                self.failed.append((pkg, msg.strip()))
+            self._icurrent += 1
+        self.stopbar = True
+        self._show_postproc_labels()
+        if len(self.failed) > 0:
+            dia = FailedPackagesDialog(self.failed)
+            gtk.gdk.threads_enter()
+            if dia.run():
+                dia.destroy()
+            self.change_cancel_button()
+            gtk.gdk.threads_leave()
+
 class FailedPackagesDialog(gtk.Dialog):
     """Dialog used to show that some packages failed to install
     """
         banner.set_property('label',
                 _('The following packages failed to install.') + '\n\n' + \
                         _('Please report this error to the developer'))
+        self.banner = banner
         bannerc.pack_start(banner, False, False, 8)
         carea.pack_start(bannerc, False, False, 0)
         scv = gtk.ScrolledWindow()
         self.model = gtk.ListStore(gtk.gdk.Pixbuf, str, bool)
         self.set_model(self.model)
         pb = FancyPixbuf('emblem-app-installed')
-#        pb = gtk.CellRendererPixbuf()
         col = gtk.TreeViewColumn('None', pb, pixbuf = 0, overlay=2)
         col.set_fixed_width(36)
         col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
     def refresh_view(self):
         #        sel = self.get_selection().get_selected_rows()[1][0][0]
+        self.cache = vl.PackageManager().cache
+        self.view.get_model().clear()
         self.show_category(self._get_selected())
 #        self.show_category(sel)
 
         row = column.get_selection().get_selected_rows()[1][0][0]
         sel = self.model[row][1]
         self.show_category(sel)
+        self.cache = vl.PackageManager().cache
+        self.view.cache = self.cache
         return
 
     def show_category(self, category):
         model = self.view.get_model()
         model.clear()
+       # cache = vl.PackageManager().cache
 	cache = self.cache
 
         if category == _('All'):
                             app_name = app.name,
                             app_short_description = _sdesc,
                             installed_indicator = _overlay)
-        elif category == _('Installed Only'):
+        elif category == _('Show Installed'):
             for app in self.repo:
                 _overlay = cache.is_app_installed(app.name)
                 if _overlay is True:
         self.model.append([
             gtk.gdk.pixbuf_new_from_file_at_size(
                 icon, 32, 32), label, overlay])
-        #        self.model.append([Icon, label])
         return
 
 class FancyPixbuf(gtk.CellRendererPixbuf):