# # BitBake Graphical GTK User Interface # # Copyright (C) 2012 Intel Corporation # # Authored by Joshua Lock # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import gobject import gtk try: import gconf except: pass class PersistentTooltip(gtk.Window): """ A tooltip which persists once shown until the user dismisses it with the Esc key or by clicking the close button. # FIXME: the PersistentTooltip should be disabled when the user clicks anywhere off # it. We can't do this with focus-out-event becuase modal ensures we have focus? markup: some Pango text markup to display in the tooltip """ def __init__(self, markup, parent_win=None): gtk.Window.__init__(self, gtk.WINDOW_POPUP) # Inherit the system theme for a tooltip style = gtk.rc_get_style_by_paths(gtk.settings_get_default(), 'gtk-tooltip', 'gtk-tooltip', gobject.TYPE_NONE) self.set_style(style) # The placement of the close button on the tip should reflect how the # window manager of the users system places close buttons. Try to read # the metacity gconf key to determine whether the close button is on the # left or the right. # In the case that we can't determine the users configuration we default # to close buttons being on the right. __button_right = True try: client = gconf.client_get_default() order = client.get_string("/apps/metacity/general/button_layout") if order and order.endswith(":"): __button_right = False except NameError: pass # We need to ensure we're only shown once self.shown = False # We don't want any WM decorations self.set_decorated(False) # We don't want to show in the taskbar or window switcher self.set_skip_pager_hint(True) self.set_skip_taskbar_hint(True) # We must be modal to ensure we grab focus when presented from a gtk.Dialog self.set_modal(True) self.set_border_width(0) self.set_position(gtk.WIN_POS_MOUSE) self.set_opacity(0.95) # Ensure a reasonable minimum size self.set_geometry_hints(self, 100, 50) # Set this window as a transient window for parent(main window) if parent_win: self.set_transient_for(parent_win) self.set_destroy_with_parent(True) # Draw our label and close buttons hbox = gtk.HBox(False, 0) hbox.show() self.add(hbox) img = gtk.Image() img.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_BUTTON) self.button = gtk.Button() self.button.set_image(img) self.button.connect("clicked", self._dismiss_cb) self.button.set_flags(gtk.CAN_DEFAULT) self.button.grab_focus() self.button.show() vbox = gtk.VBox(False, 0) vbox.show() vbox.pack_start(self.button, False, False, 0) if __button_right: hbox.pack_end(vbox, True, True, 0) else: hbox.pack_start(vbox, True, True, 0) self.set_default(self.button) bin = gtk.HBox(True, 6) bin.set_border_width(6) bin.show() self.label = gtk.Label() self.label.set_line_wrap(True) # We want to match the colours of the normal tooltips, as dictated by # the users gtk+-2.0 theme, wherever possible - on some systems this # requires explicitly setting a fg_color for the label which matches the # tooltip_fg_color settings = gtk.settings_get_default() colours = settings.get_property('gtk-color-scheme').split('\n') # remove any empty lines, there's likely to be a trailing one after # calling split on a dictionary-like string colours = filter(None, colours) for col in colours: item, val = col.split(': ') if item == 'tooltip_fg_color': style = self.label.get_style() style.fg[gtk.STATE_NORMAL] = gtk.gdk.color_parse(val) self.label.set_style(style) break # we only care for the tooltip_fg_color self.label.set_markup(markup) self.label.show() bin.add(self.label) hbox.pack_end(bin, True, True, 6) # add the original URL display for user reference if 'a href' in markup: hbox.set_tooltip_text(self.get_markup_url(markup)) hbox.show() self.connect("key-press-event", self._catch_esc_cb) """ Callback when the PersistentTooltip's close button is clicked. Hides the PersistentTooltip. """ def _dismiss_cb(self, button): self.hide() return True """ Callback when the Esc key is detected. Hides the PersistentTooltip. """ def _catch_esc_cb(self, widget, event): keyname = gtk.gdk.keyval_name(event.keyval) if keyname == "Escape": self.hide() return True """ Called to present the PersistentTooltip. Overrides the superclasses show() method to include state tracking. """ def show(self): if not self.shown: self.shown = True gtk.Window.show(self) """ Called to hide the PersistentTooltip. Overrides the superclasses hide() method to include state tracking. """ def hide(self): self.shown = False gtk.Window.hide(self) """ Called to get the hyperlink URL from markup text. """ def get_markup_url(self, markup): url = "http:" if markup and type(markup) == str: s = markup if 'http:' in s: import re url = re.search('(http:[^,\\ "]+)', s).group(0) return url