Author: jannis
Date: 2006-07-19 20:26:19 +0000 (Wed, 19 Jul 2006)
New Revision: 22486

Modified:
   installit/trunk/ChangeLog
   installit/trunk/backends/Source.py
   installit/trunk/components/packages.py
   installit/trunk/i18n/po/de.po
   installit/trunk/tools/shell.py
   installit/trunk/ui/installation.py
Log:
        * components/packages.py: Added methods to return sets of 
          unresolved libraries/programs and their paths. Added a new wrapper
          class for unresolved Programs. Renamed UnresolvedPackage into
          UnresolvedLibrary.
        * tools/shell.py: Added another constructor parameter for additional
          paths. If this parameter is defined, it will later be appended to
          $PATH. 
        * ui/installation.py: Remove subtitles from installation wizard.
          Looks better without (less text -> users understand better).
        * backend/Source.py: Pass paths of dependencies (programs only) to
          all shell commands executed during the build process. This will
          help ./configure-scripts to find required programs.
          Added a requirements (dependencies) page, which now allows to
          resolve programs which were not found. Manual library resolving
          will follow.
        * ui/installation.py: Properly display installation/deinstallation
          wizards on the center of the screen. Avoid duplicate header title 
          content.

Modified: installit/trunk/ChangeLog
===================================================================
--- installit/trunk/ChangeLog   2006-07-19 20:06:26 UTC (rev 22485)
+++ installit/trunk/ChangeLog   2006-07-19 20:26:19 UTC (rev 22486)
@@ -1,5 +1,29 @@
+2006-07-19     Jannis Pohlmann <[EMAIL PROTECTED]>
+
+       * components/packages.py: Added methods to return sets of 
+         unresolved libraries/programs and their paths. Added a new wrapper
+         class for unresolved Programs. Renamed UnresolvedPackage into
+         UnresolvedLibrary.
+       * tools/shell.py: Added another constructor parameter for additional
+         paths. If this parameter is defined, it will later be appended to
+         $PATH. 
+       * ui/installation.py: Remove subtitles from installation wizard.
+         Looks better without (less text -> users understand better).
+       * backend/Source.py: Pass paths of dependencies (programs only) to
+         all shell commands executed during the build process. This will
+         help ./configure-scripts to find required programs.
+         Added a requirements (dependencies) page, which now allows to
+         resolve programs which were not found. Manual library resolving
+         will follow.
+
 2006-07-12     Jannis Pohlmann <[EMAIL PROTECTED]>
 
+       * ui/installation.py: Properly display installation/deinstallation
+         wizards on the center of the screen. Avoid duplicate header title 
+         content.
+
+2006-07-12     Jannis Pohlmann <[EMAIL PROTECTED]>
+
        * i18n/po/de.po, i18n/po/i2t.po: New strings merged.
        * tools/env.py: Add link() and hasLibrary() methods.
        * components/packages.py: Use Environment.hasLibrary method to detect

Modified: installit/trunk/backends/Source.py
===================================================================
--- installit/trunk/backends/Source.py  2006-07-19 20:06:26 UTC (rev 22485)
+++ installit/trunk/backends/Source.py  2006-07-19 20:26:19 UTC (rev 22486)
@@ -29,6 +29,7 @@
 from tools.shell import Command
 from components.mirrors import MirrorList
 from components.config import Config
+from components.packages import Program, Library
 from ui.installation import BackendInstallationWizard, \
         BackendDeinstallationWizard
 from ui.extensions import showMessage, forceRefresh
@@ -79,16 +80,18 @@
 
         # Determine working directory
         directory = path.join(Config.get("TempDir"), package.unpackDir)
-
+        
         # Build configure command
-        return Command("./configure %s" % " ".join(options), directory)
+        return Command("./configure %s" % " ".join(options), directory,
+                       ":".join(package.getProgramPaths()))
     
     def getBuildCommand(self, package):
         # Determine working directory
         directory = path.join(Config.get("TempDir"), package.unpackDir)
 
         # Generate build command
