diff options
Diffstat (limited to 'portato/gui/windows')
-rw-r--r-- | portato/gui/windows/__init__.py | 2 | ||||
-rw-r--r-- | portato/gui/windows/about.py | 15 | ||||
-rw-r--r-- | portato/gui/windows/basic.py | 5 | ||||
-rw-r--r-- | portato/gui/windows/mailinfo.py | 139 | ||||
-rw-r--r-- | portato/gui/windows/main.py | 86 | ||||
-rw-r--r-- | portato/gui/windows/pkglist.py | 2 | ||||
-rw-r--r-- | portato/gui/windows/plugin.py | 2 | ||||
-rw-r--r-- | portato/gui/windows/preference.py | 2 | ||||
-rw-r--r-- | portato/gui/windows/search.py | 2 | ||||
-rw-r--r-- | portato/gui/windows/splash.py | 2 |
10 files changed, 203 insertions, 54 deletions
diff --git a/portato/gui/windows/__init__.py b/portato/gui/windows/__init__.py index 6a4ac82..5be95ce 100644 --- a/portato/gui/windows/__init__.py +++ b/portato/gui/windows/__init__.py @@ -3,7 +3,7 @@ # File: portato/gui/gtk/__init__.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. diff --git a/portato/gui/windows/about.py b/portato/gui/windows/about.py index 6c6fec5..0d2ce1a 100644 --- a/portato/gui/windows/about.py +++ b/portato/gui/windows/about.py @@ -3,19 +3,20 @@ # File: portato/gui/windows/about.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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> -from __future__ import absolute_import +from __future__ import absolute_import, with_statement +import os import gtk from .basic import AbstractDialog -from ...constants import VERSION, REVISION, APP_ICON +from ...constants import VERSION, REVISION, DATA_DIR class AboutWindow (AbstractDialog): """A window showing the "about"-informations.""" @@ -24,11 +25,11 @@ class AboutWindow (AbstractDialog): AbstractDialog.__init__(self, parent) - img = gtk.Image() - img.set_from_file(APP_ICON) - self.window.set_version(VERSION) - self.window.set_logo(img.get_pixbuf()) + self.window.set_logo(None) + + with open(os.path.join(DATA_DIR, "TRANSLATORS")) as f: + self.window.set_translator_credits("".join(f.readlines())) if REVISION: gitlabel = self.tree.get_widget("gitLabel") diff --git a/portato/gui/windows/basic.py b/portato/gui/windows/basic.py index 20d8009..01d31e5 100644 --- a/portato/gui/windows/basic.py +++ b/portato/gui/windows/basic.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/basic.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. @@ -151,6 +151,9 @@ class AbstractDialog (Window): self.window.set_transient_for(parent) self.parent = parent + # type hint + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + # catch the ESC-key self.window.connect("key-press-event", self.cb_key_pressed) diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py index 0cc79f2..4367482 100644 --- a/portato/gui/windows/mailinfo.py +++ b/portato/gui/windows/mailinfo.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/mailinfo.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. @@ -14,34 +14,98 @@ from __future__ import absolute_import, with_statement import smtplib, socket import time +import gtk, pango, gobject from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from os.path import basename from .basic import AbstractDialog from ..utils import GtkThread -from ..dialogs import mail_failure_dialog +from .. import dialogs from ...helper import debug, info -from ...constants import VERSION +from ...constants import VERSION, CONFIG_LOCATION from ...log import LOGFILE +from ... import session + +def mail_failure_dialog(*a): + dialogs.mail_failure_dialog(*a) + return False + +class ShowDialog (gtk.Dialog): + + def __init__(self, parent, f): + gtk.Dialog.__init__(self, f, parent, buttons = (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) + + textview = gtk.TextView() + textview.set_editable(False) + textview.modify_font(pango.FontDescription("Monospace")) + textview.set_size_request(gtk.gdk.screen_width()/2, gtk.gdk.screen_height()/3) + + sw = gtk.ScrolledWindow(); + sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sw.add(textview) + + self.vbox.add(sw) + + textbuffer = textview.get_buffer() + + with open(f) as text: + textbuffer.set_text(text.read()) + + self.vbox.show_all() class MailInfoWindow (AbstractDialog): - TO = "bugs@portato.necoro.net" + TO = "bugs@necoro.eu" def __init__ (self, parent, tb): AbstractDialog.__init__(self, parent) + + self.files = [LOGFILE, CONFIG_LOCATION] + [s._file for s in session.sessionlist] + self.fileList = self.tree.get_widget("fileList") + self.build_file_list() + self.mailEntry = self.tree.get_widget("mailEntry") self.tb = tb self.window.show_all() + def build_file_list(self): + store = gtk.ListStore(bool, str) + + for f in self.files: + store.append((True, f)) + + self.fileList.set_model(store) + cell = gtk.CellRendererText() + tCell = gtk.CellRendererToggle() + tCell.set_property("activatable", True) + tCell.connect("toggled", self.cb_file_toggled) + + self.fileList.append_column(gtk.TreeViewColumn(None, tCell, active = 0)) + self.fileList.append_column(gtk.TreeViewColumn(None, cell, text = 1)) + + def cb_file_toggled(self, cell, path): + store = self.fileList.get_model() + store[path][0] = not store[path][0] + return True + + def cb_file_clicked(self, view, path, *args): + store = view.get_model() + f = store[path][1] + + dialog = ShowDialog(self.window, f) + dialog.run() + dialog.destroy() + def set_data (self): self.message = MIMEMultipart() self.message["Subject"] = "[Bug Report] Bug in Portato %s" % VERSION self.message["To"] = self.TO + self.message["X-Portato-Version"] = VERSION # TO and FROM name = self.tree.get_widget("nameEntry").get_text() - self.addr = self.tree.get_widget("mailEntry").get_text() + self.addr = self.mailEntry.get_text() if not self.addr: self.addr = self.TO @@ -63,40 +127,61 @@ class MailInfoWindow (AbstractDialog): txtmsg = MIMEText(text, "plain", "utf-8") self.message.attach(txtmsg) - # log - if self.tree.get_widget("logCheck").get_active(): - with open(LOGFILE, "r") as f: - log = MIMEText(f.read(), "plain", "utf-8") - log.add_header('Content-Disposition', 'attachment', filename='portato.log') + # logs + for (active, f) in self.fileList.get_model(): + if active: + debug("Attaching '%s'", f) + with open(f, "r") as text: + log = MIMEText(text.read(), "plain", "utf-8") + log.add_header('Content-Disposition', 'attachment', filename=basename(f)) - self.message.attach(log) + self.message.attach(log) def send (self): try: - debug("Connecting to server") - server = smtplib.SMTP("mail.necoro.eu") - debug("Sending mail") - try: + for i in range(5): # try 5 times at max + if i > 0: + info(_("Retrying after waiting %d seconds."), 300) + time.sleep(300) try: + debug("Connecting to server") + server = smtplib.SMTP("mail.necoro.eu") + debug("Sending mail") + + if smtplib._have_ssl: server.starttls() + else: debug("TLS not supported in Python. Continuing without it.") + server.sendmail(self.addr, self.TO, self.message.as_string()) except smtplib.SMTPRecipientsRefused, e: - info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) - info(_("Retrying after waiting 60 seconds.")) - time.sleep(60) - server.sendmail(self.addr, self.TO, self.message.as_string()) - debug("Sent") - finally: - server.quit() + if e.recipients[self.TO][0] < 500: + info(_("An error occurred while sending. I think we were greylisted. The error: %s") % e) + else: raise + else: + debug("Sent") + break + finally: + try: + server.quit() + except smtplib.SMTPServerDisconnected: + pass # ignore this except socket.error, e: - mail_failure_dialog("%s (Code: %s)" % (e.args[1], e.args[0])) + gobject.idle_add(mail_failure_dialog, "%s (Code: %s)" % (e.args[1], e.args[0])) + except smtplib.SMTPResponseException, e: + gobject.idle_add(mail_failure_dialog, "%s (Code: %s)" % (e.smtp_error, e.smtp_code)) + except smtplib.SMTPException, e: + gobject.idle_add(mail_failure_dialog, e.args) def cb_cancel_clicked (self, *args): - self.close() return True def cb_send_clicked (self, *args): - self.set_data() - GtkThread(target = self.send, name = "Mail Send Thread").start() - self.close() + if self.mailEntry.get_text() or dialogs.no_email_dialog(self.window) == gtk.RESPONSE_OK: + self.set_data() + GtkThread(target = self.send, name = "Mail Send Thread").start() + self.close() + else: + self.window.present() + self.mailEntry.grab_focus() + return True diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index ca88b04..3c868e8 100644 --- a/portato/gui/windows/main.py +++ b/portato/gui/windows/main.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/main.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. @@ -29,7 +29,8 @@ from ... import get_listener from ...helper import debug, warning, error, info from ...session import Session from ...db import Database -from ...constants import CONFIG_LOCATION, VERSION, APP_ICON +from ...db.database import UnsupportedSearchTypeError +from ...constants import CONFIG_LOCATION, VERSION, APP_ICON, ICON_DIR from ...backend.exceptions import PackageNotFoundException, BlockedException, VersionsNotFoundException # plugin stuff @@ -434,18 +435,27 @@ class MainWindow (Window): self.window.set_geometry_hints (self.window, max_height = gtk.gdk.screen_height(), max_width = gtk.gdk.screen_width()) # app icon - self.window.set_icon_from_file(APP_ICON) - gtk.window_set_default_icon(self.window.get_icon()) + gtk.window_set_default_icon_from_file(APP_ICON) # booleans self.doUpdate = False self.showAll = True # show only installed or all packages? self.__searchChanged = False + # our own icon factory + fac = gtk.IconFactory() + iSet = gtk.IconSet() + iSource = gtk.IconSource() + iSource.set_filename(os.path.abspath(os.path.join(ICON_DIR, "better-package.svg"))) + iSet.add_source(iSource) + fac.add("portato-better-pkg", iSet) + fac.add_default() + # icons self.icons = {} self.icons["installed"] = self.window.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) self.icons["or"] = self.window.render_icon(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_MENU) + self.icons["better"] = self.window.render_icon("portato-better-pkg", gtk.ICON_SIZE_MENU) # get the logging window as soon as possible self.logView = LogView(self.tree.get_widget("logView")) @@ -556,6 +566,10 @@ class MainWindow (Window): splash(_("Finishing startup")) + # depends on session + self.typeCombo = self.tree.get_widget("typeCombo") + self.build_type_combo() + self.window.show_all() def show_package (self, pkg = None, cpv = None, cp = None, version = None, **kwargs): @@ -782,10 +796,14 @@ class MainWindow (Window): if not packages: raise VersionsNotFoundException(cp) + best = system.find_best_match(cp) + # append versions for vers, inst, slot in ((x.get_version(), x.is_installed(), get_slot(x)) for x in packages): if inst: icon = self.icons["installed"] + elif best is not None and vers == best.get_version(): + icon = self.icons["better"] else: icon = None @@ -871,6 +889,26 @@ class MainWindow (Window): else: # no selCatName -> so no category selected --> ignore debug("No category selected --> should be no harm.") + def build_type_combo (self): + model = gtk.ListStore(int, str) + for k,v in self.db.TYPES.iteritems(): + model.append((k,v)) + + self.typeCombo.set_model(model) + cell = gtk.CellRendererText() + self.typeCombo.pack_start(cell) + self.typeCombo.set_attributes(cell, text = 1) + + + for i, (k, v) in enumerate(model): + if k == self.db.type: break + + self.typeCombo.set_active(i) + + types = self.db.search_types() + if types == 1 or types % 2 == 0: + self.typeCombo.set_sensitive(False) + def load_session(self, sessionEx = None, defaults_only = False): """ Loads the session data. @@ -987,6 +1025,14 @@ class MainWindow (Window): return _save + # SEARCH TYPE + def load_search_type (t): + t = int(t) + try: + self.db.type = t + except UnsupportedSearchTypeError: + info("Cannot set search type. '%s' not supported by database '%s'.", t, self.db.__class__.__name__) + # SESSION VERSION def load_session_version (version): @@ -1015,7 +1061,8 @@ class MainWindow (Window): (["width", "height"], lambda w,h: self.window.resize(int(w), int(h)), self.window.get_size), (["vpanedpos", "hpanedpos"], load_paned, save_paned), (["catsel"], load_cat_selection, save_cat_selection, ["app-portage@0"]), - (["pkgsel"], load_pkg_selection, save_pkg_selection, ["portato@0"]) + (["pkgsel"], load_pkg_selection, save_pkg_selection, ["portato@0"]), + (["searchtype"], load_search_type, lambda: self.db.type) #([("merge", "queue"), ("unmerge", "queue"), ("oneshot", "queue")], load_queue, save_queue), ]) @@ -1023,7 +1070,7 @@ class MainWindow (Window): queue = plugin.get_plugin_queue() if queue: for p in queue.get_plugins(): - self.session.add_handler(([(p.name.replace(" ","_"), "plugins")], load_plugin(p), save_plugin(p))) + self.session.add_handler(([(p.name.replace(" ","_").replace(":","_"), "plugins")], load_plugin(p), save_plugin(p))) # the other things def load_cfg ((name, cat)): @@ -1387,8 +1434,8 @@ class MainWindow (Window): """Execute the current queue.""" if len(flags.newUseFlags) > 0: - if not self.session.get_boolean("useflags", "dialogs"): - self.session.set("useflags", dialogs.changed_flags_dialog(_("use flags"))[1], "dialogs") + if not self.session.get_bool("useflags", "dialogs"): + self.session.set("useflags", str(dialogs.changed_flags_dialog(_("use flags"))[1]), "dialogs") try: flags.write_use_flags() except IOError, e: @@ -1399,8 +1446,8 @@ class MainWindow (Window): debug("new masked: %s",flags.new_masked) debug("new unmasked: %s", flags.new_unmasked) debug("new testing: %s", flags.newTesting) - if not self.session.get_boolean("keywords", "dialogs"): - self.session.set("keywords", dialogs.changed_flags_dialog(_("masking keywords"))[1], "dialogs") + if not self.session.get_bool("keywords", "dialogs"): + self.session.set("keywords", str(dialogs.changed_flags_dialog(_("masking keywords"))[1]), "dialogs") try: flags.write_masked() flags.write_testing() @@ -1464,8 +1511,15 @@ class MainWindow (Window): gobject.idle_add(cb_idle_append, updating) finally: self.window.window.set_cursor(None) - - GtkThread(name="Update-Thread", target=__update).start() + + # for some reason, I have to create the thread before displaying the dialog + # else the GUI hangs + t = GtkThread(name="Update-Thread", target=__update) + + if not self.session.get_bool("update_world_warning", "dialogs"): + self.session.set("update_world_warning", str(dialogs.update_world_warning_dialog()[1]), "dialogs") + + t.start() return True @@ -1562,7 +1616,13 @@ class MainWindow (Window): return False # not again ;) - gobject.timeout_add(100, __update) + gobject.timeout_add(200, __update) + + def cb_type_combo_changed (self, *args): + model = self.typeCombo.get_model() + active = self.typeCombo.get_active() + + self.db.type = model[active][0] def cb_delete_search_clicked (self, *args): self.searchEntry.set_text("") diff --git a/portato/gui/windows/pkglist.py b/portato/gui/windows/pkglist.py index 90915cb..df3ef46 100644 --- a/portato/gui/windows/pkglist.py +++ b/portato/gui/windows/pkglist.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/pkglist.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. diff --git a/portato/gui/windows/plugin.py b/portato/gui/windows/plugin.py index 755ad58..89d38f5 100644 --- a/portato/gui/windows/plugin.py +++ b/portato/gui/windows/plugin.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/plugin.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. diff --git a/portato/gui/windows/preference.py b/portato/gui/windows/preference.py index 4bd7551..021788c 100644 --- a/portato/gui/windows/preference.py +++ b/portato/gui/windows/preference.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/preference.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. diff --git a/portato/gui/windows/search.py b/portato/gui/windows/search.py index c531507..f9191d7 100644 --- a/portato/gui/windows/search.py +++ b/portato/gui/windows/search.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/search.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. diff --git a/portato/gui/windows/splash.py b/portato/gui/windows/splash.py index c9e1542..2e9d5a8 100644 --- a/portato/gui/windows/splash.py +++ b/portato/gui/windows/splash.py @@ -3,7 +3,7 @@ # File: portato/gui/windows/splash.py # This file is part of the Portato-Project, a graphical portage-frontend. # -# Copyright (C) 2006-2009 René 'Necoro' Neumann +# Copyright (C) 2006-2010 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. |