When downloading, animate the pointer too.
[zeroinstall/zeroinstall-rsl.git] / zeroinstall / 0launch-gui / dialog.py
blobcb695861fc85f6db2aa0975db959ea8146bedc62
1 import gtk
2 import gtk.glade
3 import os
4 from zeroinstall.support import tasks
6 n_windows = 0
8 last_error = None
10 gladefile = os.path.join(os.path.dirname(__file__), 'zero-install.glade')
12 # Wrapped for glade widget tree that throws a sensible exception if the widget isn't found
13 class Template:
14 def __init__(self, root):
15 self.widgets = gtk.glade.XML(gladefile, root)
16 self.root = root
18 def get_widget(self, name = None):
19 if not name:
20 name = self.root
21 widget = self.widgets.get_widget(name)
22 assert widget, "Widget '%s' not found in glade file '%s'" % (name, gladefile)
23 return widget
25 class Dialog(gtk.Dialog):
26 __shown = False
28 def __init__(self):
29 gtk.Dialog.__init__(self)
30 self.set_has_separator(False)
31 self.set_position(gtk.WIN_POS_CENTER)
33 def add_mixed_button(self, message, stock, response):
34 button = MixedButton(message, stock)
35 button.set_flags(gtk.CAN_DEFAULT)
37 self.add_action_widget(button, response)
38 button.show_all()
39 return button
41 class DialogResponse(tasks.Blocker):
42 response = None
43 def __init__(self, dialog):
44 tasks.Blocker.__init__(self, dialog.get_title())
45 a = None
46 def response(d, resp):
47 self.response = resp
48 d.disconnect(a)
49 self.trigger()
50 a = dialog.connect('response', response)
52 class ButtonClickedBlocker(tasks.Blocker):
53 def __init__(self, button):
54 tasks.Blocker.__init__(self, "Button click")
55 a = None
56 def clicked(b):
57 b.disconnect(a)
58 self.trigger()
59 a = button.connect('clicked', lambda b: self.trigger())
61 def alert(parent, message, type = gtk.MESSAGE_ERROR):
62 if type == gtk.MESSAGE_ERROR:
63 global last_error
64 last_error = message
66 box = gtk.MessageDialog(parent, gtk.DIALOG_DESTROY_WITH_PARENT,
67 type, gtk.BUTTONS_OK,
68 str(message))
69 box.set_position(gtk.WIN_POS_CENTER)
70 def resp(b, r):
71 b.destroy()
72 box.connect('response', resp)
73 box.show()
75 def MixedButton(message, stock, x_align = 0.5, button = None):
76 if button is None:
77 button = gtk.Button()
79 label = gtk.Label('')
80 label.set_text_with_mnemonic(message)
81 label.set_mnemonic_widget(button)
83 image = gtk.image_new_from_stock(stock, gtk.ICON_SIZE_BUTTON)
84 box = gtk.HBox(False, 2)
85 align = gtk.Alignment(x_align, 0.5, 0.0, 0.0)
87 box.pack_start(image, False, False, 0)
88 box.pack_end(label, False, False, 0)
90 button.add(align)
91 align.add(box)
92 return button
94 def frame(page, title, content, expand = False):
95 frame = gtk.Frame()
96 label = gtk.Label()
97 label.set_markup('<b>%s</b>' % title)
98 frame.set_label_widget(label)
99 frame.set_shadow_type(gtk.SHADOW_NONE)
100 if type(content) in (str, unicode):
101 content = gtk.Label(content)
102 content.set_alignment(0, 0.5)
103 content.set_selectable(True)
104 frame.add(content)
105 if hasattr(content, 'set_padding'):
106 content.set_padding(8, 4)
107 else:
108 content.set_border_width(8)
109 page.pack_start(frame, expand, True, 0)
111 def get_busy_pointer(gdk_window):
112 # This is crazy. We build a cursor that looks like the old
113 # Netscape busy-with-a-pointer cursor and set that, then the
114 # X server replaces it with a decent-looking one!!
115 # See http://mail.gnome.org/archives/gtk-list/2007-May/msg00100.html
117 bit_data = "\
118 \x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\
119 \x0c\x00\x00\x00\x1c\x00\x00\x00\x3c\x00\x00\x00\
120 \x7c\x00\x00\x00\xfc\x00\x00\x00\xfc\x01\x00\x00\
121 \xfc\x3b\x00\x00\x7c\x38\x00\x00\x6c\x54\x00\x00\
122 \xc4\xdc\x00\x00\xc0\x44\x00\x00\x80\x39\x00\x00\
123 \x80\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
124 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
125 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
126 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
127 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
128 \x00\x00\x00\x00\x00\x00\x00\x00"
130 try:
131 pix = gtk.gdk.bitmap_create_from_data(None, bit_data, 32, 32)
132 color = gtk.gdk.Color()
133 return gtk.gdk.Cursor(pix, pix, color, color, 2, 2)
134 except:
135 #old bug http://bugzilla.gnome.org/show_bug.cgi?id=103616
136 return gtk.gdk.Cursor(gtk.gdk.WATCH)