-        return Command("make", directory)
+        return Command("make", directory,
+                       ":".join(package.getProgramPaths()))
     
     def getTestInstallCommand(self, package):
         # Determine working directory
@@ -96,14 +99,16 @@
 
         # Generate temporary installation command
         return Command("make DESTDIR=%s install" 
-                % package.getTempInstallPrefix(), directory)
+                % package.getTempInstallPrefix(), directory,
+                ":".join(package.getProgramPaths()))
 
     def getInstallCommand(self, package):
         # Determine working directory
         directory = path.join(Config.get("TempDir"), package.unpackDir)
 
         # Generate installation command
-        return Command("make install", directory)
+        return Command("make install", directory,
+                       ":".join(package.getProgramPaths()))
     
     def writeInstallLog(self, package):
         # Determine log directory
@@ -179,9 +184,9 @@
             page.show()
 
         # System requirements
-        # page = RequirementsPage(self, package)
-        # self.pages.add(page)
-        # page.show()
+        page = RequirementsPage(self, package)
+        self.pages.add(page)
+        page.show()
 
         # Extract
         page = ExtractPage(self, package)
@@ -637,6 +642,149 @@
         gtk.gdk.threads_leave()
 
 
+class RequirementsPage(SourceWizardPage):
+
+    def __init__(self, wizard, package):
+        SourceWizardPage.__init__(self, wizard, package, 
+            _("System Requirements for %s") % package.name)
+
+        # Generate main container
+        self.box = gtk.Frame()
+        self.box.set_shadow_type(gtk.SHADOW_NONE)
+        self.add(self.box)
+        self.box.show()
+
+        # Create a file chooser dialog for manually resolving dependencies
+        self.fileChooser = gtk.FileChooserDialog(_("Choose Folder"), None,
+                gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
+                 gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+
+        # Sets of unresolved programs/libraries
+        self.programs = set()
+        self.libraries = set()
+        
+        self.locations = dict()
+        self.statusButtons = dict()
+
+    def activate(self, wizard):
+        SourceWizardPage.activate(self, wizard)
+
+        wizard.backButton.set_sensitive(True)
+
+        if self.box.get_child():
+            self.box.remove(self.box.get_child())
+
+        container = gtk.VBox(False, 0)
+        self.box.add(container)
+        container.show()
+
+        self.programs.clear()
+        self.libraries.clear()
+        self.locations.clear()
+        self.statusButtons.clear()
+
+        # Determine unresolved programs
+        self.programs = self.package.getUnresolvedPrograms()
+
+        if len(self.programs) > 0:
+            # Add description label
+            label = gtk.Label(_("The following programs could not be found:"))
+            label.set_alignment(0.0, 0.5)
+            container.pack_start(label, False, False, 0)
+            label.show()
+
+            # Add table
+            table = gtk.Table(1, 2)
+            table.set_border_width(6)
+            table.set_col_spacings(12)
+            container.pack_start(table, False, False, 0)
+            table.show()
+
+            i = 0
+
+            for program in self.programs:
+                hbox = gtk.HBox(False, 0)
+                table.attach(hbox, 0, 1, i, i+1, gtk.SHRINK)
+                hbox.show()
+
+                # Status button
+                status = gtk.Button()
+                status.connect("clicked", lambda button:
+                        self._locateProgram(program))
+                status.set_relief(gtk.RELIEF_NONE)
+                status.set_image(gtk.image_new_from_stock(gtk.STOCK_NO,
+                        gtk.ICON_SIZE_BUTTON))
+                hbox.pack_start(status, False, True, 0)
+                status.show()
+
+                self.statusButtons[program] = status
+                
+                # Program label
+                label = gtk.Label()
+                label.set_markup("<b>%s</b>" % program.name)
+                label.set_alignment(0.0, 0.5)
+                hbox.pack_start(label, False, True, 0)
+                label.show()
+
+                # Locate manually via file chooser
+                button = gtk.Button(_("Locate manually..."))
+                button.connect("clicked", lambda button:
+                        self._locateProgram(program))
+                button.set_image(gtk.image_new_from_stock(gtk.STOCK_FIND,
+                        gtk.ICON_SIZE_BUTTON))
+                table.attach(button, 1, 2, i, i+1, gtk.SHRINK)
+                button.show()
+
+        # Determine unresolved libraries
+        self.libraries = self.package.getUnresolvedLibraries()
+
+        
+        if self.validate():
+            self.emit("page-success")
+
+    def validate(self):
+        # We're done when there are no missing depdendencies left
+        if len(self.programs) == 0 and len(self.libraries) == 0:
+            return True
+
+    def _locateProgram(self, program):
+        if self.locations.has_key(program):
+            self.fileChooser.set_filename(self.locations[program])
+
+        if self.fileChooser.run() == gtk.RESPONSE_ACCEPT:
+            self.locations[program] = self.fileChooser.get_filename()
+
+            # Generate absolute path
+            fullpath = path.join(self.locations[program], program.name)
+
+            # Check if program is executable            
+            if os.access(fullpath, os.X_OK):
+                # Update status icon
+                image = gtk.image_new_from_stock(gtk.STOCK_YES,
+                        gtk.ICON_SIZE_BUTTON)
+                self.statusButtons[program].set_image(image)
+                
+                # Create new (resolved) program object
+                newProgram = Program(program.name,
+                                     self.fileChooser.get_filename())
+                
+                # Replace UnresolvedProgram with Program
+                self.package.dependencies.programs.remove(program)
+                self.package.dependencies.programs.add(newProgram)
+                
+                # Remove program from unresolved dependencies
+                self.programs.remove(program)
+            else:
+                # Update status icon
+                image = gtk.image_new_from_stock(gtk.STOCK_NO,
+                        gtk.ICON_SIZE_BUTTON)
+                self.statusButtons[program].set_image(image)
+        
+        # Hide the file chooser again
+        self.fileChooser.hide()
+    
+
 class BuildPage(SourceWizardPage):
 
     def __init__(self, wizard, package):

Modified: installit/trunk/components/packages.py
===================================================================
--- installit/trunk/components/packages.py      2006-07-19 20:06:26 UTC (rev 
22485)
+++ installit/trunk/components/packages.py      2006-07-19 20:26:19 UTC (rev 
22486)
@@ -76,7 +76,7 @@
         self.install = None
 
 
-class UnresolvedPackage:
+class UnresolvedLibrary:
 
     def __init__(self, name, version, backend=None):
         self.name = name
@@ -84,6 +84,12 @@
         self.backend = backend
 
 
+class UnresolvedProgram:
+
+    def __init__(self, name):
+        self.name = name
+
+
 class Dependencies:
 
     def __init__(self):
@@ -125,7 +131,33 @@
                 results = results.union(package.getDeepDependencies())
         return results
 
+    def getUnresolvedPrograms(self):
+        results = set()
 
+        for dep in self.dependencies.programs:
+            if isinstance(dep, UnresolvedProgram):
+                results.add(dep)
+
+        return results
+
+    def getUnresolvedLibraries(self):
+        results = set()
+        
+        for dep in self.dependencies.libraries:
+            if isinstance(dep, UnresolvedLibrary):
+                results.add(dep)
+
+        return results
+    
+    def getProgramPaths(self):
+        paths = set()
+        
+        for program in self.dependencies.programs:
+            paths.add(program.path)
+            
+        return paths
+
+
 # Register Package to GObject type system
 gobject.type_register(Package)
 
@@ -526,7 +558,7 @@
         paths = BaseDir.getPath()
 
         for location in paths:
-            if path.isfile(path.join(location, name)):
+            if os.access(path.join(location, name), os.X_OK):
                 return Program(name, path.join(location, name))
         
         raise ProgramNotFoundError(name)
@@ -550,12 +582,12 @@
                         if Environment.hasLibrary(dep["name"], dep["version"]):
                             return Library(dep["name"], dep["version"])
                         else:
-                            return UnresolvedPackage(dep["name"],
+                            return UnresolvedLibrary(dep["name"],
                                     dep["version"])
                     else:
                         # Mark this dependency as unresolved and try resolving
                         # it manually during installation.
-                        pkg = UnresolvedPackage(dep["name"], dep["version"])
+                        pkg = UnresolvedLibrary(dep["name"], dep["version"])
 
             newDeps.add(pkg)
 
@@ -568,8 +600,8 @@
         for dep in package.dependencies.programs:
             try:
                 pkg = self._resolveProgram(dep["name"])
-            except PackageNotFoundError, e:
-                pkg = UnresolvedPackage(dep["name"], None, None)
+            except ProgramNotFoundError, e:
+                pkg = UnresolvedProgram(dep["name"])
 
             newDeps.add(pkg)
 

Modified: installit/trunk/i18n/po/de.po
===================================================================
--- installit/trunk/i18n/po/de.po       2006-07-19 20:06:26 UTC (rev 22485)
+++ installit/trunk/i18n/po/de.po       2006-07-19 20:26:19 UTC (rev 22486)
@@ -29,17 +29,19 @@
 
 #: ../..//backends/Source.py:341
 #, python-format
-msgid "Please specify the installation prefix <b>%(name)s</b> should be 
installed to. You need write permissions for this directory."
-msgstr "Bitte geben Sie das Zielverzeichnis an, in das <b>%(name)s</b> 
installiert werden soll. Sie benötigen für dieses Verzeichnis Schreibrechte."
+msgid ""
+"Please specify the installation prefix <b>%(name)s</b> should be installed "
+"to. You need write permissions for this directory."
+msgstr ""
+"Bitte geben Sie das Zielverzeichnis an, in das <b>%(name)s</b> installiert "
+"werden soll. Sie benötigen für dieses Verzeichnis Schreibrechte."
 
 #. File chooser dialog
-#: ../..//backends/Source.py:351
-#: ../..//ui/main.py:82
+#: ../..//backends/Source.py:351 ../..//ui/main.py:82
 msgid "Installation Prefix"
 msgstr "Zielverzeichnis"
 
-#: ../..//backends/Source.py:378
-#: ../..//ui/initial.py:306
+#: ../..//backends/Source.py:378 ../..//ui/initial.py:306
 #, python-format
 msgid "Directory %s is not writable."
 msgstr "Verzeichnis %s ist schreibgeschützt."
@@ -205,7 +207,9 @@
 
 #: ../..//ui/main.py:142
 msgid "Perform package installations/removals/updates."
-msgstr "Die gewünschten Installationen/Deinstallationen und Aktualisierungen 
durchführen."
+msgstr ""
+"Die gewünschten Installationen/Deinstallationen und Aktualisierungen "
+"durchführen."
 
 #: ../..//ui/main.py:144
 msgid "Select _Mirror"
@@ -241,8 +245,12 @@
 
 #. Display additional packages dialog
 #: ../..//ui/main.py:401
-msgid "The following additional packages have to be installed. Do you want to 
continue?"
-msgstr "Die folgenden, zusätzlichen Pakete müssen installiert werden. Wollen 
Sie fortfahren?"
+msgid ""
+"The following additional packages have to be installed. Do you want to "
+"continue?"
+msgstr ""
+"Die folgenden, zusätzlichen Pakete müssen installiert werden. Wollen Sie "
+"fortfahren?"
 
 #: ../..//ui/main.py:417
 msgid "No changes were made."
@@ -253,8 +261,7 @@
 msgid "Downloading packages"
 msgstr "Lade Pakete herunter"
 
-#: ../..//ui/main.py:485
-#: ../..//ui/tasks.py:428
+#: ../..//ui/main.py:485 ../..//ui/tasks.py:428
 #, python-format
 msgid "Could not fetch package from %s."
 msgstr "Konnte Paket nicht von %s holen."
@@ -264,8 +271,12 @@
 msgstr "Einleitende Konfiguration"
 
 #: ../..//ui/initial.py:112
-msgid "You have to configure InstallIt on first startup. Do you really want to 
abort?"
-msgstr "InstallIt muss vor dem ersten Start konfiguriert werden. Sind Sie 
sicher, dass sie abbrechen wollen?"
+msgid ""
+"You have to configure InstallIt on first startup. Do you really want to "
+"abort?"
+msgstr ""
+"InstallIt muss vor dem ersten Start konfiguriert werden. Sind Sie sicher, "
+"dass sie abbrechen wollen?"
 
 #: ../..//ui/initial.py:135
 msgid "Please fill out this page correctly."
@@ -278,11 +289,15 @@
 #. Description
 #: ../..//ui/initial.py:219
 msgid ""
-"InstallIt uses a repository system and needs to store some data on your 
harddrive, like the mirror list, package information and temporary installation 
files.\n"
+"InstallIt uses a repository system and needs to store some data on your "
+"harddrive, like the mirror list, package information and temporary "
+"installation files.\n"
 " \n"
 "Please enter/select the directories you want InstallIt to use."
 msgstr ""
-"InstallIt verwendet ein Paketsystem und muss Daten auf Ihrer Festplatte 
speichern, wie zum Beispiel die Mirror-Liste, Paketinformationen und temporäre 
Installationsdateien. \n"
+"InstallIt verwendet ein Paketsystem und muss Daten auf Ihrer Festplatte "
+"speichern, wie zum Beispiel die Mirror-Liste, Paketinformationen und "
+"temporäre Installationsdateien. \n"
 "\n"
 "Bitte geben sie die Verzeichnisse an, die InstallIt dafür nutzen soll."
 
@@ -304,8 +319,7 @@
 msgstr "Verzeichnis auswählen"
 
 #. Name column
-#: ../..//ui/categories.py:94
-#: ../..//ui/installation.py:107
+#: ../..//ui/categories.py:94 ../..//ui/installation.py:107
 #: ../..//ui/packages.py:158
 msgid "Name"
 msgstr "Name"
@@ -334,8 +348,7 @@
 msgid "Installation Wizard"
 msgstr "Installation"
 
-#: ../..//ui/installation.py:174
-#: ../..//ui/installation.py:312
+#: ../..//ui/installation.py:174 ../..//ui/installation.py:312
 msgid "<b>Packages:</b>"
 msgstr "<b>Pakete:</b>"
 
@@ -353,8 +366,7 @@
 msgid "All packages were removed successfully."
 msgstr "Alle Pakete wurden erfolgreich entfernt."
 
-#: ../..//ui/download.py:114
-#: ../..//ui/download.py:115
+#: ../..//ui/download.py:114 ../..//ui/download.py:115
 msgid "Establishing connection..."
 msgstr "Stelle Verbindung her..."
 
@@ -421,11 +433,13 @@
 
 #: ../..//setup.py:43
 msgid "You need at least PyGTK 2.6 to run InstallIt (i2t)"
-msgstr "Sie benötigen mindestens PyGTK 2.6 um InstallIt (i2t) nutzen zu 
können."
+msgstr ""
+"Sie benötigen mindestens PyGTK 2.6 um InstallIt (i2t) nutzen zu können."
 
 #: ../..//setup.py:59
 msgid "Graphical source-based package manager and installer"
-msgstr "Grafisches, quellenbasiertes Paketverwaltungs- und 
Installationsprogramm"
+msgstr ""
+"Grafisches, quellenbasiertes Paketverwaltungs- und Installationsprogramm"
 
 #: ../..//setup.py:61
 msgid "InstallIt (i2t) is a source-based package management solution"
@@ -458,16 +472,22 @@
 
 #~ msgid "Features"
 #~ msgstr "Features"
+
 #~ msgid "Configuration"
 #~ msgstr "Konfiguration"
+
 #~ msgid "Performing Test Installation"
 #~ msgstr "Führe Testinstallation durch"
+
 #~ msgid "Download Wizard"
 #~ msgstr "Download"
+
 #~ msgid "Moving %(file)s to %(dir)s"
 #~ msgstr "Verschiebe %(file)s nach %(dir)s"
+
 #~ msgid "All packages were successfully installed."
 #~ msgstr "Alle Pakete wurden erfolgreich installiert."
+
 #~ msgid "Select _mirror"
 #~ msgstr "_Mirror auswählen"
 
@@ -488,16 +508,20 @@
 #~ msgid_plural "Remove packages"
 #~ msgstr[0] "Paket _entfernen"
 #~ msgstr[1] "Paket _entfernen"
+
 #~ msgid "Version"
 #~ msgstr "Version"
+
 #~ msgid "Backend"
 #~ msgstr "Backend"
+
 #~ msgid ""
 #~ "GTK+ bindings for Python could not be found. Please install python-gtk or "
 #~ "pygtk first."
 #~ msgstr ""
 #~ "GTK+-Bindungen für Python konnten nicht gefunden werden. Bitte "
 #~ "installieren Sie zunächst python-gtk oder pygtk."
+
 #~ msgid ""
 #~ "This is your first start of InstallIt. In order to use it you will have "
 #~ "to define working directories first. \n"
@@ -508,4 +532,3 @@
 #~ "können, müssen vorab Arbeitsverzeichnisse festgelegt werden. \n"
 #~ "Sie können alternativ dazu die vordefinierten Verzeichnisse nutzen. Diese "
 #~ "sind für die meisten Benutzer ausreichend."
-

Modified: installit/trunk/tools/shell.py
===================================================================
--- installit/trunk/tools/shell.py      2006-07-19 20:06:26 UTC (rev 22485)
+++ installit/trunk/tools/shell.py      2006-07-19 20:26:19 UTC (rev 22486)
@@ -33,11 +33,12 @@
 
 class Command(gobject.GObject):
 
-    def __init__(self, command, directory=None):
+    def __init__(self, command, directory=None, path=""):
         gobject.GObject.__init__(self)
         
         self.command = command
         self.directory = directory
+        self.path = path
 
     def _reset(self):
         self.terminated = False
@@ -53,6 +54,12 @@
     def _process(self):
         # Setup process environment
         env = Environment.copy()
+        
+        # Expand $PATH
+        if env.has_key("PATH"):
+            env["PATH"] = env["PATH"] + ":" + self.path
+        else:
+            env["PATH"] = self.path
 
         Environment.expandPkgConfigPath(env)
         Environment.expandLibraryPath(env)

Modified: installit/trunk/ui/installation.py
===================================================================
--- installit/trunk/ui/installation.py  2006-07-19 20:06:26 UTC (rev 22485)
+++ installit/trunk/ui/installation.py  2006-07-19 20:26:19 UTC (rev 22486)
@@ -41,7 +41,6 @@
         self.package = package
 
     def setTitle(self, title):
-        self.dialog.set_subtitle(title)
         self.dialog.set_title(_("Installation: %s" % title))
 
 
@@ -71,7 +70,6 @@
         self.package = package
 
     def setTitle(self, title):
-        self.dialog.heading.set_subtitle(title)
         self.dialog.set_title(_("Deinstallation: %s") % title)
 
 
@@ -153,6 +151,7 @@
 
         # Basic window setup
         self.set_default_size(640, 480)
+        self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
         self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
         self.set_property("skip-taskbar-hint", False)
         self.set_property("skip-pager-hint", False)
@@ -291,6 +290,7 @@
 
         # Basic window setup
         self.set_default_size(640, 480)
+        self.set_position(gtk.WIN_POS_CENTER_ALWAYS)
         self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL)
         self.set_property("skip-taskbar-hint", False)
         self.set_property("skip-pager-hint", False)

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to