summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/Changelog2
-rw-r--r--doc/Hooks7
-rw-r--r--doc/Howto_Write_Plugins1
-rw-r--r--doc/TODO2
-rw-r--r--i18n/de_DE.po238
-rw-r--r--i18n/messages.pot198
-rw-r--r--plugin.xsd2
-rw-r--r--plugins/notify.xml (renamed from plugins/noroot.xml)12
-rw-r--r--plugins/resume_loop.xml4
-rw-r--r--portato.desktop2
-rwxr-xr-xportato.py35
-rw-r--r--portato/__init__.py3
-rw-r--r--portato/constants.py7
-rw-r--r--portato/gui/gtk/__init__.py3
-rw-r--r--portato/gui/gtk/windows.py111
-rw-r--r--portato/gui/templates/portato.glade420
-rw-r--r--portato/helper.py17
-rw-r--r--portato/plistener.py127
-rw-r--r--portato/plugin.py3
-rw-r--r--portato/plugins/etc_proposals.py3
-rw-r--r--portato/plugins/noroot.py15
-rw-r--r--portato/plugins/notify.py23
22 files changed, 704 insertions, 531 deletions
diff --git a/doc/Changelog b/doc/Changelog
index 0893e48..fa48774 100644
--- a/doc/Changelog
+++ b/doc/Changelog
@@ -4,6 +4,8 @@ next:
- new threading model for the emerge process
- minor enhancements
- added splash screen
+- added notifies
+- added listener / launch gksu/kdesu by ourselves
0.8.1:
- bugfixes
diff --git a/doc/Hooks b/doc/Hooks
index 43dfe3b..e0469e9 100644
--- a/doc/Hooks
+++ b/doc/Hooks
@@ -1,13 +1,6 @@
List of hooks currently being supported by Portato
==================================================
-am_i_root
----------
-Called: When checking whether the current user is root (ie. uid == 0).
-Parameters: None
-Return if override: Boolean signaling whether we are root.
-
-
emerge:
-------
Called: When emerge or every other command given by e.g. the synccmd preference is being called.
diff --git a/doc/Howto_Write_Plugins b/doc/Howto_Write_Plugins
index 6c4f97f..9b0e375 100644
--- a/doc/Howto_Write_Plugins
+++ b/doc/Howto_Write_Plugins
@@ -42,6 +42,7 @@ Sample XML
Notes:
- If you want to specify a dependency plugin the connect tag has to be like: <connect type = "after"> The other plugin we depend on </connect>.
+- The "connect"-tag can be omitted. It then defaults to "<connect type='before' />".
- It is possible of course to have more than one "hook" tag.
- The options tag is optional. For a complete list of options, see below.
diff --git a/doc/TODO b/doc/TODO
index c79d0a2..e3821d7 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -26,6 +26,8 @@ Main Point: user preferences:
- window size / location
- colors and font sizes
+- rotating systray icon
+
GTK:
----
- make oneshot better
diff --git a/i18n/de_DE.po b/i18n/de_DE.po
index f61b737..936b13a 100644
--- a/i18n/de_DE.po
+++ b/i18n/de_DE.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Portato\n"
"POT-Creation-Date: \n"
-"PO-Revision-Date: 2007-08-09 20:20-0800\n"
+"PO-Revision-Date: 2007-08-11 22:13-0800\n"
"Last-Translator: René 'Necoro' Neumann <necoro@necoro.net>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -30,18 +30,18 @@ msgid "gtk-quit"
msgstr ""
#: portato/gui/templates/portato.glade:81
-#: portato/gui/templates/portato.glade:569
+#: portato/gui/templates/portato.glade:514
msgid "_Emerge"
msgstr "_Emerge"
#: portato/gui/templates/portato.glade:89
#: portato/gui/templates/portato.glade:719
-#: portato/gui/gtk/windows.py:690
+#: portato/gui/gtk/windows.py:691
msgid "E_merge"
msgstr "E_merge"
#: portato/gui/templates/portato.glade:104
-#: portato/gui/templates/portato.glade:578
+#: portato/gui/templates/portato.glade:523
#: portato/gui/templates/portato.glade:728
msgid "_Unmerge"
msgstr "_Unmerge"
@@ -112,47 +112,47 @@ msgstr "Zeige _Log"
msgid "gtk-find"
msgstr ""
-#: portato/gui/templates/portato.glade:472
-msgid "<b>Installed, but not in portage anymore</b>"
-msgstr "<b>Installiert, aber nicht mehr im Portage-Tree vorhanden</b>"
-
-#: portato/gui/templates/portato.glade:551
-msgid "<span foreground='red'><b>MISSING KEYWORD</b></span>"
-msgstr "<span foreground='red'><b>FEHLENDES KEYWORD</b></span>"
-
-#: portato/gui/templates/portato.glade:590
-msgid "Re_vert"
-msgstr "_Wiederherstellen"
-
-#: portato/gui/templates/portato.glade:602
-msgid "E_build"
-msgstr "E_build"
-
-#: portato/gui/templates/portato.glade:628
+#: portato/gui/templates/portato.glade:461
msgid "Installed"
msgstr "Installiert"
-#: portato/gui/templates/portato.glade:641
-#: portato/gui/gtk/windows.py:667
-#: portato/gui/gtk/windows.py:670
-#: portato/gui/gtk/windows.py:673
-#: portato/gui/gtk/windows.py:778
-#: portato/gui/gtk/windows.py:781
-#: portato/gui/gtk/windows.py:788
-#: portato/gui/gtk/windows.py:792
+#: portato/gui/templates/portato.glade:474
+#: portato/gui/gtk/windows.py:668
+#: portato/gui/gtk/windows.py:671
+#: portato/gui/gtk/windows.py:674
+#: portato/gui/gtk/windows.py:773
+#: portato/gui/gtk/windows.py:776
+#: portato/gui/gtk/windows.py:783
+#: portato/gui/gtk/windows.py:787
msgid "Masked"
msgstr "Masked"
-#: portato/gui/templates/portato.glade:655
-#: portato/gui/gtk/windows.py:680
-#: portato/gui/gtk/windows.py:683
+#: portato/gui/templates/portato.glade:488
+#: portato/gui/gtk/windows.py:681
+#: portato/gui/gtk/windows.py:684
+#: portato/gui/gtk/windows.py:745
#: portato/gui/gtk/windows.py:750
-#: portato/gui/gtk/windows.py:755
msgid "Testing"
msgstr "Testing"
+#: portato/gui/templates/portato.glade:535
+msgid "Re_vert"
+msgstr "_Wiederherstellen"
+
+#: portato/gui/templates/portato.glade:547
+msgid "E_build"
+msgstr "E_build"
+
+#: portato/gui/templates/portato.glade:568
+msgid "<span foreground='red'><b>MISSING KEYWORD</b></span>"
+msgstr "<span foreground='red'><b>FEHLENDES KEYWORD</b></span>"
+
+#: portato/gui/templates/portato.glade:647
+msgid "<b>Installed, but not in portage anymore</b>"
+msgstr "<b>Installiert, aber nicht mehr im Portage-Tree vorhanden</b>"
+
#: portato/gui/templates/portato.glade:682
-#: portato/gui/gtk/windows.py:127
+#: portato/gui/gtk/windows.py:128
msgid "Package"
msgstr "Paket"
@@ -161,12 +161,12 @@ msgid "_Remove"
msgstr "_Löschen"
#: portato/gui/templates/portato.glade:777
-#: portato/gui/gtk/windows.py:1003
+#: portato/gui/gtk/windows.py:998
msgid "Queue"
msgstr "Queue"
#: portato/gui/templates/portato.glade:805
-#: portato/gui/gtk/windows.py:1100
+#: portato/gui/gtk/windows.py:1095
msgid "Console"
msgstr "Konsole"
@@ -220,31 +220,19 @@ msgstr "Sync-Befehl: "
msgid "<b>Sync Options</b>"
msgstr "<b>Sync Optionen</b>"
-#: portato/gui/templates/portato.glade:1164
-msgid "File name to use, if package.use is a directory: "
-msgstr "Zu benutzender Dateiname, wenn package.use ein Verzeichnis ist:"
-
-#: portato/gui/templates/portato.glade:1175
-msgid "Add only exact version to package.use"
-msgstr "Füge nur die exakte Paketversion zu package.keywords hinzu"
-
-#: portato/gui/templates/portato.glade:1188
-msgid "Add only exact version to package.keywords"
-msgstr "Füge nur die exakte Paketversion zu package.keywords hinzu"
-
-#: portato/gui/templates/portato.glade:1202
-msgid "File name to use, if package.keywords is a directory: "
-msgstr "Zu benutzender Dateiname, wenn package.keywords ein Verzeichnis ist:"
+#: portato/gui/templates/portato.glade:1154
+msgid "<u><i>Masking Keywords</i></u>"
+msgstr "<u><i>Masking Keywords</i></u>"
-#: portato/gui/templates/portato.glade:1236
-msgid "File name to use, if package.mask/package.unmask is a directory: "
-msgstr "Zu benutzender Dateiname, wenn package.mask/package.unmask ein Verzeichnis ist:"
+#: portato/gui/templates/portato.glade:1169
+msgid "<u><i>Testing Keywords</i></u>"
+msgstr "<u><i>Testing Keywords</i></u>"
-#: portato/gui/templates/portato.glade:1247
-msgid "Add only exact version to package.mask/package.unmask"
-msgstr "Füge nur die exakte Paketversion zu package.mask/package.unmask hinzu"
+#: portato/gui/templates/portato.glade:1184
+msgid "<u><i>Use-Flags</i></u>"
+msgstr "<u><i>Use-Flags</i></u>"
-#: portato/gui/templates/portato.glade:1269
+#: portato/gui/templates/portato.glade:1206
msgid ""
"<u>You may use the following placeholders:</u>\n"
"\n"
@@ -258,17 +246,29 @@ msgstr ""
"<i>$(pkg)</i>: Paketname\n"
"<i>$(cat-1)/$(cat-2)</i>: erster/zweiter Teil der Kategorie"
-#: portato/gui/templates/portato.glade:1295
-msgid "<u><i>Use-Flags</i></u>"
-msgstr "<u><i>Use-Flags</i></u>"
+#: portato/gui/templates/portato.glade:1230
+msgid "Add only exact version to package.mask/package.unmask"
+msgstr "Füge nur die exakte Paketversion zu package.mask/package.unmask hinzu"
-#: portato/gui/templates/portato.glade:1310
-msgid "<u><i>Testing Keywords</i></u>"
-msgstr "<u><i>Testing Keywords</i></u>"
+#: portato/gui/templates/portato.glade:1244
+msgid "File name to use, if package.mask/package.unmask is a directory: "
+msgstr "Zu benutzender Dateiname, wenn package.mask/package.unmask ein Verzeichnis ist:"
-#: portato/gui/templates/portato.glade:1325
-msgid "<u><i>Masking Keywords</i></u>"
-msgstr "<u><i>Masking Keywords</i></u>"
+#: portato/gui/templates/portato.glade:1278
+msgid "File name to use, if package.keywords is a directory: "
+msgstr "Zu benutzender Dateiname, wenn package.keywords ein Verzeichnis ist:"
+
+#: portato/gui/templates/portato.glade:1289
+msgid "Add only exact version to package.keywords"
+msgstr "Füge nur die exakte Paketversion zu package.keywords hinzu"
+
+#: portato/gui/templates/portato.glade:1302
+msgid "Add only exact version to package.use"
+msgstr "Füge nur die exakte Paketversion zu package.keywords hinzu"
+
+#: portato/gui/templates/portato.glade:1316
+msgid "File name to use, if package.use is a directory: "
+msgstr "Zu benutzender Dateiname, wenn package.use ein Verzeichnis ist:"
#: portato/gui/templates/portato.glade:1342
msgid "<b>Use Flag and Keyword Options</b>"
@@ -355,100 +355,104 @@ msgstr "Logs"
msgid "Resume-loop called while process is still running!"
msgstr "\"Resume-Loop\" aufgerufen, während Emerge noch lief. Bug!"
-#: portato/plugins/etc_proposals.py:64
-#: portato/plugins/etc_proposals.py:76
+#: portato/plugins/etc_proposals.py:65
+#: portato/plugins/etc_proposals.py:77
msgid "Cannot start etc-proposals. No graphical frontend installed!"
msgstr "Kann etc-proposals nicht starten. Kein grafisches Frontend installiert."
-#: portato/plugins/etc_proposals.py:78
+#: portato/plugins/etc_proposals.py:79
msgid "Cannot start etc-proposals. Not root!"
msgstr "Kann etc-proposals nicht starten. Nur root kann das!"
-#: portato/gui/gtk/windows.py:72
+#: portato/plugins/notify.py:11
+msgid "Notify called while process is still running!"
+msgstr "\"Notify\" aufgerufen, während Emerge noch lief."
+
+#: portato/gui/gtk/windows.py:73
msgid "Plugin"
msgstr "Plugin"
-#: portato/gui/gtk/windows.py:75
+#: portato/gui/gtk/windows.py:76
msgid "Authors"
msgstr "Entwickler"
-#: portato/gui/gtk/windows.py:80
-#: portato/gui/gtk/windows.py:126
-#: portato/gui/gtk/windows.py:541
+#: portato/gui/gtk/windows.py:81
+#: portato/gui/gtk/windows.py:127
+#: portato/gui/gtk/windows.py:542
msgid "Enabled"
msgstr "Aktiviert"
-#: portato/gui/gtk/windows.py:225
+#: portato/gui/gtk/windows.py:226
msgid "Results"
msgstr "Ergebnisse"
-#: portato/gui/gtk/windows.py:494
+#: portato/gui/gtk/windows.py:495
msgid "<no description>"
msgstr "<keine Beschreibung>"
-#: portato/gui/gtk/windows.py:523
+#: portato/gui/gtk/windows.py:524
msgid "This is an expanded use flag and cannot be selected"
msgstr "Dies ist ein \"Expanded Use Flag\" und kann daher nicht ausgewählt werden."
-#: portato/gui/gtk/windows.py:542
+#: portato/gui/gtk/windows.py:543
msgid "Flag"
msgstr "Flag"
-#: portato/gui/gtk/windows.py:543
+#: portato/gui/gtk/windows.py:544
msgid "Description"
msgstr "Beschreibung"
-#: portato/gui/gtk/windows.py:622
+#: portato/gui/gtk/windows.py:623
#, python-format
msgid "Package could not be found: %s"
msgstr "Paket konnte nicht gefunden werden: %s"
-#: portato/gui/gtk/windows.py:693
+#: portato/gui/gtk/windows.py:694
msgid "Re_merge"
msgstr "Re_merge"
-#: portato/gui/gtk/windows.py:890
+#: portato/gui/gtk/windows.py:885
msgid "Creating Database"
msgstr "Erstelle Datenbank"
-#: portato/gui/gtk/windows.py:895
+#: portato/gui/gtk/windows.py:890
msgid "Loading Config"
msgstr "Lade Konfiguration"
-#: portato/gui/gtk/windows.py:906
+#: portato/gui/gtk/windows.py:901
msgid "Loading Plugins"
msgstr "Lade Plugins"
-#: portato/gui/gtk/windows.py:919
+#: portato/gui/gtk/windows.py:914
msgid "Finishing startup"
msgstr "Erledige letzte Handgriffe :)"
-#: portato/gui/gtk/windows.py:1006
+#: portato/gui/gtk/windows.py:1001
msgid "Options"
msgstr "Optionen"
-#: portato/gui/gtk/windows.py:1024
+#: portato/gui/gtk/windows.py:1019
msgid "Categories"
msgstr "Kategorien"
-#: portato/gui/gtk/windows.py:1039
+#: portato/gui/gtk/windows.py:1034
msgid "Packages"
msgstr "Pakete"
-#: portato/gui/gtk/windows.py:1102
+#: portato/gui/gtk/windows.py:1097
#, python-format
msgid "Console (%(title)s)"
msgstr "Konsole (%(title)s)"
-#: portato/gui/gtk/windows.py:1154
+#: portato/gui/gtk/windows.py:1149
msgid "use flags"
msgstr "Use Flags"
-#: portato/gui/gtk/windows.py:1161
+#: portato/gui/gtk/windows.py:1156
msgid "masking keywords"
msgstr "Masking Keywords"
-#: portato/gui/gtk/__init__.py:20
+#: portato/gui/gtk/__init__.py:21
msgid "Loading Portage"
msgstr "Lade Portage"
@@ -587,90 +591,98 @@ msgstr "Konflikt beim Masking-Status: %s"
msgid "Unrecognized line in configuration: %s"
msgstr "Unbekannte Zeile in Konfiguration: %s"
-#: portato/plugin.py:287
-#: portato/plugin.py:293
-#: portato/plugin.py:298
+#: portato/plugin.py:290
+#: portato/plugin.py:296
+#: portato/plugin.py:301
#, python-format
msgid "%s cannot be imported."
msgstr "%s kann nicht importiert werden."
-#: portato/plugin.py:325
+#: portato/plugin.py:328
#, python-format
msgid "Accessing hook '%(hook)s' of plugin '%(plugin)s' (before)."
msgstr "Aufruf des Hooks '%(hook)s' vom Plugin '%(plugin)s'. (before)"
-#: portato/plugin.py:329
+#: portato/plugin.py:332
#, python-format
msgid "Overriding hook '%(hook)s' with plugin '%(plugin)s'."
msgstr "Überschreibe den Hook '%(hook)s' mit Plugin '%(plugin)s'."
-#: portato/plugin.py:336
+#: portato/plugin.py:339
#, python-format
msgid "Accessing hook '%(hook)s' of plugin '%(plugin)s' (after)."
msgstr "Aufruf des Hooks '%(hook)s' vom Plugin '%(plugin)s'. (after)"
-#: portato/plugin.py:356
+#: portato/plugin.py:359
#, python-format
msgid "Loading plugin '%s' failed. Invalid XML syntax."
msgstr "Laden des Plugins '%s\" fehlgeschlagen: XML-Syntax-Fehler."
-#: portato/plugin.py:359
+#: portato/plugin.py:362
#, python-format
msgid "Loading plugin '%s' failed. Plugin does not comply with schema."
msgstr "Laden des Plugins '%s\" fehlgeschlagen. Plugin erfüllt nicht das XML-Schema."
-#: portato/plugin.py:388
+#: portato/plugin.py:391
#, python-format
msgid "Plugin '%s' loaded."
msgstr "Plugin '%s' geladen."
-#: portato/plugin.py:391
+#: portato/plugin.py:394
#, python-format
msgid "Loading plugin '%(plugin)s' failed: Could not import %(import)s"
msgstr "Laden des Plugins '%(plugin)s\" fehlgeschlagen. Import von '%(import)s' nicht möglich."
-#: portato/plugin.py:456
+#: portato/plugin.py:459
#, python-format
msgid "For hook '%(hook)s' an override is already defined by plugin '%(plugin)s'!"
msgstr "Das Plugin '%(plugin)s' definiert bereits einen \"Override\" fürr den Hook '%(hook)s'!"
-#: portato.py:38
+#: portato/plistener.py:95
+msgid "Listener has not been started."
+msgstr "Listener wurde nicht gestartet."
+
+#: portato.py:40
msgid "runs pychecker (should only be used by developers)"
msgstr "Startet \"pychecker\". (Nur Entwickler sollten dies brauchen)."
-#: portato.py:41
+#: portato.py:43
#, python-format
msgid "the frontend to use - possible values are: %s [default: %%default]"
msgstr "Das zu benutzende Frontend. Möglichkeiten: %s [Default: %%default]"
-#: portato.py:44
+#: portato.py:46
msgid "opens the ebuild viewer instead of launching Portato"
msgstr "Öffnet den Ebuild Viewer anstatt Portato zu starten"
-#: portato.py:47
+#: portato.py:49
msgid "validates the given plugin xml instead of launching Portato"
msgstr "Validiert die gegebene Plugin-XML. Startet nicht Portato."
-#: portato.py:60
+#: portato.py:52
+msgid "do not start listener"
+msgstr "Starte den Listener nicht."
+
+#: portato.py:65
#, python-format
msgid "Unknown frontend '%(frontend)s'. Correct frontends are: %(list)s"
msgstr "Unbekanntest Frontend '%(frontend)s'. Erlaubte Frontends sind: %(list)s"
-#: portato.py:68
+#: portato.py:73
#, python-format
msgid "'%(frontend)s' should be installed, but cannot be imported. This is definitly a bug. (%(error)s)"
msgstr "'%(frontend)s' sollte installiert sein, aber das Einbinden schlug fehl. Das ist definitiv ein Bug. (%(error)s)"
-#: portato.py:78
+#: portato.py:83
#, python-format
msgid "Validation failed. XML syntax error: %s."
msgstr "Validierung fehlgeschlagen. XML Syntax Fehler: %s."
-#: portato.py:81
+#: portato.py:86
msgid "Validation failed. Does not comply with schema."
msgstr "Validierung gegen das Schema fehlgeschlagen."
-#: portato.py:84
+#: portato.py:89
msgid "Validation succeeded."
msgstr "Validierung erfolgreich."
diff --git a/i18n/messages.pot b/i18n/messages.pot
index 272221d..b1efe83 100644
--- a/i18n/messages.pot
+++ b/i18n/messages.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-08-09 20:17-0700\n"
+"POT-Creation-Date: 2007-08-11 22:12-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -34,17 +34,17 @@ msgid "gtk-quit"
msgstr ""
#: portato/gui/templates/portato.glade:81
-#: portato/gui/templates/portato.glade:569
+#: portato/gui/templates/portato.glade:514
msgid "_Emerge"
msgstr ""
#: portato/gui/templates/portato.glade:89
-#: portato/gui/templates/portato.glade:719 portato/gui/gtk/windows.py:690
+#: portato/gui/templates/portato.glade:719 portato/gui/gtk/windows.py:691
msgid "E_merge"
msgstr ""
#: portato/gui/templates/portato.glade:104
-#: portato/gui/templates/portato.glade:578
+#: portato/gui/templates/portato.glade:523
#: portato/gui/templates/portato.glade:728
msgid "_Unmerge"
msgstr ""
@@ -115,40 +115,40 @@ msgstr ""
msgid "gtk-find"
msgstr ""
-#: portato/gui/templates/portato.glade:472
-msgid "<b>Installed, but not in portage anymore</b>"
+#: portato/gui/templates/portato.glade:461
+msgid "Installed"
msgstr ""
-#: portato/gui/templates/portato.glade:551
-msgid "<span foreground='red'><b>MISSING KEYWORD</b></span>"
+#: portato/gui/templates/portato.glade:474 portato/gui/gtk/windows.py:668
+#: portato/gui/gtk/windows.py:671 portato/gui/gtk/windows.py:674
+#: portato/gui/gtk/windows.py:773 portato/gui/gtk/windows.py:776
+#: portato/gui/gtk/windows.py:783 portato/gui/gtk/windows.py:787
+msgid "Masked"
msgstr ""
-#: portato/gui/templates/portato.glade:590
-msgid "Re_vert"
+#: portato/gui/templates/portato.glade:488 portato/gui/gtk/windows.py:681
+#: portato/gui/gtk/windows.py:684 portato/gui/gtk/windows.py:745
+#: portato/gui/gtk/windows.py:750
+msgid "Testing"
msgstr ""
-#: portato/gui/templates/portato.glade:602
-msgid "E_build"
+#: portato/gui/templates/portato.glade:535
+msgid "Re_vert"
msgstr ""
-#: portato/gui/templates/portato.glade:628
-msgid "Installed"
+#: portato/gui/templates/portato.glade:547
+msgid "E_build"
msgstr ""
-#: portato/gui/templates/portato.glade:641 portato/gui/gtk/windows.py:667
-#: portato/gui/gtk/windows.py:670 portato/gui/gtk/windows.py:673
-#: portato/gui/gtk/windows.py:778 portato/gui/gtk/windows.py:781
-#: portato/gui/gtk/windows.py:788 portato/gui/gtk/windows.py:792
-msgid "Masked"
+#: portato/gui/templates/portato.glade:568
+msgid "<span foreground='red'><b>MISSING KEYWORD</b></span>"
msgstr ""
-#: portato/gui/templates/portato.glade:655 portato/gui/gtk/windows.py:680
-#: portato/gui/gtk/windows.py:683 portato/gui/gtk/windows.py:750
-#: portato/gui/gtk/windows.py:755
-msgid "Testing"
+#: portato/gui/templates/portato.glade:647
+msgid "<b>Installed, but not in portage anymore</b>"
msgstr ""
-#: portato/gui/templates/portato.glade:682 portato/gui/gtk/windows.py:127
+#: portato/gui/templates/portato.glade:682 portato/gui/gtk/windows.py:128
msgid "Package"
msgstr ""
@@ -156,11 +156,11 @@ msgstr ""
msgid "_Remove"
msgstr ""
-#: portato/gui/templates/portato.glade:777 portato/gui/gtk/windows.py:1003
+#: portato/gui/templates/portato.glade:777 portato/gui/gtk/windows.py:998
msgid "Queue"
msgstr ""
-#: portato/gui/templates/portato.glade:805 portato/gui/gtk/windows.py:1100
+#: portato/gui/templates/portato.glade:805 portato/gui/gtk/windows.py:1095
msgid "Console"
msgstr ""
@@ -214,31 +214,19 @@ msgstr ""
msgid "<b>Sync Options</b>"
msgstr ""
-#: portato/gui/templates/portato.glade:1164
-msgid "File name to use, if package.use is a directory: "
-msgstr ""
-
-#: portato/gui/templates/portato.glade:1175
-msgid "Add only exact version to package.use"
-msgstr ""
-
-#: portato/gui/templates/portato.glade:1188
-msgid "Add only exact version to package.keywords"
-msgstr ""
-
-#: portato/gui/templates/portato.glade:1202
-msgid "File name to use, if package.keywords is a directory: "
+#: portato/gui/templates/portato.glade:1154
+msgid "<u><i>Masking Keywords</i></u>"
msgstr ""
-#: portato/gui/templates/portato.glade:1236
-msgid "File name to use, if package.mask/package.unmask is a directory: "
+#: portato/gui/templates/portato.glade:1169
+msgid "<u><i>Testing Keywords</i></u>"
msgstr ""
-#: portato/gui/templates/portato.glade:1247
-msgid "Add only exact version to package.mask/package.unmask"
+#: portato/gui/templates/portato.glade:1184
+msgid "<u><i>Use-Flags</i></u>"
msgstr ""
-#: portato/gui/templates/portato.glade:1269
+#: portato/gui/templates/portato.glade:1206
msgid ""
"<u>You may use the following placeholders:</u>\n"
"\n"
@@ -247,16 +235,28 @@ msgid ""
"<i>$(cat-1)/$(cat-2)</i>: first/second part of the category"
msgstr ""
-#: portato/gui/templates/portato.glade:1295
-msgid "<u><i>Use-Flags</i></u>"
+#: portato/gui/templates/portato.glade:1230
+msgid "Add only exact version to package.mask/package.unmask"
msgstr ""
-#: portato/gui/templates/portato.glade:1310
-msgid "<u><i>Testing Keywords</i></u>"
+#: portato/gui/templates/portato.glade:1244
+msgid "File name to use, if package.mask/package.unmask is a directory: "
msgstr ""
-#: portato/gui/templates/portato.glade:1325
-msgid "<u><i>Masking Keywords</i></u>"
+#: portato/gui/templates/portato.glade:1278
+msgid "File name to use, if package.keywords is a directory: "
+msgstr ""
+
+#: portato/gui/templates/portato.glade:1289
+msgid "Add only exact version to package.keywords"
+msgstr ""
+
+#: portato/gui/templates/portato.glade:1302
+msgid "Add only exact version to package.use"
+msgstr ""
+
+#: portato/gui/templates/portato.glade:1316
+msgid "File name to use, if package.use is a directory: "
msgstr ""
#: portato/gui/templates/portato.glade:1342
@@ -342,98 +342,102 @@ msgstr ""
msgid "Resume-loop called while process is still running!"
msgstr ""
-#: portato/plugins/etc_proposals.py:64 portato/plugins/etc_proposals.py:76
+#: portato/plugins/etc_proposals.py:65 portato/plugins/etc_proposals.py:77
msgid "Cannot start etc-proposals. No graphical frontend installed!"
msgstr ""
-#: portato/plugins/etc_proposals.py:78
+#: portato/plugins/etc_proposals.py:79
msgid "Cannot start etc-proposals. Not root!"
msgstr ""
-#: portato/gui/gtk/windows.py:72
+#: portato/plugins/notify.py:11
+msgid "Notify called while process is still running!"
+msgstr ""
+
+#: portato/gui/gtk/windows.py:73
msgid "Plugin"
msgstr ""
-#: portato/gui/gtk/windows.py:75
+#: portato/gui/gtk/windows.py:76
msgid "Authors"
msgstr ""
-#: portato/gui/gtk/windows.py:80 portato/gui/gtk/windows.py:126
-#: portato/gui/gtk/windows.py:541
+#: portato/gui/gtk/windows.py:81 portato/gui/gtk/windows.py:127
+#: portato/gui/gtk/windows.py:542
msgid "Enabled"
msgstr ""
-#: portato/gui/gtk/windows.py:225
+#: portato/gui/gtk/windows.py:226
msgid "Results"
msgstr ""
-#: portato/gui/gtk/windows.py:494
+#: portato/gui/gtk/windows.py:495
msgid "<no description>"
msgstr ""
-#: portato/gui/gtk/windows.py:523
+#: portato/gui/gtk/windows.py:524
msgid "This is an expanded use flag and cannot be selected"
msgstr ""
-#: portato/gui/gtk/windows.py:542
+#: portato/gui/gtk/windows.py:543
msgid "Flag"
msgstr ""
-#: portato/gui/gtk/windows.py:543
+#: portato/gui/gtk/windows.py:544
msgid "Description"
msgstr ""
-#: portato/gui/gtk/windows.py:622
+#: portato/gui/gtk/windows.py:623
#, python-format
msgid "Package could not be found: %s"
msgstr ""
-#: portato/gui/gtk/windows.py:693
+#: portato/gui/gtk/windows.py:694
msgid "Re_merge"
msgstr ""
-#: portato/gui/gtk/windows.py:890
+#: portato/gui/gtk/windows.py:885
msgid "Creating Database"
msgstr ""
-#: portato/gui/gtk/windows.py:895
+#: portato/gui/gtk/windows.py:890
msgid "Loading Config"
msgstr ""
-#: portato/gui/gtk/windows.py:906
+#: portato/gui/gtk/windows.py:901
msgid "Loading Plugins"
msgstr ""
-#: portato/gui/gtk/windows.py:919
+#: portato/gui/gtk/windows.py:914
msgid "Finishing startup"
msgstr ""
-#: portato/gui/gtk/windows.py:1006
+#: portato/gui/gtk/windows.py:1001
msgid "Options"
msgstr ""
-#: portato/gui/gtk/windows.py:1024
+#: portato/gui/gtk/windows.py:1019
msgid "Categories"
msgstr ""
-#: portato/gui/gtk/windows.py:1039
+#: portato/gui/gtk/windows.py:1034
msgid "Packages"
msgstr ""
-#: portato/gui/gtk/windows.py:1102
+#: portato/gui/gtk/windows.py:1097
#, python-format
msgid "Console (%(title)s)"
msgstr ""
-#: portato/gui/gtk/windows.py:1154
+#: portato/gui/gtk/windows.py:1149
msgid "use flags"
msgstr ""
-#: portato/gui/gtk/windows.py:1161
+#: portato/gui/gtk/windows.py:1156
msgid "masking keywords"
msgstr ""
-#: portato/gui/gtk/__init__.py:20
+#: portato/gui/gtk/__init__.py:21
msgid "Loading Portage"
msgstr ""
@@ -571,90 +575,98 @@ msgstr ""
msgid "Unrecognized line in configuration: %s"
msgstr ""
-#: portato/plugin.py:287 portato/plugin.py:293 portato/plugin.py:298
+#: portato/plugin.py:290 portato/plugin.py:296 portato/plugin.py:301
#, python-format
msgid "%s cannot be imported."
msgstr ""
-#: portato/plugin.py:325
+#: portato/plugin.py:328
#, python-format
msgid "Accessing hook '%(hook)s' of plugin '%(plugin)s' (before)."
msgstr ""
-#: portato/plugin.py:329
+#: portato/plugin.py:332
#, python-format
msgid "Overriding hook '%(hook)s' with plugin '%(plugin)s'."
msgstr ""
-#: portato/plugin.py:336
+#: portato/plugin.py:339
#, python-format
msgid "Accessing hook '%(hook)s' of plugin '%(plugin)s' (after)."
msgstr ""
-#: portato/plugin.py:356
+#: portato/plugin.py:359
#, python-format
msgid "Loading plugin '%s' failed. Invalid XML syntax."
msgstr ""
-#: portato/plugin.py:359
+#: portato/plugin.py:362
#, python-format
msgid "Loading plugin '%s' failed. Plugin does not comply with schema."
msgstr ""
-#: portato/plugin.py:388
+#: portato/plugin.py:391
#, python-format
msgid "Plugin '%s' loaded."
msgstr ""
-#: portato/plugin.py:391
+#: portato/plugin.py:394
#, python-format
msgid "Loading plugin '%(plugin)s' failed: Could not import %(import)s"
msgstr ""
-#: portato/plugin.py:456
+#: portato/plugin.py:459
#, python-format
msgid ""
"For hook '%(hook)s' an override is already defined by plugin '%(plugin)s'!"
msgstr ""
-#: portato.py:38
+#: portato/plistener.py:95
+msgid "Listener has not been started."
+msgstr ""
+
+#: portato.py:40
msgid "runs pychecker (should only be used by developers)"
msgstr ""
-#: portato.py:41
+#: portato.py:43
#, python-format
msgid "the frontend to use - possible values are: %s [default: %%default]"
msgstr ""
-#: portato.py:44
+#: portato.py:46
msgid "opens the ebuild viewer instead of launching Portato"
msgstr ""
-#: portato.py:47
+#: portato.py:49
msgid "validates the given plugin xml instead of launching Portato"
msgstr ""
-#: portato.py:60
+#: portato.py:52
+msgid "do not start listener"
+msgstr ""
+
+#: portato.py:65
#, python-format
msgid "Unknown frontend '%(frontend)s'. Correct frontends are: %(list)s"
msgstr ""
-#: portato.py:68
+#: portato.py:73
#, python-format
msgid ""
"'%(frontend)s' should be installed, but cannot be imported. This is "
"definitly a bug. (%(error)s)"
msgstr ""
-#: portato.py:78
+#: portato.py:83
#, python-format
msgid "Validation failed. XML syntax error: %s."
msgstr ""
-#: portato.py:81
+#: portato.py:86
msgid "Validation failed. Does not comply with schema."
msgstr ""
-#: portato.py:84
+#: portato.py:89
msgid "Validation succeeded."
msgstr ""
diff --git a/plugin.xsd b/plugin.xsd
index 7f9975b..06b22f6 100644
--- a/plugin.xsd
+++ b/plugin.xsd
@@ -13,7 +13,7 @@
<xs:element name="hook" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
- <xs:element name="connect" minOccurs="1" maxOccurs="unbounded">
+ <xs:element name="connect" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
diff --git a/plugins/noroot.xml b/plugins/notify.xml
index 850a039..8de08c8 100644
--- a/plugins/noroot.xml
+++ b/plugins/notify.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<plugin xmlns="http://portato.sourceforge.net/plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://portato.sourceforge.net/plugin http://portato.sourceforge.net/plugin.xsd">
+
<author>René 'Necoro' Neumann</author>
- <name>No Root</name>
- <import>portato.plugins.noroot</import>
+ <name>Notify</name>
+ <frontends>gtk</frontends>
+
+ <import>portato.plugins.notify</import>
<hooks>
- <hook type = "am_i_root" call = "i_am_root">
- <connect type="override" />
- </hook>
+ <hook type = "after_emerge" call = "notify" />
</hooks>
+
</plugin>
diff --git a/plugins/resume_loop.xml b/plugins/resume_loop.xml
index 01dca78..124d61d 100644
--- a/plugins/resume_loop.xml
+++ b/plugins/resume_loop.xml
@@ -5,9 +5,7 @@
<import>portato.plugins.resume_loop</import>
<hooks>
- <hook type="emerge" call="set_data">
- <connect />
- </hook>
+ <hook type="emerge" call="set_data" />
<hook type="after_emerge" call="resume_loop">
<connect type="before">*</connect>
diff --git a/portato.desktop b/portato.desktop
index e65eaa8..693235e 100644
--- a/portato.desktop
+++ b/portato.desktop
@@ -1,7 +1,7 @@
[Desktop Entry]
Name=Portato
Icon=portato-icon
-Exec=gksu -D "Portato (GTK)" -u root portato gtk
+Exec=portato
StartupNotify=true
Type=Application
Categories=Application;System;PackageManager
diff --git a/portato.py b/portato.py
index e318411..f90fd69 100755
--- a/portato.py
+++ b/portato.py
@@ -12,9 +12,11 @@
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>
-from portato.constants import VERSION, FRONTENDS, STD_FRONTEND, XSD_LOCATION, LOCALE_DIR, APP
+from portato import listener
+from portato.constants import VERSION, FRONTENDS, STD_FRONTEND, XSD_LOCATION, LOCALE_DIR, APP, SU_COMMAND
from optparse import OptionParser
-import sys, os
+from subprocess import call
+import sys, os, socket
import gettext, locale
def get_frontend_list ():
@@ -46,6 +48,9 @@ def main ():
parser.add_option("-x", "--validate", action = "store", dest = "validate", metavar="PLUGIN",
help = _("validates the given plugin xml instead of launching Portato"))
+ parser.add_option("-L", "--no-listener", action = "store_true", dest = "nolistener", default = False,
+ help = _("do not start listener"))
+
# run parser
(options, args) = parser.parse_args()
@@ -83,8 +88,32 @@ def main ():
else:
print _("Validation succeeded.")
return
- else:
+ elif options.nolistener:
+ try:
+ # move this process into a new process group
+ # this is to be able to kill emerge et al w/o killing ourselves :)
+ os.setsid()
+ except OSError:
+ pass
+ listener.set_send()
run()
+ else: # start listener and start us again in root modus
+ if os.fork() == 0:
+ listener.set_recv()
+ else:
+ additional = []
+ if options.check:
+ additional.append("-c")
+ if options.frontend:
+ additional.extend(["-f", options.frontend])
+
+ try:
+ if os.getuid() == 0:
+ call([SU_COMMAND, "%s --no-listener %s" % (sys.argv[0], " ".join(additional))], env = os.environ)
+ else:
+ call([sys.argv[0], "--no-listener"]+additional, env = os.environ)
+ except KeyboardInterrupt:
+ pass
if __name__ == "__main__":
main()
diff --git a/portato/__init__.py b/portato/__init__.py
index f10b9ef..57dd691 100644
--- a/portato/__init__.py
+++ b/portato/__init__.py
@@ -55,3 +55,6 @@ handler.setFormatter(formatter)
logging.getLogger("portatoLogger").addHandler(handler)
logging.getLogger("portatoLogger").setLevel(logging.DEBUG)
logging.getLogger("portatoLogger").propagate = False
+
+from plistener import PListener
+listener = PListener()
diff --git a/portato/constants.py b/portato/constants.py
index c21b0a5..309b774 100644
--- a/portato/constants.py
+++ b/portato/constants.py
@@ -38,6 +38,10 @@ These should be set during the installation.
@type FRONTENDS: string[]
@var STD_FRONTEND: the frontend uses as the default, i.e. if no other one is given on the cmdline
@type STD_FRONTEND: string
+@var SU_COMMAND: command to execute to "su"
+@type SU_COMMAND: string
+@var SOCKET: path to socket for communication between listener and GUI
+@type SOCKET: string
"""
from os.path import join as pjoin
@@ -60,3 +64,6 @@ LOCALE_DIR = "i18n/"
FRONTENDS = ["gtk" ,"qt"]
STD_FRONTEND = "gtk"
+
+SU_COMMAND = "gksu -D 'Portato'"
+SOCKET = "/tmp/portato.socket"
diff --git a/portato/gui/gtk/__init__.py b/portato/gui/gtk/__init__.py
index 0714f39..ba49652 100644
--- a/portato/gui/gtk/__init__.py
+++ b/portato/gui/gtk/__init__.py
@@ -12,6 +12,7 @@
from gettext import lgettext as _
+from portato import listener
from exception_handling import register_ex_handler
def run ():
@@ -27,6 +28,8 @@ def run ():
except KeyboardInterrupt:
pass
+ listener.close()
+
def show_ebuild (pkg):
import gtk
from portato import plugin
diff --git a/portato/gui/gtk/windows.py b/portato/gui/gtk/windows.py
index 74f7058..f0b7f1b 100644
--- a/portato/gui/gtk/windows.py
+++ b/portato/gui/gtk/windows.py
@@ -20,6 +20,7 @@ from subprocess import Popen
from gettext import lgettext as _
# our backend stuff
+from portato import listener
from portato.helper import *
from portato.constants import CONFIG_LOCATION, VERSION, APP_ICON
from portato.backend import flags, system
@@ -335,7 +336,7 @@ class PreferenceWindow (AbstractDialog):
self.cfg.set("consolefont", font, section = "GTK")
self.set_console_font(font)
- gtk.link_button_set_uri_hook(lambda btn, x: Popen([self.cfg.get("browserCmd", section = "GUI"), btn.get_uri()]))
+ gtk.link_button_set_uri_hook(lambda btn, x: listener.send_cmd([self.cfg.get("browserCmd", section = "GUI"), btn.get_uri()]))
def cb_ok_clicked(self, button):
"""Saves, writes to config-file and closes the window."""
@@ -717,20 +718,14 @@ class PackageTable:
def cb_package_emerge_clicked (self, button):
"""Callback for pressed emerge-button. Adds the package to the EmergeQueue."""
- if not am_i_root():
- not_root_dialog()
- else:
- self._update_keywords(True)
- self.main.notebook.set_current_page(self.main.QUEUE_PAGE)
+ self._update_keywords(True)
+ self.main.notebook.set_current_page(self.main.QUEUE_PAGE)
return True
def cb_package_unmerge_clicked (self, button):
"""Callback for pressed unmerge-button clicked. Adds the package to the UnmergeQueue."""
- if not am_i_root():
- not_root_dialog()
- else:
- self._update_keywords(False)
- self.main.notebook.set_current_page(self.main.QUEUE_PAGE)
+ self._update_keywords(False)
+ self.main.notebook.set_current_page(self.main.QUEUE_PAGE)
return True
def cb_package_ebuild_clicked(self, button):
@@ -900,7 +895,7 @@ class MainWindow (Window):
raise
self.cfg.modify_external_configs()
- gtk.link_button_set_uri_hook(lambda btn, x: Popen([self.cfg.get("browserCmd", section = "GUI"), btn.get_uri()]))
+ gtk.link_button_set_uri_hook(lambda btn, x: listener.send_cmd([self.cfg.get("browserCmd", section = "GUI"), btn.get_uri()]))
# set plugins and plugin-menu
splash(_("Loading Plugins"))
@@ -1177,47 +1172,43 @@ class MainWindow (Window):
return True
def cb_update_clicked (self, action):
- if not am_i_root():
- not_root_dialog()
- else:
+ def __update():
- def __update():
-
- def cb_idle_append (pkg, unmask):
- self.queue.append(pkg.get_cpv(), unmask = unmask)
- return False
+ def cb_idle_append (pkg, unmask):
+ self.queue.append(pkg.get_cpv(), unmask = unmask)
+ return False
- def cb_idle_unmask_dialog (e, updating):
- if unmask_dialog(e[0]) == gtk.RESPONSE_YES:
- for pkg, old_pkg in updating:
- self.queue.append(pkg.get_cpv(), unmask = True)
- return False
+ def cb_idle_unmask_dialog (e, updating):
+ if unmask_dialog(e[0]) == gtk.RESPONSE_YES:
+ for pkg, old_pkg in updating:
+ self.queue.append(pkg.get_cpv(), unmask = True)
+ return False
- def cb_idle_blocked(e):
- blocked_dialog(e[0], e[1])
- self.queue.remove_children(self.queue.emergeIt)
- return False
+ def cb_idle_blocked(e):
+ blocked_dialog(e[0], e[1])
+ self.queue.remove_children(self.queue.emergeIt)
+ return False
- watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
- self.window.window.set_cursor(watch)
+ watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
+ self.window.window.set_cursor(watch)
+ try:
+ updating = system.update_world(newuse = self.cfg.get_boolean("newuse"), deep = self.cfg.get_boolean("deep"))
+ debug("updating list: %s --> length: %s", [(x.get_cpv(), y.get_cpv()) for x,y in updating], len(updating))
try:
- updating = system.update_world(newuse = self.cfg.get_boolean("newuse"), deep = self.cfg.get_boolean("deep"))
- debug("updating list: %s --> length: %s", [(x.get_cpv(), y.get_cpv()) for x,y in updating], len(updating))
try:
- try:
- for pkg, old_pkg in updating:
- gobject.idle_add(cb_idle_append, pkg, False)
- except PackageNotFoundException, e:
- gobject.idle_add(cb_idle_unmask_dialog, e, updating)
-
- except BlockedException, e:
- gobject.idle_add(cb_idle_blocked(e))
-
- if len(updating): self.doUpdate = True
- finally:
- self.window.window.set_cursor(None)
+ for pkg, old_pkg in updating:
+ gobject.idle_add(cb_idle_append, pkg, False)
+ except PackageNotFoundException, e:
+ gobject.idle_add(cb_idle_unmask_dialog, e, updating)
- GtkThread(name="Update-Thread", target=__update).start()
+ except BlockedException, e:
+ gobject.idle_add(cb_idle_blocked(e))
+
+ if len(updating): self.doUpdate = True
+ finally:
+ self.window.window.set_cursor(None)
+
+ GtkThread(name="Update-Thread", target=__update).start()
return True
@@ -1245,26 +1236,20 @@ class MainWindow (Window):
return True
def cb_sync_clicked (self, action):
- if not am_i_root():
- not_root_dialog()
- else:
- self.notebook.set_current_page(self.CONSOLE_PAGE)
- cmd = self.cfg.get("syncCmd")
+ self.notebook.set_current_page(self.CONSOLE_PAGE)
+ cmd = self.cfg.get("syncCmd")
- if cmd != "emerge --sync":
- cmd = cmd.split()
- self.queue.sync(cmd)
- else:
- self.queue.sync()
+ if cmd != "emerge --sync":
+ cmd = cmd.split()
+ self.queue.sync(cmd)
+ else:
+ self.queue.sync()
def cb_save_flags_clicked (self, action):
- if not am_i_root():
- not_root_dialog()
- else:
- flags.write_use_flags()
- flags.write_testing()
- flags.write_masked()
-
+ flags.write_use_flags()
+ flags.write_testing()
+ flags.write_masked()
+
@Window.watch_cursor
def cb_reload_clicked (self, action):
"""Reloads the portage settings and the database."""
diff --git a/portato/gui/templates/portato.glade b/portato/gui/templates/portato.glade
index fe57c9a..77f8a8f 100644
--- a/portato/gui/templates/portato.glade
+++ b/portato/gui/templates/portato.glade
@@ -450,109 +450,54 @@
<property name="n_rows">5</property>
<property name="n_columns">3</property>
<child>
- <widget class="GtkHBox" id="pkgLinkBox">
+ <widget class="GtkHBox" id="checkHB">
<property name="visible">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="spacing">1</property>
+ <property name="homogeneous">True</property>
<child>
- <placeholder/>
+ <widget class="GtkCheckButton" id="installedCheck">
+ <property name="visible">True</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Installed</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="button_press_event" handler="cb_button_pressed"/>
+ </widget>
+ <packing>
+ <property name="fill">False</property>
+ </packing>
</child>
- </widget>
- <packing>
- <property name="right_attach">3</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_EXPAND</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="notInSysLabel">
- <property name="visible">True</property>
- <property name="no_show_all">True</property>
- <property name="label" translatable="yes">&lt;b&gt;Installed, but not in portage anymore&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="right_attach">3</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="hbox2">
- <property name="visible">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="spacing">5</property>
<child>
- <widget class="GtkScrolledWindow" id="versionListScroll">
+ <widget class="GtkCheckButton" id="maskedCheck">
<property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <child>
- <widget class="GtkTreeView" id="versionList">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="headers_clickable">True</property>
- <property name="show_expanders">False</property>
- <signal name="cursor_changed" handler="cb_vers_list_changed"/>
- </widget>
- </child>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Masked</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="cb_masked_toggled"/>
</widget>
<packing>
- <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
- <widget class="GtkScrolledWindow" id="useListScroll">
+ <widget class="GtkCheckButton" id="testingCheck">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
- <child>
- <widget class="GtkTreeView" id="useList">
- <property name="visible">True</property>
- </widget>
- </child>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">Testing</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="cb_testing_toggled"/>
</widget>
<packing>
- <property name="position">1</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="right_attach">3</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_padding">5</property>
- <property name="y_padding">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="descLabel">
- <property name="visible">True</property>
- <property name="justify">GTK_JUSTIFY_CENTER</property>
- <property name="wrap">True</property>
- </widget>
- <packing>
- <property name="right_attach">3</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- <property name="y_padding">10</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="missingLabel">
- <property name="visible">True</property>
- <property name="no_show_all">True</property>
- <property name="label" translatable="yes">&lt;span foreground='red'&gt;&lt;b&gt;MISSING KEYWORD&lt;/b&gt;&lt;/span&gt;</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="right_attach">3</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options">GTK_FILL</property>
@@ -617,51 +562,90 @@
</packing>
</child>
<child>
- <widget class="GtkHBox" id="checkHB">
+ <widget class="GtkLabel" id="missingLabel">
<property name="visible">True</property>
- <property name="spacing">1</property>
- <property name="homogeneous">True</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">&lt;span foreground='red'&gt;&lt;b&gt;MISSING KEYWORD&lt;/b&gt;&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="descLabel">
+ <property name="visible">True</property>
+ <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ <property name="y_padding">10</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="spacing">5</property>
<child>
- <widget class="GtkCheckButton" id="installedCheck">
+ <widget class="GtkScrolledWindow" id="versionListScroll">
<property name="visible">True</property>
- <property name="no_show_all">True</property>
- <property name="label" translatable="yes">Installed</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- <signal name="button_press_event" handler="cb_button_pressed"/>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <child>
+ <widget class="GtkTreeView" id="versionList">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="headers_clickable">True</property>
+ <property name="show_expanders">False</property>
+ <signal name="cursor_changed" handler="cb_vers_list_changed"/>
+ </widget>
+ </child>
</widget>
<packing>
- <property name="fill">False</property>
+ <property name="expand">False</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="maskedCheck">
+ <widget class="GtkScrolledWindow" id="useListScroll">
<property name="visible">True</property>
- <property name="no_show_all">True</property>
- <property name="label" translatable="yes">Masked</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="cb_masked_toggled"/>
+ <property name="can_focus">False</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <child>
+ <widget class="GtkTreeView" id="useList">
+ <property name="visible">True</property>
+ </widget>
+ </child>
</widget>
<packing>
- <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
- <child>
- <widget class="GtkCheckButton" id="testingCheck">
- <property name="visible">True</property>
- <property name="no_show_all">True</property>
- <property name="label" translatable="yes">Testing</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="cb_testing_toggled"/>
- </widget>
- <packing>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_padding">5</property>
+ <property name="y_padding">5</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="notInSysLabel">
+ <property name="visible">True</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;Installed, but not in portage anymore&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
</widget>
<packing>
<property name="right_attach">3</property>
@@ -670,6 +654,22 @@
<property name="y_options">GTK_FILL</property>
</packing>
</child>
+ <child>
+ <widget class="GtkHBox" id="pkgLinkBox">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_EXPAND</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="tab_expand">False</property>
@@ -1147,189 +1147,189 @@
<placeholder/>
</child>
<child>
- <widget class="GtkEntry" id="useFileEdit">
+ <widget class="GtkLabel" id="maskLabel">
<property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">5</property>
+ <property name="label" translatable="yes">&lt;u&gt;&lt;i&gt;Masking Keywords&lt;/i&gt;&lt;/u&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="single_line_mode">True</property>
</widget>
<packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="y_padding">5</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="useEditLabel">
+ <widget class="GtkLabel" id="testLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">File name to use, if package.use is a directory: </property>
+ <property name="xpad">5</property>
+ <property name="label" translatable="yes">&lt;u&gt;&lt;i&gt;Testing Keywords&lt;/i&gt;&lt;/u&gt;</property>
+ <property name="use_markup">True</property>
<property name="single_line_mode">True</property>
</widget>
<packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_padding">5</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="usePerVersionCheck">
+ <widget class="GtkLabel" id="useLabel">
<property name="visible">True</property>
- <property name="label" translatable="yes">Add only exact version to package.use</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">5</property>
+ <property name="label" translatable="yes">&lt;u&gt;&lt;i&gt;Use-Flags&lt;/i&gt;&lt;/u&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="single_line_mode">True</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_padding">6</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEventBox" id="hintEB">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkFrame" id="hintFrame">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_OUT</property>
+ <child>
+ <widget class="GtkLabel" id="hintLabel">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;u&gt;You may use the following placeholders:&lt;/u&gt;
+
+&lt;i&gt;$(cat)&lt;/i&gt;: category
+&lt;i&gt;$(pkg)&lt;/i&gt;: package name
+&lt;i&gt;$(cat-1)/$(cat-2)&lt;/i&gt;: first/second part of the category</property>
+ <property name="use_markup">True</property>
+ </widget>
+ </child>
+ <child>
+ <placeholder/>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
</widget>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="testPerVersionCheck">
+ <widget class="GtkCheckButton" id="maskPerVersionCheck">
<property name="visible">True</property>
- <property name="label" translatable="yes">Add only exact version to package.keywords</property>
+ <property name="label" translatable="yes">Add only exact version to package.mask/package.unmask</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="testEditLabel">
+ <widget class="GtkLabel" id="maskEditLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">File name to use, if package.keywords is a directory: </property>
+ <property name="label" translatable="yes">File name to use, if package.mask/package.unmask is a directory: </property>
<property name="single_line_mode">True</property>
</widget>
<packing>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
+ <property name="top_attach">9</property>
+ <property name="bottom_attach">10</property>
</packing>
</child>
<child>
- <widget class="GtkEntry" id="testFileEdit">
+ <widget class="GtkEntry" id="maskFileEdit">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
+ <property name="top_attach">9</property>
+ <property name="bottom_attach">10</property>
</packing>
</child>
<child>
- <widget class="GtkEntry" id="maskFileEdit">
+ <widget class="GtkEntry" id="testFileEdit">
<property name="visible">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
- <property name="top_attach">9</property>
- <property name="bottom_attach">10</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="maskEditLabel">
+ <widget class="GtkLabel" id="testEditLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">File name to use, if package.mask/package.unmask is a directory: </property>
+ <property name="label" translatable="yes">File name to use, if package.keywords is a directory: </property>
<property name="single_line_mode">True</property>
</widget>
<packing>
- <property name="top_attach">9</property>
- <property name="bottom_attach">10</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
</packing>
</child>
<child>
- <widget class="GtkCheckButton" id="maskPerVersionCheck">
+ <widget class="GtkCheckButton" id="testPerVersionCheck">
<property name="visible">True</property>
- <property name="label" translatable="yes">Add only exact version to package.mask/package.unmask</property>
+ <property name="label" translatable="yes">Add only exact version to package.keywords</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="right_attach">2</property>
- <property name="top_attach">8</property>
- <property name="bottom_attach">9</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
</packing>
</child>
<child>
- <widget class="GtkEventBox" id="hintEB">
+ <widget class="GtkCheckButton" id="usePerVersionCheck">
<property name="visible">True</property>
- <child>
- <widget class="GtkFrame" id="hintFrame">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">GTK_SHADOW_OUT</property>
- <child>
- <widget class="GtkLabel" id="hintLabel">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">&lt;u&gt;You may use the following placeholders:&lt;/u&gt;
-
-&lt;i&gt;$(cat)&lt;/i&gt;: category
-&lt;i&gt;$(pkg)&lt;/i&gt;: package name
-&lt;i&gt;$(cat-1)/$(cat-2)&lt;/i&gt;: first/second part of the category</property>
- <property name="use_markup">True</property>
- </widget>
- </child>
- <child>
- <placeholder/>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- </child>
+ <property name="label" translatable="yes">Add only exact version to package.use</property>
+ <property name="response_id">0</property>
+ <property name="draw_indicator">True</property>
</widget>
<packing>
<property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="useLabel">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">5</property>
- <property name="label" translatable="yes">&lt;u&gt;&lt;i&gt;Use-Flags&lt;/i&gt;&lt;/u&gt;</property>
- <property name="use_markup">True</property>
- <property name="single_line_mode">True</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_padding">6</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="testLabel">
+ <widget class="GtkLabel" id="useEditLabel">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="xpad">5</property>
- <property name="label" translatable="yes">&lt;u&gt;&lt;i&gt;Testing Keywords&lt;/i&gt;&lt;/u&gt;</property>
- <property name="use_markup">True</property>
+ <property name="label" translatable="yes">File name to use, if package.use is a directory: </property>
<property name="single_line_mode">True</property>
</widget>
<packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- <property name="y_padding">5</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
</packing>
</child>
<child>
- <widget class="GtkLabel" id="maskLabel">
+ <widget class="GtkEntry" id="useFileEdit">
<property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">5</property>
- <property name="label" translatable="yes">&lt;u&gt;&lt;i&gt;Masking Keywords&lt;/i&gt;&lt;/u&gt;</property>
- <property name="use_markup">True</property>
- <property name="single_line_mode">True</property>
</widget>
<packing>
- <property name="top_attach">7</property>
- <property name="bottom_attach">8</property>
- <property name="y_padding">5</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
</packing>
</child>
</widget>
diff --git a/portato/helper.py b/portato/helper.py
index 754f566..cb3289c 100644
--- a/portato/helper.py
+++ b/portato/helper.py
@@ -14,7 +14,7 @@
Some nice functions used in the program.
"""
-import os, signal, logging
+import os, signal, logging, grp
debug = logging.getLogger("portatoLogger").debug
info = logging.getLogger("portatoLogger").info
@@ -43,21 +43,6 @@ def send_signal_to_group (sig):
pgid = os.getpgrp()
os.killpg(pgid, sig)
-def am_i_root ():
- """Returns True if the current user is root, False otherwise.
- @rtype: boolean"""
-
- from plugin import hook
-
- @hook("am_i_root")
- def __am_i_root():
- if os.getuid() == 0:
- return True
- else:
- return False
-
- return __am_i_root()
-
def flatten (listOfLists):
"""Flattens the given list of lists.
diff --git a/portato/plistener.py b/portato/plistener.py
new file mode 100644
index 0000000..29054b2
--- /dev/null
+++ b/portato/plistener.py
@@ -0,0 +1,127 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/gui/gtk/plistener.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2007 René 'Necoro' Neumann
+# 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 René 'Necoro' Neumann <necoro@necoro.net>
+
+import socket, os
+from subprocess import Popen
+from gettext import lgettext as _
+
+try:
+ import pynotify
+except ImportError:
+ pynotify = None
+
+from constants import SOCKET, APP
+from helper import debug, warning
+
+class PListener (object):
+ """This class handles the communication between the "listener" and the GUI.
+ This listener starts programs as the user while the GUI runs as root.
+
+ @ivar _recv: listener socket
+ @type _recv: socket.socket
+ @ivar _send: sender socket
+ @type _send: socket.socket"""
+
+ def set_recv (self):
+ self._recv = socket.socket(socket.AF_UNIX)
+
+ try:
+ self._recv.bind(SOCKET)
+ except socket.error, e:
+ if int(e[0]) == 98: # already existing - delete
+ os.unlink(SOCKET)
+ self._recv.bind(SOCKET)
+ else:
+ raise
+
+ self._recv.listen(1)
+ con, addr = self._recv.accept()
+
+ while True:
+ try:
+ len = con.recv(4)
+ string = con.recv(int(len))
+
+ data = string.split("\0")
+ debug(data)
+
+ if data[0] == "notify":
+ self.do_notify(*data[1:])
+ elif data[0] == "cmd":
+ self.do_cmd(data[1:])
+ elif data[0] == "close":
+ break
+ except KeyboardInterrupt:
+ pass
+
+ con.close()
+ self._recv.close()
+
+ def do_cmd (self, cmdlist):
+ """Starts a command as the user.
+
+ @param cmdlist: list of command (options)
+ @type cmdlist: string[]"""
+
+ Popen(cmdlist)
+
+ def do_notify(self, base, descr, icon, urgency):
+ """Displays a notify.
+ This will do nothing if pynotify is not present and/or root is running the listener."""
+
+ if pynotify and not os.getuid == 0:
+ if not pynotify.is_initted():
+ pynotify.init(APP)
+
+ n = pynotify.Notification(base, descr, icon)
+ n.set_urgency(int(urgency))
+ n.show()
+
+ def set_send (self):
+ self._send = socket.socket(socket.AF_UNIX)
+ try:
+ self._send.connect(SOCKET)
+ except socket.error, e:
+ if e[0] in [111, 2]: # can't connect
+ warning(_("Listener has not been started."))
+ self._send = None
+ else:
+ raise
+
+ def __send (self, string):
+ self._send.sendall("%4d" % len(string))
+ self._send.sendall(string)
+
+ def send_notify (self, base = "", descr = "", icon = "", urgency = None):
+ if self._send is None:
+ self.do_notify(base, descr, icon, urgency)
+ else:
+ string = "\0".join(["notify", base, descr, icon])
+
+ if urgency is not None:
+ string += "\0%d" % urgency
+ else:
+ string += "\0"
+
+ self.__send(string)
+
+ def send_cmd (self, cmdlist):
+ if self._send is None:
+ self.do_cmd(cmdlist)
+ else:
+ self.__send("\0".join(["cmd"] +cmdlist))
+
+ def close (self):
+ if self._send is not None:
+ self.__send("close")
+ self._send.close()
+ os.unlink(SOCKET)
diff --git a/portato/plugin.py b/portato/plugin.py
index 3b065b9..baa5d0c 100644
--- a/portato/plugin.py
+++ b/portato/plugin.py
@@ -133,6 +133,9 @@ class Hook:
@param connects: the list of <connect>'s
@type connects: NodeList"""
+ if not connects: # no connects - assume "before" connect
+ self.connects.append(Connect(self, "before", None))
+
for c in connects:
type = c.getAttribute("type")
if type == '':
diff --git a/portato/plugins/etc_proposals.py b/portato/plugins/etc_proposals.py
index 81370e0..f094599 100644
--- a/portato/plugins/etc_proposals.py
+++ b/portato/plugins/etc_proposals.py
@@ -13,6 +13,7 @@
from portato.helper import *
from portato.backend import system
+import os
from subprocess import Popen
from gettext import lgettext as _
from etcproposals.etcproposals_lib import EtcProposals, __version__
@@ -64,7 +65,7 @@ def etc_prop (*args, **kwargs):
error(_("Cannot start etc-proposals. No graphical frontend installed!"))
def etc_prop_menu (*args, **kwargs):
- if am_i_root():
+ if os.getuid() == 0:
if float(__version__) < 1.1:
Popen(PROG)
else:
diff --git a/portato/plugins/noroot.py b/portato/plugins/noroot.py
deleted file mode 100644
index a28ef85..0000000
--- a/portato/plugins/noroot.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# File: portato/plugins/noroot.py
-# This file is part of the Portato-Project, a graphical portage-frontend.
-#
-# Copyright (C) 2007 René 'Necoro' Neumann
-# 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 René 'Necoro' Neumann <necoro@necoro.net>
-
-def i_am_root (*args):
- """Pretend we are root."""
- return True
diff --git a/portato/plugins/notify.py b/portato/plugins/notify.py
new file mode 100644
index 0000000..5e4a577
--- /dev/null
+++ b/portato/plugins/notify.py
@@ -0,0 +1,23 @@
+from gettext import lgettext as _
+import pynotify
+
+from portato import listener
+
+from portato.helper import warning, error, debug
+from portato.constants import APP_ICON, APP
+
+def notify (retcode, **kwargs):
+ if retcode is None:
+ warning(_("Notify called while process is still running!"))
+ else:
+ icon = APP_ICON
+ if retcode == 0:
+ text = "Emerge finished!"
+ descr = ""
+ urgency = pynotify.URGENCY_NORMAL
+ else:
+ text = "Emerge failed!"
+ descr = "Error Code: %d" % retcode
+ urgency = pynotify.URGENCY_CRITICAL
+
+ listener.send_notify(base = text, descr = descr, icon = icon, urgency = urgency)