confirm
[rox-lib.git] / python / rox / __init__.py
blob7da614218fcc33f6954942435a11c91361401348
1 import sys, os
3 try:
4 import gtk2 as g
5 except:
6 sys.stderr.write('The pygtk2 package must be ' +
7 'installed to use this program!')
8 raise
10 TRUE = g.TRUE
11 FALSE = g.FALSE
13 app_dir = os.path.dirname(sys.argv[0])
15 def alert(message):
16 "Display message in an error box."
17 toplevel_ref()
18 box = g.MessageDialog(None, 0, g.MESSAGE_ERROR, g.BUTTONS_OK, message)
19 box.set_position(g.WIN_POS_CENTER)
20 box.set_title('Error')
21 box.run()
22 box.destroy()
23 toplevel_unref()
25 def croak(message):
26 "Display message in an error box, then die."
27 alert(message)
28 sys.exit(1)
30 def info(message):
31 "Display informational message."
32 toplevel_ref()
33 box = g.MessageDialog(None, 0, g.MESSAGE_INFO, g.BUTTONS_OK, message)
34 box.set_position(g.WIN_POS_CENTER)
35 box.set_title('Information')
36 box.run()
37 box.destroy()
38 toplevel_unref()
40 def confirm(message, stock_icon, action = None):
41 "Display a <Cancel>/<Action> dialog. Returns 1 if the user chooses the "
42 "action."
43 toplevel_ref()
44 box = g.MessageDialog(None, 0, g.MESSAGE_QUESTION,
45 g.BUTTONS_CANCEL, message)
46 if action:
47 button = ButtonMixed(stock_icon, action)
48 else:
49 button = g.Button(stock = stock_icon)
50 button.set_flags(g.CAN_DEFAULT)
51 button.show()
52 box.add_action_widget(button, g.RESPONSE_OK)
53 box.set_position(g.WIN_POS_CENTER)
54 box.set_title('Confirm:')
55 box.set_default_response(g.RESPONSE_OK)
56 resp = box.run()
57 box.destroy()
58 toplevel_unref()
59 return resp == g.RESPONSE_OK
61 def report_exception():
62 import traceback
63 type, value, tb = sys.exc_info()
64 traceback.print_exception(type, value, tb)
65 ex = traceback.format_exception_only(type, value)
66 alert(''.join(ex))
68 class ButtonMixed(g.Button):
69 "A button with a stock icon, but any label."
70 def __init__(self, stock, message):
71 g.Button.__init__(self)
73 label = g.Label('')
74 label.set_text_with_mnemonic(message)
75 label.set_mnemonic_widget(self)
77 image = g.image_new_from_stock(stock, g.ICON_SIZE_BUTTON)
78 box = g.HBox(FALSE, 2)
79 align = g.Alignment(0.5, 0.5, 0.0, 0.0)
81 box.pack_start(image, FALSE, FALSE, 0)
82 box.pack_end(label, FALSE, FALSE, 0)
84 self.add(align)
85 align.add(box)
86 align.show_all()
88 _toplevel_windows = 0
89 _in_mainloops = 0
90 def mainloop():
91 global _toplevel_windows, _in_mainloops
93 _in_mainloops += 1
94 try:
95 while _toplevel_windows:
96 g.mainloop()
97 finally:
98 _in_mainloops -= 1
100 def toplevel_ref():
101 global _toplevel_windows
102 _toplevel_windows += 1
104 def toplevel_unref():
105 global _toplevel_windows
106 assert _toplevel_windows > 0
107 _toplevel_windows -= 1
108 if _toplevel_windows == 0 and _in_mainloops:
109 g.mainquit()
111 _host_name = None
112 def our_host_name():
113 from socket import gethostbyaddr, gethostname
114 global _host_name
115 if _host_name:
116 return _host_name
117 try:
118 (host, alias, ips) = gethostbyaddr(gethostname())
119 for name in [host] + alias:
120 if find(name, '.') != -1:
121 _host_name = name
122 return name
123 return name
124 except:
125 sys.stderr.write(
126 "*** ROX-Lib gethostbyaddr(gethostname()) failed!\n")
127 return "localhost"
129 def get_local_path(uri):
130 "Convert uri to a local path and return, if possible. Otherwise,"
131 "return None."
132 if not uri:
133 return None
135 if uri[0] == '/':
136 if uri[1] != '/':
137 return uri # A normal Unix pathname
138 i = uri.find('/', 2)
139 if i == -1:
140 return None # //something
141 if i == 2:
142 return uri[2:] # ///path
143 remote_host = uri[2:i]
144 if remote_host == our_host_name():
145 return uri[i:] # //localhost/path
146 # //otherhost/path
147 elif uri[:5].lower() == 'file:':
148 if uri[5:6] == '/':
149 return get_local_path(uri[5:])
150 elif uri[:2] == './' or uri[:3] == '../':
151 return uri
152 return None
154 app_options = None
155 def setup_app_options(program, leaf = 'Options.xml'):
156 global app_options
157 assert not app_options
158 from options import OptionGroup
159 app_options = OptionGroup(program, leaf)
161 _options_box = None
162 def edit_options(options_file = None):
163 """Edit the app_options using the GUI specified in 'options_file'
164 (default <app_dir>/Options.xml)"""
165 assert app_options
167 global _options_box
168 if _options_box:
169 _options_box.present()
170 return
172 if not options_file:
173 options_file = os.path.join(app_dir, 'Options.xml')
175 import OptionsBox
176 _options_box = OptionsBox.OptionsBox(app_options, options_file)
178 def closed(widget):
179 global _options_box
180 assert _options_box == widget
181 _options_box = None
182 _options_box.connect('destroy', closed)
183 _options_box.open()
185 try:
186 import xml
187 except:
188 alert("You do not have the Python 'xml' module installed, which " \
189 "ROX-Lib2 requires. You need to install python-xmlbase " \
190 "(this is a small package; the full PyXML package is not " \
191 "required).")