summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/persistenttooltip.py
blob: 927c194292b9fc4da725d60fc26329ff2285a151 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2012   Intel Corporation
#
# Authored by Joshua Lock <josh@linux.intel.com>
#
# 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