diff options
Diffstat (limited to '')
-rw-r--r-- | portato/gui/windows/basic.py | 72 | ||||
-rw-r--r-- | portato/gui/windows/main.py | 120 | ||||
-rw-r--r-- | portato/gui/windows/preference.py | 76 |
3 files changed, 163 insertions, 105 deletions
diff --git a/portato/gui/windows/basic.py b/portato/gui/windows/basic.py index 1117e5e..b3f210c 100644 --- a/portato/gui/windows/basic.py +++ b/portato/gui/windows/basic.py @@ -14,7 +14,6 @@ from __future__ import absolute_import # gtk stuff import gtk -import gtk.glade import gobject from functools import wraps @@ -23,11 +22,18 @@ import os.path from ...constants import TEMPLATE_DIR, APP, LOCALE_DIR from ...helper import error -gtk.glade.bindtextdomain (APP, LOCALE_DIR) -gtk.glade.textdomain (APP) +# for the GtkBuilder to translate correctly :) +import ctypes +try: + getlib = ctypes.cdll.LoadLibrary("libgettextlib.so") +except OSError: + error("'libgettextlib.so' cannot be loaded. Might be, that there are no translations available in the GUI.") +else: + getlib.textdomain(APP) + getlib.bindtextdomain(APP, LOCALE_DIR) class WrappedTree (object): - __slots__ = ("klass", "tree", "get_widget") + __slots__ = ("klass", "tree", "get_widget", "get_ui") def __init__ (self, klass, tree): self.tree = tree self.klass = klass @@ -39,25 +45,52 @@ class WrappedTree (object): return getattr(self.tree, name) def get_widget(self, name): - w = self.tree.get_widget(name) + w = self.tree.get_object(name) if w is None: error("Widget '%s' could not be found in class '%s'.", name, self.klass) return w -class Window (object): - def __init__ (self): + def get_ui (self, name, ui = "uimanager"): + uiw = self.get_widget(ui) + if uiw is None: + return None - if not hasattr(self, "__tree__"): - self.__tree__ = self.__class__.__name__ + if not name.startswith("ui/"): + name = "ui/%s" % name - if not hasattr(self, "__window__"): - self.__window__ = self.__class__.__name__ + w = uiw.get_widget(name) + if w is None: + error("UIItem '%s' of UIManager '%s' could not be found in class '%s'.", name, ui, self.klass) + return w + +class UIBuilder (object): + def __init__ (self, connector = None): if not hasattr(self, "__file__"): self.__file__ = self.__class__.__name__ - self.tree = self.get_tree(self.__tree__) - self.tree.signal_autoconnect(self) + self._builder = gtk.Builder() + self._builder.add_from_file(os.path.join(TEMPLATE_DIR, self.__file__+".ui")) + self._builder.set_translation_domain(APP) + + if connector is None: connector = self + + unconnected = self._builder.connect_signals(connector) + + if unconnected is not None: + for uc in set(unconnected): + error("Signal '%s' not connected in class '%s'.", uc, self.__class__.__name__) + + self.tree = WrappedTree(self.__class__.__name__, self._builder) + +class Window (UIBuilder): + def __init__ (self): + + UIBuilder.__init__(self) + + if not hasattr(self, "__window__"): + self.__window__ = self.__class__.__name__ + self.window = self.tree.get_widget(self.__window__) @staticmethod @@ -82,9 +115,6 @@ class Window (object): return wrapper - def get_tree (self, name): - return WrappedTree(self.__class__.__name__, gtk.glade.XML(os.path.join(TEMPLATE_DIR, self.__file__+".glade"), name)) - class AbstractDialog (Window): """A class all our dialogs get derived from. It sets useful default vars and automatically handles the ESC-Button.""" @@ -114,13 +144,3 @@ class AbstractDialog (Window): def close (self, *args): self.window.destroy() - -class Popup (object): - - def __init__ (self, name, parent, file = "popups"): - self.tree = WrappedTree(self.__class__.__name__, gtk.glade.XML(os.path.join(TEMPLATE_DIR, file+".glade"), root = name)) - self.tree.signal_autoconnect(parent) - self._popup = self.tree.get_widget(name) - - def popup (self, *args): - self._popup.popup(*args) diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py index 443fa76..04a9995 100644 --- a/portato/gui/windows/main.py +++ b/portato/gui/windows/main.py @@ -43,7 +43,7 @@ from ..dialogs import (blocked_dialog, changed_flags_dialog, io_ex_dialog, from ..exceptions import PreReqError # even more GUI stuff -from .basic import Window, Popup +from .basic import Window from .about import AboutWindow from .plugin import PluginWindow from .preference import PreferenceWindow @@ -62,7 +62,6 @@ class PackageTable: self.main = main self.tree = main.tree self.window = main.window - self.tree.signal_autoconnect(self) # all the package data is in this one VB self.vb = self.tree.get_widget("packageVB") @@ -77,8 +76,7 @@ class PackageTable: self.maskedLabel = self.tree.get_widget("maskedLabel") # labels - generalVB = self.tree.get_widget("generalVB") - generalVB.modify_bg(gtk.STATE_NORMAL, get_color(self.main.cfg, "packagetable")) + self.main.set_color(get_color(self.main.cfg, "packagetable")) self.nameLabel = self.tree.get_widget("nameLabel") self.descLabel = self.tree.get_widget("descLabel") @@ -473,7 +471,7 @@ class MainWindow (Window): # package db splash(_("Creating Database")) - self.db = Database() + self.db = Database(self.cfg.get("type", section = "DATABASE")) # set plugins and plugin-menu splash(_("Loading Plugins")) @@ -481,13 +479,24 @@ class MainWindow (Window): plugin.load_plugins() menus = [p.menus for p in plugin.get_plugin_queue().get_plugins()] if menus: - self.tree.get_widget("pluginMenuItem").set_no_show_all(False) - pluginMenu = self.tree.get_widget("pluginMenu") + uim = self.tree.get_widget("uimanager") + ag = self.tree.get_widget("pluginActionGroup") + ctr = 0 for m in itt.chain(*menus): - item = gtk.MenuItem(m.label) - item.connect("activate", m.call) - pluginMenu.append(item) + + # create action + aname = "plugin%d" % ctr + a = gtk.Action(aname, m.label, None, None) + a.connect("activate", m.call) + ag.add_action(a) + + # add to UI + mid = uim.new_merge_id() + uim.add_ui(mid, "ui/menubar/pluginMenu", aname, aname, gtk.UI_MANAGER_MENUITEM, False) + + ctr += 1 + splash(_("Building frontend")) # set paned position @@ -554,18 +563,11 @@ class MainWindow (Window): self.packageTable = PackageTable(self) # popups - self.consolePopup = Popup("consolePopup", self, self.__file__) - self.trayPopup = Popup("systrayPopup", self) + self.consolePopup = self.tree.get_ui("consolePopup") + self.trayPopup = self.tree.get_ui("systrayPopup") # pause menu items self.emergePaused = False - self.pauseItems = {} - self.pauseItems["tray"] = self.trayPopup.tree.get_widget("pauseItemTray") - self.pauseItems["popup"] = self.consolePopup.tree.get_widget("pauseItemPopup") - self.pauseItems["menu"] = self.tree.get_widget("pauseItemMenu") - - for k,v in self.pauseItems.iteritems(): - self.pauseItems[k] = (v, v.connect_after("activate", self.cb_pause_emerge(k))) # systray if self.cfg.get_boolean("showSystray", "GUI"): @@ -1256,6 +1258,17 @@ class MainWindow (Window): self.catList.get_selection().select_path(pos) self.catList.scroll_to_cell(pos) + def set_color (self, color): + """ + Sets the color of the general VB (i.e. the thing that displays the package details) + + @param color: color to set it to + @type color: gtk.gdk.Color + """ + + generalVB = self.tree.get_widget("generalVB") + generalVB.modify_bg(gtk.STATE_NORMAL, color) + def set_uri_hook (self, browser): """ Sets the browser command which is called when a URL is going to be opened. @@ -1358,7 +1371,7 @@ class MainWindow (Window): try: self.fill_version_list(self.selCP) except VersionsNotFoundException, e: - warning(_("No versions of package '%s' found!.") % self.selCP) + warning(_("No versions of package '%s' found!") % self.selCP) no_versions_dialog(self.selCP) self.db.disable(self.selCP) self.selCP = oldcp @@ -1675,7 +1688,7 @@ class MainWindow (Window): """ User wants to open preferences. """ - PreferenceWindow(self.window, self.cfg, self.console.set_font_from_string, self.set_uri_hook, self.set_notebook_tabpos, self.fill_cat_store) + PreferenceWindow(self.window, self.cfg, self.console.set_font_from_string, self.set_uri_hook, self.set_notebook_tabpos, self.fill_cat_store, self.set_color) return True def cb_about_clicked (self, *args): @@ -1772,50 +1785,13 @@ class MainWindow (Window): self.queue.append(package, update = True, oneshot = set, forceUpdate = True) - def cb_pause_emerge (self, curr): - """ - This method returns a callback for a "pause emerge" toggle button. - It is needed as there are different toggle buttons of this type and if one is clicked, - the others should be marked too. - - @param curr: The button to return the callback for. - @type curr: gtk.ToggleButton - """ - def pause (cb): - """ - The actual callback. - - Mark all other buttons too. - - @param cb: The button which got toggled. - @type cb: gtk.ToggleButton - """ - - # pause or continue - self.emergePaused = cb.get_active() - if not self.emergePaused: - self.queue.continue_emerge() - #self.tray.set_from_file(APP_ICON) - else: - self.queue.stop_emerge() - #self.tray.set_from_file(os.path.join(ICON_DIR, "pausing.png")) - - # block the handlers of the other buttons - # so that calling "set_active" does not call this callback recursivly - for v in self.pauseItems.itervalues(): - v[0].handler_block(v[1]) - - # mark the others - for k, v in self.pauseItems.iteritems(): - if k != curr: - v[0].set_active(self.emergePaused) - - # unblock - for v in self.pauseItems.itervalues(): - v[0].handler_unblock(v[1]) - - return False - return pause + def cb_pause_emerge (self, action): + # pause or continue + self.emergePaused = action.get_active() + if not self.emergePaused: + self.queue.continue_emerge() + else: + self.queue.stop_emerge() def cb_kill_clicked (self, *args): """ @@ -1823,7 +1799,7 @@ class MainWindow (Window): """ self.queue.kill_emerge() if self.emergePaused: # unmark the "pause emerge" buttons - self.pauseItems["menu"][0].set_active(False) # calling one button is enough (see: cb_pause_emerge) + self.tree.get_widget("generalActionGroup").get_action("pauseAction").set_active(False) def cb_copy_clicked (self, *args): """ @@ -1879,6 +1855,18 @@ class MainWindow (Window): else: self.window.iconify() + def cb_testing_toggled (self, *args): + return self.packageTable.cb_testing_toggled(*args) + def cb_masked_toggled (self, *args): + return self.packageTable.cb_masked_toggled(*args) + def cb_button_pressed (self, *args): + return self.packageTable.cb_button_pressed(*args) + def cb_package_revert_clicked (self, *args): + return self.packageTable.cb_package_revert_clicked(*args) + def cb_package_unmerge_clicked (self, *args): + return self.packageTable.cb_package_unmerge_clicked(*args) + def cb_package_emerge_clicked (self, *args): + return self.packageTable.cb_package_emerge_clicked(*args) def cb_use_flag_toggled (self, *args): return self.packageTable.cb_use_flag_toggled(*args) diff --git a/portato/gui/windows/preference.py b/portato/gui/windows/preference.py index df18e88..5b88b22 100644 --- a/portato/gui/windows/preference.py +++ b/portato/gui/windows/preference.py @@ -20,6 +20,7 @@ from .basic import AbstractDialog from ..dialogs import io_ex_dialog from ..utils import get_color from ...helper import debug +from ... import db class PreferenceWindow (AbstractDialog): """Window displaying some preferences.""" @@ -60,7 +61,7 @@ class PreferenceWindow (AbstractDialog): 4 : gtk.POS_RIGHT } - def __init__ (self, parent, cfg, console_fn, linkbtn_fn, tabpos_fn, catmodel_fn): + def __init__ (self, parent, cfg, console_fn, linkbtn_fn, tabpos_fn, catmodel_fn, labelcolor_fn): """Constructor. @param parent: parent window @@ -74,7 +75,9 @@ class PreferenceWindow (AbstractDialog): @param tabpos_fn: function to call to set the tabposition of the notebooks @type tabpos_fn: function(gtk.ComboBox,int) @param catmodel_fn: function to call to set the model of the cat list (collapsed/not collapsed) - @type catmodel_fn: function()""" + @type catmodel_fn: function() + @param labelcolor_fn: function to call to set the color of the label + @type labelcolor_fn: function(gtk.gdk.Color)""" AbstractDialog.__init__(self, parent) @@ -101,6 +104,7 @@ class PreferenceWindow (AbstractDialog): self.linkbtn_fn = linkbtn_fn self.tabpos_fn = tabpos_fn self.catmodel_fn = catmodel_fn + self.labelcolor_fn = labelcolor_fn # set the bg-color of the hint hintEB = self.tree.get_widget("hintEB") @@ -109,20 +113,16 @@ class PreferenceWindow (AbstractDialog): # the checkboxes for box, val in self.checkboxes.iteritems(): if isinstance(val, tuple): - self.tree.get_widget(box).\ - set_active(self.cfg.get_boolean(val[0], section = val[1])) + self.tree.get_widget(box).set_active(self.cfg.get_boolean(val[0], section = val[1])) else: - self.tree.get_widget(box).\ - set_active(self.cfg.get_boolean(val)) + self.tree.get_widget(box).set_active(self.cfg.get_boolean(val)) # the edits for edit, val in self.edits.iteritems(): if isinstance(val,tuple): - self.tree.get_widget(edit).\ - set_text(self.cfg.get(val[0], section = val[1])) + self.tree.get_widget(edit).set_text(self.cfg.get(val[0], section = val[1])) else: - self.tree.get_widget(edit).\ - set_text(self.cfg.get(val)) + self.tree.get_widget(edit).set_text(self.cfg.get(val)) # the set list self.setList = self.tree.get_widget("setList") @@ -138,19 +138,54 @@ class PreferenceWindow (AbstractDialog): self.titleLengthSpinBtn = self.tree.get_widget("titleLengthSpinBtn") self.titleLengthSpinBtn.set_value(int(self.cfg.get("titlelength", section = "GUI"))) + # the color buttons + self.pkgTableColorBtn = self.tree.get_widget("pkgTableColorBtn") + self.pkgTableColorBtn.set_color(get_color(self.cfg, "packagetable")) + + self.prefColorBtn = self.tree.get_widget("prefColorBtn") + self.prefColorBtn.set_color(get_color(self.cfg, "prefhint")) + # the comboboxes self.systemTabCombo = self.tree.get_widget("systemTabCombo") self.pkgTabCombo = self.tree.get_widget("packageTabCombo") for c in (self.systemTabCombo, self.pkgTabCombo): - m = c.get_model() - m.clear() + model = gtk.ListStore(str) for i in (_("Top"), _("Bottom"), _("Left"), _("Right")): - m.append((i,)) + model.append((i,)) + + c.set_model(model) + + cell = gtk.CellRendererText() + c.pack_start(cell) + c.set_attributes(cell, text = 0) self.systemTabCombo.set_active(int(self.cfg.get("systemTabPos", section = "GUI"))-1) self.pkgTabCombo.set_active(int(self.cfg.get("packageTabPos", section = "GUI"))-1) + # the database combo + dbtype = self.cfg.get("type", section = "DATABASE") + self.databaseCombo = self.tree.get_widget("databaseCombo") + model = gtk.ListStore(str, str, str) + + ctr = 0 + active = 0 + for k, (name, desc) in db.types.iteritems(): + if k == dbtype: + active = ctr + + model.append([name, desc, k]) + ctr += 1 + + self.databaseCombo.set_model(model) + self.databaseCombo.set_active(active) + + cell = gtk.CellRendererText() + self.databaseCombo.pack_start(cell) + self.databaseCombo.set_attributes(cell, text = 0) + + self.cb_db_combo_changed() + self.window.show_all() def _save(self): @@ -189,6 +224,14 @@ class PreferenceWindow (AbstractDialog): self.catmodel_fn() + # colors + c = self.pkgTableColorBtn.get_color() + self.cfg.set("packagetable", str(c)[1:], section = "COLORS") + self.labelcolor_fn(c) + + c = self.prefColorBtn.get_color() + self.cfg.set("prefhint", str(c)[1:], section = "COLORS") + def fill_setlist (self): store = gtk.ListStore(bool, str, str, str) @@ -212,6 +255,13 @@ class PreferenceWindow (AbstractDialog): self.setList.set_model(store) + def cb_db_combo_changed (self, *args): + model = self.databaseCombo.get_model() + active = self.databaseCombo.get_active() + + descr = self.tree.get_widget("dbDescriptionLabel") + descr.set_markup("<i>%s</i>" % model[active][1]) + def cb_ok_clicked(self, button): """Saves, writes to config-file and closes the window.""" self._save() |