blob: 1d3edb3aacde44e308a90def2938c2898bd6d5fc [file] [log] [blame]
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +00001"""Easy to use dialogs.
2
3Message(msg) -- display a message and an OK button.
4AskString(prompt, default) -- ask for a string, display OK and Cancel buttons.
Just van Rossumcdcc0f01999-02-15 00:04:05 +00005AskPassword(prompt, default) -- like AskString(), but shows text as bullets.
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +00006AskYesNoCancel(question, default) -- display a question and Yes, No and Cancel buttons.
Jack Jansen3032fe62003-01-21 14:38:32 +00007GetArgv(optionlist, commandlist) -- fill a sys.argv-like list using a dialog
Raymond Hettingerff41c482003-04-06 09:01:11 +00008AskFileForOpen(...) -- Ask the user for an existing file
Jack Jansen3032fe62003-01-21 14:38:32 +00009AskFileForSave(...) -- Ask the user for an output file
10AskFolder(...) -- Ask the user to select a folder
Jack Jansen3a87f5b1995-11-14 10:13:49 +000011bar = Progress(label, maxvalue) -- Display a progress bar
12bar.set(value) -- Set value
Jack Jansen1d63d8c1997-05-12 15:44:14 +000013bar.inc( *amount ) -- increment value by amount (default=1)
Raymond Hettingerff41c482003-04-06 09:01:11 +000014bar.label( *newlabel ) -- get or set text label.
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000015
16More documentation in each function.
Jack Jansencc386881999-12-12 22:57:51 +000017This module uses DLOG resources 260 and on.
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000018Based upon STDWIN dialogs with the same names and functions.
19"""
20
Benjamin Peterson23681932008-05-12 21:42:13 +000021from warnings import warnpy3k
Benjamin Petersona6864e02008-07-14 17:42:17 +000022warnpy3k("In 3.x, the EasyDialogs module is removed.", stacklevel=2)
Benjamin Peterson23681932008-05-12 21:42:13 +000023
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000024from Carbon.Dlg import GetNewDialog, SetDialogItemText, GetDialogItemText, ModalDialog
25from Carbon import Qd
26from Carbon import QuickDraw
27from Carbon import Dialogs
28from Carbon import Windows
29from Carbon import Dlg,Win,Evt,Events # sdm7g
30from Carbon import Ctl
31from Carbon import Controls
32from Carbon import Menu
Jack Jansen7451e3b2003-03-03 12:25:02 +000033from Carbon import AE
Jack Jansenf0d12da2003-01-17 16:04:39 +000034import Nav
Jack Jansena5a49811998-07-01 15:47:44 +000035import MacOS
36import string
Raymond Hettingerff41c482003-04-06 09:01:11 +000037from Carbon.ControlAccessor import * # Also import Controls constants
Jack Jansenf0d12da2003-01-17 16:04:39 +000038import Carbon.File
Jack Jansendde800e2002-11-07 23:07:05 +000039import macresource
Jack Jansene58962a2003-01-17 23:13:03 +000040import os
Jack Jansen2b3ce3b2003-01-26 20:22:41 +000041import sys
Jack Jansendde800e2002-11-07 23:07:05 +000042
Jack Jansen3032fe62003-01-21 14:38:32 +000043__all__ = ['Message', 'AskString', 'AskPassword', 'AskYesNoCancel',
Just van Rossum35b50e22003-06-21 14:41:32 +000044 'GetArgv', 'AskFileForOpen', 'AskFileForSave', 'AskFolder',
45 'ProgressBar']
Raymond Hettingerff41c482003-04-06 09:01:11 +000046
Jack Jansendde800e2002-11-07 23:07:05 +000047_initialized = 0
48
49def _initialize():
Just van Rossum35b50e22003-06-21 14:41:32 +000050 global _initialized
51 if _initialized: return
52 macresource.need("DLOG", 260, "dialogs.rsrc", __name__)
Raymond Hettingerff41c482003-04-06 09:01:11 +000053
Jack Jansen7451e3b2003-03-03 12:25:02 +000054def _interact():
Just van Rossum35b50e22003-06-21 14:41:32 +000055 """Make sure the application is in the foreground"""
56 AE.AEInteractWithUser(50000000)
Jack Jansena5a49811998-07-01 15:47:44 +000057
58def cr2lf(text):
Just van Rossum35b50e22003-06-21 14:41:32 +000059 if '\r' in text:
60 text = string.join(string.split(text, '\r'), '\n')
61 return text
Jack Jansena5a49811998-07-01 15:47:44 +000062
63def lf2cr(text):
Just van Rossum35b50e22003-06-21 14:41:32 +000064 if '\n' in text:
65 text = string.join(string.split(text, '\n'), '\r')
66 if len(text) > 253:
67 text = text[:253] + '\311'
68 return text
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000069
Jack Jansencc386881999-12-12 22:57:51 +000070def Message(msg, id=260, ok=None):
Just van Rossum35b50e22003-06-21 14:41:32 +000071 """Display a MESSAGE string.
Raymond Hettingerff41c482003-04-06 09:01:11 +000072
Just van Rossum35b50e22003-06-21 14:41:32 +000073 Return when the user clicks the OK button or presses Return.
Raymond Hettingerff41c482003-04-06 09:01:11 +000074
Just van Rossum35b50e22003-06-21 14:41:32 +000075 The MESSAGE string can be at most 255 characters long.
76 """
77 _initialize()
78 _interact()
79 d = GetNewDialog(id, -1)
80 if not d:
81 print "EasyDialogs: Can't get DLOG resource with id =", id, " (missing resource file?)"
82 return
83 h = d.GetDialogItemAsControl(2)
84 SetDialogItemText(h, lf2cr(msg))
Benjamin Peterson5b63acd2008-03-29 15:24:25 +000085 if ok is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +000086 h = d.GetDialogItemAsControl(1)
87 h.SetControlTitle(ok)
88 d.SetDialogDefaultItem(1)
89 d.AutoSizeDialog()
90 d.GetDialogWindow().ShowWindow()
91 while 1:
92 n = ModalDialog(None)
93 if n == 1:
94 return
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000095
96
Jack Jansencc386881999-12-12 22:57:51 +000097def AskString(prompt, default = "", id=261, ok=None, cancel=None):
Just van Rossum35b50e22003-06-21 14:41:32 +000098 """Display a PROMPT string and a text entry field with a DEFAULT string.
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +000099
Just van Rossum35b50e22003-06-21 14:41:32 +0000100 Return the contents of the text entry field when the user clicks the
101 OK button or presses Return.
102 Return None when the user clicks the Cancel button.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000103
Just van Rossum35b50e22003-06-21 14:41:32 +0000104 If omitted, DEFAULT is empty.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000105
Just van Rossum35b50e22003-06-21 14:41:32 +0000106 The PROMPT and DEFAULT strings, as well as the return value,
107 can be at most 255 characters long.
108 """
Raymond Hettingerff41c482003-04-06 09:01:11 +0000109
Just van Rossum35b50e22003-06-21 14:41:32 +0000110 _initialize()
111 _interact()
112 d = GetNewDialog(id, -1)
113 if not d:
114 print "EasyDialogs: Can't get DLOG resource with id =", id, " (missing resource file?)"
115 return
116 h = d.GetDialogItemAsControl(3)
117 SetDialogItemText(h, lf2cr(prompt))
118 h = d.GetDialogItemAsControl(4)
119 SetDialogItemText(h, lf2cr(default))
120 d.SelectDialogItemText(4, 0, 999)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000121# d.SetDialogItem(4, 0, 255)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000122 if ok is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000123 h = d.GetDialogItemAsControl(1)
124 h.SetControlTitle(ok)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000125 if cancel is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000126 h = d.GetDialogItemAsControl(2)
127 h.SetControlTitle(cancel)
128 d.SetDialogDefaultItem(1)
129 d.SetDialogCancelItem(2)
130 d.AutoSizeDialog()
131 d.GetDialogWindow().ShowWindow()
132 while 1:
133 n = ModalDialog(None)
134 if n == 1:
135 h = d.GetDialogItemAsControl(4)
136 return cr2lf(GetDialogItemText(h))
137 if n == 2: return None
Raymond Hettingerff41c482003-04-06 09:01:11 +0000138
139def AskPassword(prompt, default='', id=264, ok=None, cancel=None):
Just van Rossum35b50e22003-06-21 14:41:32 +0000140 """Display a PROMPT string and a text entry field with a DEFAULT string.
141 The string is displayed as bullets only.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000142
Just van Rossum35b50e22003-06-21 14:41:32 +0000143 Return the contents of the text entry field when the user clicks the
144 OK button or presses Return.
145 Return None when the user clicks the Cancel button.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000146
Just van Rossum35b50e22003-06-21 14:41:32 +0000147 If omitted, DEFAULT is empty.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000148
Just van Rossum35b50e22003-06-21 14:41:32 +0000149 The PROMPT and DEFAULT strings, as well as the return value,
150 can be at most 255 characters long.
151 """
152 _initialize()
153 _interact()
154 d = GetNewDialog(id, -1)
155 if not d:
156 print "EasyDialogs: Can't get DLOG resource with id =", id, " (missing resource file?)"
157 return
158 h = d.GetDialogItemAsControl(3)
159 SetDialogItemText(h, lf2cr(prompt))
160 pwd = d.GetDialogItemAsControl(4)
161 bullets = '\245'*len(default)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000162## SetControlData(pwd, kControlEditTextPart, kControlEditTextTextTag, bullets)
Just van Rossum35b50e22003-06-21 14:41:32 +0000163 SetControlData(pwd, kControlEditTextPart, kControlEditTextPasswordTag, default)
164 d.SelectDialogItemText(4, 0, 999)
165 Ctl.SetKeyboardFocus(d.GetDialogWindow(), pwd, kControlEditTextPart)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000166 if ok is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000167 h = d.GetDialogItemAsControl(1)
168 h.SetControlTitle(ok)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000169 if cancel is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000170 h = d.GetDialogItemAsControl(2)
171 h.SetControlTitle(cancel)
172 d.SetDialogDefaultItem(Dialogs.ok)
173 d.SetDialogCancelItem(Dialogs.cancel)
174 d.AutoSizeDialog()
175 d.GetDialogWindow().ShowWindow()
176 while 1:
177 n = ModalDialog(None)
178 if n == 1:
179 h = d.GetDialogItemAsControl(4)
180 return cr2lf(GetControlData(pwd, kControlEditTextPart, kControlEditTextPasswordTag))
181 if n == 2: return None
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000182
Jack Jansencc386881999-12-12 22:57:51 +0000183def AskYesNoCancel(question, default = 0, yes=None, no=None, cancel=None, id=262):
Just van Rossum35b50e22003-06-21 14:41:32 +0000184 """Display a QUESTION string which can be answered with Yes or No.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000185
Just van Rossum35b50e22003-06-21 14:41:32 +0000186 Return 1 when the user clicks the Yes button.
187 Return 0 when the user clicks the No button.
188 Return -1 when the user clicks the Cancel button.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000189
Just van Rossum35b50e22003-06-21 14:41:32 +0000190 When the user presses Return, the DEFAULT value is returned.
191 If omitted, this is 0 (No).
Raymond Hettingerff41c482003-04-06 09:01:11 +0000192
Just van Rossum35b50e22003-06-21 14:41:32 +0000193 The QUESTION string can be at most 255 characters.
194 """
Raymond Hettingerff41c482003-04-06 09:01:11 +0000195
Just van Rossum35b50e22003-06-21 14:41:32 +0000196 _initialize()
197 _interact()
198 d = GetNewDialog(id, -1)
199 if not d:
200 print "EasyDialogs: Can't get DLOG resource with id =", id, " (missing resource file?)"
201 return
202 # Button assignments:
203 # 1 = default (invisible)
204 # 2 = Yes
205 # 3 = No
206 # 4 = Cancel
207 # The question string is item 5
208 h = d.GetDialogItemAsControl(5)
209 SetDialogItemText(h, lf2cr(question))
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000210 if yes is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000211 if yes == '':
212 d.HideDialogItem(2)
213 else:
214 h = d.GetDialogItemAsControl(2)
215 h.SetControlTitle(yes)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000216 if no is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000217 if no == '':
218 d.HideDialogItem(3)
219 else:
220 h = d.GetDialogItemAsControl(3)
221 h.SetControlTitle(no)
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000222 if cancel is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000223 if cancel == '':
224 d.HideDialogItem(4)
225 else:
226 h = d.GetDialogItemAsControl(4)
227 h.SetControlTitle(cancel)
228 d.SetDialogCancelItem(4)
229 if default == 1:
230 d.SetDialogDefaultItem(2)
231 elif default == 0:
232 d.SetDialogDefaultItem(3)
233 elif default == -1:
234 d.SetDialogDefaultItem(4)
235 d.AutoSizeDialog()
236 d.GetDialogWindow().ShowWindow()
237 while 1:
238 n = ModalDialog(None)
239 if n == 1: return default
240 if n == 2: return 1
241 if n == 3: return 0
242 if n == 4: return -1
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000243
244
Raymond Hettingerff41c482003-04-06 09:01:11 +0000245
Ned Deily8e60f6e2013-05-30 00:14:29 -0700246# The deprecated Carbon QuickDraw APIs are no longer available as of
247# OS X 10.8. Raise an ImportError here in that case so that callers
248# of EasyDialogs, like BuildApplet, will do the right thing.
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000249
Ned Deily8e60f6e2013-05-30 00:14:29 -0700250try:
251 screenbounds = Qd.GetQDGlobalsScreenBits().bounds
252except AttributeError:
253 raise ImportError("QuickDraw APIs not available")
254
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000255screenbounds = screenbounds[0]+4, screenbounds[1]+4, \
Just van Rossum35b50e22003-06-21 14:41:32 +0000256 screenbounds[2]-4, screenbounds[3]-4
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000257
Raymond Hettingerff41c482003-04-06 09:01:11 +0000258kControlProgressBarIndeterminateTag = 'inde' # from Controls.py
Jack Jansen911e87d2001-08-27 15:24:07 +0000259
260
Jack Jansen3a87f5b1995-11-14 10:13:49 +0000261class ProgressBar:
Just van Rossum35b50e22003-06-21 14:41:32 +0000262 def __init__(self, title="Working...", maxval=0, label="", id=263):
263 self.w = None
264 self.d = None
265 _initialize()
266 self.d = GetNewDialog(id, -1)
267 self.w = self.d.GetDialogWindow()
268 self.label(label)
269 self.title(title)
270 self.set(0, maxval)
271 self.d.AutoSizeDialog()
272 self.w.ShowWindow()
273 self.d.DrawDialog()
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000274
Martin Blais215f13d2006-06-06 12:46:55 +0000275 def __del__(self):
Just van Rossum35b50e22003-06-21 14:41:32 +0000276 if self.w:
277 self.w.BringToFront()
278 self.w.HideWindow()
279 del self.w
280 del self.d
Jack Jansen911e87d2001-08-27 15:24:07 +0000281
Just van Rossum35b50e22003-06-21 14:41:32 +0000282 def title(self, newstr=""):
283 """title(text) - Set title of progress window"""
284 self.w.BringToFront()
285 self.w.SetWTitle(newstr)
Jack Jansen911e87d2001-08-27 15:24:07 +0000286
Martin Blais215f13d2006-06-06 12:46:55 +0000287 def label(self, *newstr):
Just van Rossum35b50e22003-06-21 14:41:32 +0000288 """label(text) - Set text in progress box"""
289 self.w.BringToFront()
290 if newstr:
291 self._label = lf2cr(newstr[0])
292 text_h = self.d.GetDialogItemAsControl(2)
293 SetDialogItemText(text_h, self._label)
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000294
Just van Rossum35b50e22003-06-21 14:41:32 +0000295 def _update(self, value):
296 maxval = self.maxval
297 if maxval == 0: # an indeterminate bar
298 Ctl.IdleControls(self.w) # spin the barber pole
299 else: # a determinate bar
300 if maxval > 32767:
301 value = int(value/(maxval/32767.0))
302 maxval = 32767
303 maxval = int(maxval)
304 value = int(value)
305 progbar = self.d.GetDialogItemAsControl(3)
306 progbar.SetControlMaximum(maxval)
307 progbar.SetControlValue(value) # set the bar length
Raymond Hettingerff41c482003-04-06 09:01:11 +0000308
Just van Rossum35b50e22003-06-21 14:41:32 +0000309 # Test for cancel button
310 ready, ev = Evt.WaitNextEvent( Events.mDownMask, 1 )
311 if ready :
312 what,msg,when,where,mod = ev
313 part = Win.FindWindow(where)[0]
314 if Dlg.IsDialogEvent(ev):
315 ds = Dlg.DialogSelect(ev)
316 if ds[0] and ds[1] == self.d and ds[-1] == 1:
317 self.w.HideWindow()
318 self.w = None
319 self.d = None
320 raise KeyboardInterrupt, ev
321 else:
322 if part == 4: # inDrag
323 self.w.DragWindow(where, screenbounds)
324 else:
325 MacOS.HandleEvent(ev)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000326
327
Just van Rossum35b50e22003-06-21 14:41:32 +0000328 def set(self, value, max=None):
329 """set(value) - Set progress bar position"""
Benjamin Peterson5b63acd2008-03-29 15:24:25 +0000330 if max is not None:
Just van Rossum35b50e22003-06-21 14:41:32 +0000331 self.maxval = max
332 bar = self.d.GetDialogItemAsControl(3)
333 if max <= 0: # indeterminate bar
334 bar.SetControlData(0,kControlProgressBarIndeterminateTag,'\x01')
335 else: # determinate bar
336 bar.SetControlData(0,kControlProgressBarIndeterminateTag,'\x00')
337 if value < 0:
338 value = 0
339 elif value > self.maxval:
340 value = self.maxval
341 self.curval = value
342 self._update(value)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000343
Just van Rossum35b50e22003-06-21 14:41:32 +0000344 def inc(self, n=1):
345 """inc(amt) - Increment progress bar position"""
346 self.set(self.curval + n)
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000347
Jack Jansenf86eda52000-09-19 22:42:38 +0000348ARGV_ID=265
349ARGV_ITEM_OK=1
350ARGV_ITEM_CANCEL=2
351ARGV_OPTION_GROUP=3
352ARGV_OPTION_EXPLAIN=4
353ARGV_OPTION_VALUE=5
354ARGV_OPTION_ADD=6
355ARGV_COMMAND_GROUP=7
356ARGV_COMMAND_EXPLAIN=8
357ARGV_COMMAND_ADD=9
358ARGV_ADD_OLDFILE=10
359ARGV_ADD_NEWFILE=11
360ARGV_ADD_FOLDER=12
361ARGV_CMDLINE_GROUP=13
362ARGV_CMDLINE_DATA=14
363
364##def _myModalDialog(d):
Raymond Hettingerff41c482003-04-06 09:01:11 +0000365## while 1:
Just van Rossum35b50e22003-06-21 14:41:32 +0000366## ready, ev = Evt.WaitNextEvent(0xffff, -1)
367## print 'DBG: WNE', ready, ev
368## if ready :
369## what,msg,when,where,mod = ev
370## part, window = Win.FindWindow(where)
371## if Dlg.IsDialogEvent(ev):
372## didit, dlgdone, itemdone = Dlg.DialogSelect(ev)
373## print 'DBG: DialogSelect', didit, dlgdone, itemdone, d
374## if didit and dlgdone == d:
375## return itemdone
376## elif window == d.GetDialogWindow():
377## d.GetDialogWindow().SelectWindow()
378## if part == 4: # inDrag
379## d.DragWindow(where, screenbounds)
380## else:
381## MacOS.HandleEvent(ev)
382## else:
383## MacOS.HandleEvent(ev)
Jack Jansenf86eda52000-09-19 22:42:38 +0000384##
385def _setmenu(control, items):
Tim Peters182b5ac2004-07-18 06:16:08 +0000386 mhandle = control.GetControlData_Handle(Controls.kControlMenuPart,
387 Controls.kControlPopupButtonMenuHandleTag)
388 menu = Menu.as_Menu(mhandle)
389 for item in items:
390 if type(item) == type(()):
391 label = item[0]
392 else:
393 label = item
394 if label[-1] == '=' or label[-1] == ':':
395 label = label[:-1]
396 menu.AppendMenu(label)
Just van Rossum35b50e22003-06-21 14:41:32 +0000397## mhandle, mid = menu.getpopupinfo()
398## control.SetControlData_Handle(Controls.kControlMenuPart,
399## Controls.kControlPopupButtonMenuHandleTag, mhandle)
Tim Peters182b5ac2004-07-18 06:16:08 +0000400 control.SetControlMinimum(1)
401 control.SetControlMaximum(len(items)+1)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000402
Jack Jansenf86eda52000-09-19 22:42:38 +0000403def _selectoption(d, optionlist, idx):
Just van Rossum35b50e22003-06-21 14:41:32 +0000404 if idx < 0 or idx >= len(optionlist):
405 MacOS.SysBeep()
406 return
407 option = optionlist[idx]
408 if type(option) == type(()):
409 if len(option) == 4:
410 help = option[2]
411 elif len(option) > 1:
412 help = option[-1]
Raymond Hettingerff41c482003-04-06 09:01:11 +0000413 else:
Just van Rossum35b50e22003-06-21 14:41:32 +0000414 help = ''
415 else:
416 help = ''
417 h = d.GetDialogItemAsControl(ARGV_OPTION_EXPLAIN)
418 if help and len(help) > 250:
419 help = help[:250] + '...'
420 Dlg.SetDialogItemText(h, help)
421 hasvalue = 0
422 if type(option) == type(()):
423 label = option[0]
424 else:
425 label = option
426 if label[-1] == '=' or label[-1] == ':':
427 hasvalue = 1
428 h = d.GetDialogItemAsControl(ARGV_OPTION_VALUE)
429 Dlg.SetDialogItemText(h, '')
430 if hasvalue:
431 d.ShowDialogItem(ARGV_OPTION_VALUE)
432 d.SelectDialogItemText(ARGV_OPTION_VALUE, 0, 0)
433 else:
434 d.HideDialogItem(ARGV_OPTION_VALUE)
Jack Jansenf86eda52000-09-19 22:42:38 +0000435
436
437def GetArgv(optionlist=None, commandlist=None, addoldfile=1, addnewfile=1, addfolder=1, id=ARGV_ID):
Just van Rossum35b50e22003-06-21 14:41:32 +0000438 _initialize()
439 _interact()
440 d = GetNewDialog(id, -1)
441 if not d:
442 print "EasyDialogs: Can't get DLOG resource with id =", id, " (missing resource file?)"
443 return
Raymond Hettingerff41c482003-04-06 09:01:11 +0000444# h = d.GetDialogItemAsControl(3)
445# SetDialogItemText(h, lf2cr(prompt))
446# h = d.GetDialogItemAsControl(4)
447# SetDialogItemText(h, lf2cr(default))
448# d.SelectDialogItemText(4, 0, 999)
449# d.SetDialogItem(4, 0, 255)
Just van Rossum35b50e22003-06-21 14:41:32 +0000450 if optionlist:
451 _setmenu(d.GetDialogItemAsControl(ARGV_OPTION_GROUP), optionlist)
452 _selectoption(d, optionlist, 0)
453 else:
454 d.GetDialogItemAsControl(ARGV_OPTION_GROUP).DeactivateControl()
455 if commandlist:
456 _setmenu(d.GetDialogItemAsControl(ARGV_COMMAND_GROUP), commandlist)
457 if type(commandlist[0]) == type(()) and len(commandlist[0]) > 1:
458 help = commandlist[0][-1]
459 h = d.GetDialogItemAsControl(ARGV_COMMAND_EXPLAIN)
460 Dlg.SetDialogItemText(h, help)
461 else:
462 d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).DeactivateControl()
463 if not addoldfile:
464 d.GetDialogItemAsControl(ARGV_ADD_OLDFILE).DeactivateControl()
465 if not addnewfile:
466 d.GetDialogItemAsControl(ARGV_ADD_NEWFILE).DeactivateControl()
467 if not addfolder:
468 d.GetDialogItemAsControl(ARGV_ADD_FOLDER).DeactivateControl()
469 d.SetDialogDefaultItem(ARGV_ITEM_OK)
470 d.SetDialogCancelItem(ARGV_ITEM_CANCEL)
471 d.GetDialogWindow().ShowWindow()
472 d.DrawDialog()
473 if hasattr(MacOS, 'SchedParams'):
474 appsw = MacOS.SchedParams(1, 0)
475 try:
476 while 1:
477 stringstoadd = []
478 n = ModalDialog(None)
479 if n == ARGV_ITEM_OK:
480 break
481 elif n == ARGV_ITEM_CANCEL:
482 raise SystemExit
483 elif n == ARGV_OPTION_GROUP:
484 idx = d.GetDialogItemAsControl(ARGV_OPTION_GROUP).GetControlValue()-1
485 _selectoption(d, optionlist, idx)
486 elif n == ARGV_OPTION_VALUE:
487 pass
488 elif n == ARGV_OPTION_ADD:
489 idx = d.GetDialogItemAsControl(ARGV_OPTION_GROUP).GetControlValue()-1
490 if 0 <= idx < len(optionlist):
491 option = optionlist[idx]
492 if type(option) == type(()):
493 option = option[0]
494 if option[-1] == '=' or option[-1] == ':':
495 option = option[:-1]
496 h = d.GetDialogItemAsControl(ARGV_OPTION_VALUE)
497 value = Dlg.GetDialogItemText(h)
498 else:
499 value = ''
500 if len(option) == 1:
501 stringtoadd = '-' + option
502 else:
503 stringtoadd = '--' + option
504 stringstoadd = [stringtoadd]
505 if value:
506 stringstoadd.append(value)
507 else:
508 MacOS.SysBeep()
509 elif n == ARGV_COMMAND_GROUP:
510 idx = d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).GetControlValue()-1
511 if 0 <= idx < len(commandlist) and type(commandlist[idx]) == type(()) and \
512 len(commandlist[idx]) > 1:
513 help = commandlist[idx][-1]
514 h = d.GetDialogItemAsControl(ARGV_COMMAND_EXPLAIN)
515 Dlg.SetDialogItemText(h, help)
516 elif n == ARGV_COMMAND_ADD:
517 idx = d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).GetControlValue()-1
518 if 0 <= idx < len(commandlist):
519 command = commandlist[idx]
520 if type(command) == type(()):
521 command = command[0]
522 stringstoadd = [command]
523 else:
524 MacOS.SysBeep()
525 elif n == ARGV_ADD_OLDFILE:
526 pathname = AskFileForOpen()
527 if pathname:
528 stringstoadd = [pathname]
529 elif n == ARGV_ADD_NEWFILE:
530 pathname = AskFileForSave()
531 if pathname:
532 stringstoadd = [pathname]
533 elif n == ARGV_ADD_FOLDER:
534 pathname = AskFolder()
535 if pathname:
536 stringstoadd = [pathname]
537 elif n == ARGV_CMDLINE_DATA:
538 pass # Nothing to do
539 else:
540 raise RuntimeError, "Unknown dialog item %d"%n
Raymond Hettingerff41c482003-04-06 09:01:11 +0000541
Just van Rossum35b50e22003-06-21 14:41:32 +0000542 for stringtoadd in stringstoadd:
543 if '"' in stringtoadd or "'" in stringtoadd or " " in stringtoadd:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000544 stringtoadd = repr(stringtoadd)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000545 h = d.GetDialogItemAsControl(ARGV_CMDLINE_DATA)
546 oldstr = GetDialogItemText(h)
Just van Rossum35b50e22003-06-21 14:41:32 +0000547 if oldstr and oldstr[-1] != ' ':
548 oldstr = oldstr + ' '
549 oldstr = oldstr + stringtoadd
550 if oldstr[-1] != ' ':
551 oldstr = oldstr + ' '
552 SetDialogItemText(h, oldstr)
553 d.SelectDialogItemText(ARGV_CMDLINE_DATA, 0x7fff, 0x7fff)
554 h = d.GetDialogItemAsControl(ARGV_CMDLINE_DATA)
555 oldstr = GetDialogItemText(h)
556 tmplist = string.split(oldstr)
557 newlist = []
558 while tmplist:
559 item = tmplist[0]
560 del tmplist[0]
561 if item[0] == '"':
562 while item[-1] != '"':
563 if not tmplist:
564 raise RuntimeError, "Unterminated quoted argument"
565 item = item + ' ' + tmplist[0]
566 del tmplist[0]
567 item = item[1:-1]
568 if item[0] == "'":
569 while item[-1] != "'":
570 if not tmplist:
571 raise RuntimeError, "Unterminated quoted argument"
572 item = item + ' ' + tmplist[0]
573 del tmplist[0]
574 item = item[1:-1]
575 newlist.append(item)
576 return newlist
577 finally:
578 if hasattr(MacOS, 'SchedParams'):
579 MacOS.SchedParams(*appsw)
580 del d
Jack Jansenf0d12da2003-01-17 16:04:39 +0000581
Jack Jansen3032fe62003-01-21 14:38:32 +0000582def _process_Nav_args(dftflags, **args):
Ronald Oussoren919697c2009-01-02 14:52:09 +0000583 import Carbon.AppleEvents
Just van Rossum35b50e22003-06-21 14:41:32 +0000584 import Carbon.AE
585 import Carbon.File
586 for k in args.keys():
587 if args[k] is None:
588 del args[k]
589 # Set some defaults, and modify some arguments
Mark Dickinsona3a50502010-04-03 18:17:54 +0000590 if 'dialogOptionFlags' not in args:
Just van Rossum35b50e22003-06-21 14:41:32 +0000591 args['dialogOptionFlags'] = dftflags
Mark Dickinsona3a50502010-04-03 18:17:54 +0000592 if 'defaultLocation' in args and \
Just van Rossum35b50e22003-06-21 14:41:32 +0000593 not isinstance(args['defaultLocation'], Carbon.AE.AEDesc):
594 defaultLocation = args['defaultLocation']
Ronald Oussoren919697c2009-01-02 14:52:09 +0000595 if isinstance(defaultLocation, Carbon.File.FSSpec):
596 args['defaultLocation'] = Carbon.AE.AECreateDesc(
597 Carbon.AppleEvents.typeFSS, defaultLocation.data)
Just van Rossum35b50e22003-06-21 14:41:32 +0000598 else:
Ronald Oussoren919697c2009-01-02 14:52:09 +0000599 if not isinstance(defaultLocation, Carbon.File.FSRef):
600 defaultLocation = Carbon.File.FSRef(defaultLocation)
601 args['defaultLocation'] = Carbon.AE.AECreateDesc(
602 Carbon.AppleEvents.typeFSRef, defaultLocation.data)
Mark Dickinsona3a50502010-04-03 18:17:54 +0000603 if 'typeList' in args and not isinstance(args['typeList'], Carbon.Res.ResourceType):
Just van Rossum35b50e22003-06-21 14:41:32 +0000604 typeList = args['typeList'][:]
605 # Workaround for OSX typeless files:
606 if 'TEXT' in typeList and not '\0\0\0\0' in typeList:
607 typeList = typeList + ('\0\0\0\0',)
608 data = 'Pyth' + struct.pack("hh", 0, len(typeList))
609 for type in typeList:
610 data = data+type
611 args['typeList'] = Carbon.Res.Handle(data)
612 tpwanted = str
Mark Dickinsona3a50502010-04-03 18:17:54 +0000613 if 'wanted' in args:
Just van Rossum35b50e22003-06-21 14:41:32 +0000614 tpwanted = args['wanted']
615 del args['wanted']
616 return args, tpwanted
Raymond Hettingerff41c482003-04-06 09:01:11 +0000617
Jack Jansen2731c5c2003-02-07 15:45:40 +0000618def _dummy_Nav_eventproc(msg, data):
Just van Rossum35b50e22003-06-21 14:41:32 +0000619 pass
Raymond Hettingerff41c482003-04-06 09:01:11 +0000620
Jack Jansen2731c5c2003-02-07 15:45:40 +0000621_default_Nav_eventproc = _dummy_Nav_eventproc
622
623def SetDefaultEventProc(proc):
Just van Rossum35b50e22003-06-21 14:41:32 +0000624 global _default_Nav_eventproc
625 rv = _default_Nav_eventproc
626 if proc is None:
627 proc = _dummy_Nav_eventproc
628 _default_Nav_eventproc = proc
629 return rv
Raymond Hettingerff41c482003-04-06 09:01:11 +0000630
Jack Jansen3032fe62003-01-21 14:38:32 +0000631def AskFileForOpen(
Just van Rossum35b50e22003-06-21 14:41:32 +0000632 message=None,
633 typeList=None,
634 # From here on the order is not documented
635 version=None,
636 defaultLocation=None,
637 dialogOptionFlags=None,
638 location=None,
639 clientName=None,
640 windowTitle=None,
641 actionButtonLabel=None,
642 cancelButtonLabel=None,
643 preferenceKey=None,
644 popupExtension=None,
645 eventProc=_dummy_Nav_eventproc,
646 previewProc=None,
647 filterProc=None,
648 wanted=None,
649 multiple=None):
650 """Display a dialog asking the user for a file to open.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000651
Just van Rossum35b50e22003-06-21 14:41:32 +0000652 wanted is the return type wanted: FSSpec, FSRef, unicode or string (default)
653 the other arguments can be looked up in Apple's Navigation Services documentation"""
Raymond Hettingerff41c482003-04-06 09:01:11 +0000654
Just van Rossum35b50e22003-06-21 14:41:32 +0000655 default_flags = 0x56 # Or 0xe4?
656 args, tpwanted = _process_Nav_args(default_flags, version=version,
657 defaultLocation=defaultLocation, dialogOptionFlags=dialogOptionFlags,
658 location=location,clientName=clientName,windowTitle=windowTitle,
659 actionButtonLabel=actionButtonLabel,cancelButtonLabel=cancelButtonLabel,
660 message=message,preferenceKey=preferenceKey,
661 popupExtension=popupExtension,eventProc=eventProc,previewProc=previewProc,
662 filterProc=filterProc,typeList=typeList,wanted=wanted,multiple=multiple)
663 _interact()
664 try:
665 rr = Nav.NavChooseFile(args)
666 good = 1
667 except Nav.error, arg:
668 if arg[0] != -128: # userCancelledErr
669 raise Nav.error, arg
670 return None
671 if not rr.validRecord or not rr.selection:
672 return None
673 if issubclass(tpwanted, Carbon.File.FSRef):
674 return tpwanted(rr.selection_fsr[0])
675 if issubclass(tpwanted, Carbon.File.FSSpec):
676 return tpwanted(rr.selection[0])
677 if issubclass(tpwanted, str):
678 return tpwanted(rr.selection_fsr[0].as_pathname())
679 if issubclass(tpwanted, unicode):
680 return tpwanted(rr.selection_fsr[0].as_pathname(), 'utf8')
681 raise TypeError, "Unknown value for argument 'wanted': %s" % repr(tpwanted)
Jack Jansenf0d12da2003-01-17 16:04:39 +0000682
Jack Jansen3032fe62003-01-21 14:38:32 +0000683def AskFileForSave(
Just van Rossum35b50e22003-06-21 14:41:32 +0000684 message=None,
685 savedFileName=None,
686 # From here on the order is not documented
687 version=None,
688 defaultLocation=None,
689 dialogOptionFlags=None,
690 location=None,
691 clientName=None,
692 windowTitle=None,
693 actionButtonLabel=None,
694 cancelButtonLabel=None,
695 preferenceKey=None,
696 popupExtension=None,
697 eventProc=_dummy_Nav_eventproc,
698 fileType=None,
699 fileCreator=None,
700 wanted=None,
701 multiple=None):
702 """Display a dialog asking the user for a filename to save to.
Jack Jansen3032fe62003-01-21 14:38:32 +0000703
Just van Rossum35b50e22003-06-21 14:41:32 +0000704 wanted is the return type wanted: FSSpec, FSRef, unicode or string (default)
705 the other arguments can be looked up in Apple's Navigation Services documentation"""
Raymond Hettingerff41c482003-04-06 09:01:11 +0000706
707
Just van Rossum35b50e22003-06-21 14:41:32 +0000708 default_flags = 0x07
709 args, tpwanted = _process_Nav_args(default_flags, version=version,
710 defaultLocation=defaultLocation, dialogOptionFlags=dialogOptionFlags,
711 location=location,clientName=clientName,windowTitle=windowTitle,
712 actionButtonLabel=actionButtonLabel,cancelButtonLabel=cancelButtonLabel,
713 savedFileName=savedFileName,message=message,preferenceKey=preferenceKey,
714 popupExtension=popupExtension,eventProc=eventProc,fileType=fileType,
715 fileCreator=fileCreator,wanted=wanted,multiple=multiple)
716 _interact()
717 try:
718 rr = Nav.NavPutFile(args)
719 good = 1
720 except Nav.error, arg:
721 if arg[0] != -128: # userCancelledErr
722 raise Nav.error, arg
723 return None
724 if not rr.validRecord or not rr.selection:
725 return None
726 if issubclass(tpwanted, Carbon.File.FSRef):
727 raise TypeError, "Cannot pass wanted=FSRef to AskFileForSave"
728 if issubclass(tpwanted, Carbon.File.FSSpec):
729 return tpwanted(rr.selection[0])
730 if issubclass(tpwanted, (str, unicode)):
Ronald Oussoren9545a232010-05-05 19:09:31 +0000731 # This is gross, and probably incorrect too
732 vrefnum, dirid, name = rr.selection[0].as_tuple()
733 pardir_fss = Carbon.File.FSSpec((vrefnum, dirid, ''))
734 pardir_fsr = Carbon.File.FSRef(pardir_fss)
735 pardir_path = pardir_fsr.FSRefMakePath() # This is utf-8
736 name_utf8 = unicode(name, 'macroman').encode('utf8')
737 fullpath = os.path.join(pardir_path, name_utf8)
Just van Rossum35b50e22003-06-21 14:41:32 +0000738 if issubclass(tpwanted, unicode):
739 return unicode(fullpath, 'utf8')
740 return tpwanted(fullpath)
741 raise TypeError, "Unknown value for argument 'wanted': %s" % repr(tpwanted)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000742
Jack Jansen3032fe62003-01-21 14:38:32 +0000743def AskFolder(
Just van Rossum35b50e22003-06-21 14:41:32 +0000744 message=None,
745 # From here on the order is not documented
746 version=None,
747 defaultLocation=None,
748 dialogOptionFlags=None,
749 location=None,
750 clientName=None,
751 windowTitle=None,
752 actionButtonLabel=None,
753 cancelButtonLabel=None,
754 preferenceKey=None,
755 popupExtension=None,
756 eventProc=_dummy_Nav_eventproc,
757 filterProc=None,
758 wanted=None,
759 multiple=None):
760 """Display a dialog asking the user for select a folder.
Raymond Hettingerff41c482003-04-06 09:01:11 +0000761
Just van Rossum35b50e22003-06-21 14:41:32 +0000762 wanted is the return type wanted: FSSpec, FSRef, unicode or string (default)
763 the other arguments can be looked up in Apple's Navigation Services documentation"""
Raymond Hettingerff41c482003-04-06 09:01:11 +0000764
Just van Rossum35b50e22003-06-21 14:41:32 +0000765 default_flags = 0x17
766 args, tpwanted = _process_Nav_args(default_flags, version=version,
767 defaultLocation=defaultLocation, dialogOptionFlags=dialogOptionFlags,
768 location=location,clientName=clientName,windowTitle=windowTitle,
769 actionButtonLabel=actionButtonLabel,cancelButtonLabel=cancelButtonLabel,
770 message=message,preferenceKey=preferenceKey,
771 popupExtension=popupExtension,eventProc=eventProc,filterProc=filterProc,
772 wanted=wanted,multiple=multiple)
773 _interact()
774 try:
775 rr = Nav.NavChooseFolder(args)
776 good = 1
777 except Nav.error, arg:
778 if arg[0] != -128: # userCancelledErr
779 raise Nav.error, arg
780 return None
781 if not rr.validRecord or not rr.selection:
782 return None
783 if issubclass(tpwanted, Carbon.File.FSRef):
784 return tpwanted(rr.selection_fsr[0])
785 if issubclass(tpwanted, Carbon.File.FSSpec):
786 return tpwanted(rr.selection[0])
787 if issubclass(tpwanted, str):
788 return tpwanted(rr.selection_fsr[0].as_pathname())
789 if issubclass(tpwanted, unicode):
790 return tpwanted(rr.selection_fsr[0].as_pathname(), 'utf8')
791 raise TypeError, "Unknown value for argument 'wanted': %s" % repr(tpwanted)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000792
Jack Jansenf0d12da2003-01-17 16:04:39 +0000793
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000794def test():
Just van Rossum35b50e22003-06-21 14:41:32 +0000795 import time
Jack Jansen1d63d8c1997-05-12 15:44:14 +0000796
Just van Rossum35b50e22003-06-21 14:41:32 +0000797 Message("Testing EasyDialogs.")
798 optionlist = (('v', 'Verbose'), ('verbose', 'Verbose as long option'),
799 ('flags=', 'Valued option'), ('f:', 'Short valued option'))
800 commandlist = (('start', 'Start something'), ('stop', 'Stop something'))
801 argv = GetArgv(optionlist=optionlist, commandlist=commandlist, addoldfile=0)
802 Message("Command line: %s"%' '.join(argv))
803 for i in range(len(argv)):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000804 print 'arg[%d] = %r' % (i, argv[i])
Just van Rossum35b50e22003-06-21 14:41:32 +0000805 ok = AskYesNoCancel("Do you want to proceed?")
806 ok = AskYesNoCancel("Do you want to identify?", yes="Identify", no="No")
807 if ok > 0:
808 s = AskString("Enter your first name", "Joe")
809 s2 = AskPassword("Okay %s, tell us your nickname"%s, s, cancel="None")
810 if not s2:
811 Message("%s has no secret nickname"%s)
Raymond Hettingerff41c482003-04-06 09:01:11 +0000812 else:
Just van Rossum35b50e22003-06-21 14:41:32 +0000813 Message("Hello everybody!!\nThe secret nickname of %s is %s!!!"%(s, s2))
814 else:
815 s = 'Anonymous'
816 rv = AskFileForOpen(message="Gimme a file, %s"%s, wanted=Carbon.File.FSSpec)
817 Message("rv: %s"%rv)
818 rv = AskFileForSave(wanted=Carbon.File.FSRef, savedFileName="%s.txt"%s)
819 Message("rv.as_pathname: %s"%rv.as_pathname())
820 rv = AskFolder()
821 Message("Folder name: %s"%rv)
822 text = ( "Working Hard...", "Hardly Working..." ,
823 "So far, so good!", "Keep on truckin'" )
824 bar = ProgressBar("Progress, progress...", 0, label="Ramping up...")
825 try:
826 if hasattr(MacOS, 'SchedParams'):
827 appsw = MacOS.SchedParams(1, 0)
828 for i in xrange(20):
829 bar.inc()
830 time.sleep(0.05)
831 bar.set(0,100)
832 for i in xrange(100):
833 bar.set(i)
834 time.sleep(0.05)
835 if i % 10 == 0:
836 bar.label(text[(i/10) % 4])
837 bar.label("Done.")
838 time.sleep(1.0) # give'em a chance to see "Done."
839 finally:
840 del bar
841 if hasattr(MacOS, 'SchedParams'):
842 MacOS.SchedParams(*appsw)
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000843
Guido van Rossum8f4b6ad1995-04-05 09:18:35 +0000844if __name__ == '__main__':
Just van Rossum35b50e22003-06-21 14:41:32 +0000845 try:
846 test()
847 except KeyboardInterrupt:
848 Message("Operation Canceled.")