-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathPyZenity.py
439 lines (327 loc) · 14.7 KB
/
PyZenity.py
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
################################################################################
# Name: PyZenity.py
# Author: Brian Ramos
# Created: 10/17/2005
# Revision Information:
# $Date: $
# $Revision: $
# $Author: bramos $
#
# Licence: MIT Licence
#
# Copyright (c) 2010 Brian Ramos
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
################################################################################
from datetime import date
from subprocess import Popen, PIPE
from itertools import chain
from os import path
__all__ = ['GetDate', 'GetFilename', 'GetDirectory', 'GetSavename', 'GetText',
'InfoMessage', 'Question', 'Warning', 'ErrorMessage',
'Notification', 'TextInfo', 'Progress','List' ]
__doc__ = """PyZenity is an easy to use interface to Zenity for Python.
Zenity is normally called from scripts by invoking it with a multitude of
command line parameters that it uses to construct its interfaces. This
module hides the details of invoking the command and presents simple API
functions like:
cancel = Question('Should I cancel the operation?')
Each function takes optional kwargs parameters. This is to allow the use of
general Zenity parameters such as:
title - Set the dialog title
window_icon - Set the window icon
ok_label - Set the text for the Ok label
cancel_label - Set the text for the Cancel label
height - Set the height
width - Set the width
timeout - Set the dialog timeout in seconds"""
zen_exec = 'zenity'
def run_zenity(type, *args):
return Popen([zen_exec, type] + list(args), stdin=PIPE, stdout=PIPE)
# This is a dictionary of optional parameters that would create
# syntax errors in python if they were passed in as kwargs.
kw_subst = {
'window_icon': 'window-icon',
'ok_label': 'ok-label',
'cancel_label': 'cancel-label'
}
def kwargs_helper(kwargs):
"""This function preprocesses the kwargs dictionary to sanitize it."""
args = []
for param, value in kwargs.items():
param = kw_subst.get(param, param)
args.append((param, value))
return args
def GetDate(text=None, selected=None, **kwargs):
"""Prompt the user for a date.
This will raise a Zenity Calendar Dialog for the user to pick a date.
It will return a datetime.date object with the date or None if the
user hit cancel.
text - Text to be displayed in the calendar dialog.
selected - A datetime.date object that will be the pre-selected date.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--date-format=%d/%m/%Y']
if text:
args.append('--text=%s' % text)
if selected:
args.append('--day=%d' % selected.day)
args.append('--month=%d' % selected.month)
args.append('--year=%d' % selected.year)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--calendar', *args)
if p.wait() == 0:
retval = p.stdout.read().strip()
day, month, year = [int(x) for x in retval.split('/')]
return date(year, month, day)
def GetFilename(multiple=False, sep='|', **kwargs):
"""Prompt the user for a filename.
This will raise a Zenity File Selection Dialog. It will return a list with
the selected files or None if the user hit cancel.
multiple - True to allow the user to select multiple files.
sep - Token to use as the path separator when parsing Zenity's return
string.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = []
if multiple:
args.append('--multiple')
if sep != '|':
args.append('--separator=%s' % sep)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--file-selection', *args)
if p.wait() == 0:
return p.stdout.read()[:-1].split('|')
def GetDirectory(multiple=False, selected=None, sep=None, **kwargs):
"""Prompt the user for a directory.
This will raise a Zenity Directory Selection Dialog. It will return a
list with the selected directories or None if the user hit cancel.
multiple - True to allow the user to select multiple directories.
selected - Path to the directory to be selected on startup.
sep - Token to use as the path separator when parsing Zenity's return
string.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--directory']
if multiple:
args.append('--multiple')
if selected:
if not path.lexists(selected):
raise ValueError("File %s does not exist!" % selected)
args.append('--filename=%s' % selected)
if sep:
args.append('--separator=%s' % sep)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--file-selection', *args)
if p.wait() == 0:
return p.stdout.read().strip().split('|')
def GetSavename(default=None, **kwargs):
"""Prompt the user for a filename to save as.
This will raise a Zenity Save As Dialog. It will return the name to save
a file as or None if the user hit cancel.
default - The default name that should appear in the save as dialog.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--save']
if default:
args.append('--filename=%s' % default)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--file-selection', *args)
if p.wait() == 0:
return p.stdout.read().strip().split('|')
def Notification(text=None, window_icon=None, **kwargs):
"""Put an icon in the notification area.
This will put an icon in the notification area and return when the user
clicks on it.
text - The tooltip that will show when the user hovers over it.
window_icon - The stock icon ("question", "info", "warning", "error") or
path to the icon to show.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = []
if text:
args.append('--text=%s' % text)
if window_icon:
args.append('--window-icon=%s' % window_icon)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--notification', *args)
p.wait()
def List(column_names, title=None, boolstyle=None, editable=False,
select_col=None, sep='|', data=[], **kwargs):
"""Present a list of items to select.
This will raise a Zenity List Dialog populated with the colomns and rows
specified and return either the cell or row that was selected or None if
the user hit cancel.
column_names - A tuple or list containing the names of the columns.
title - The title of the dialog box.
boolstyle - Whether the first columns should be a bool option ("checklist",
"radiolist") or None if it should be a text field.
editable - True if the user can edit the cells.
select_col - The column number of the selected cell to return or "ALL" to
return the entire row.
sep - Token to use as the row separator when parsing Zenity's return.
Cells should not contain this token.
data - A list or tuple of tuples that contain the cells in the row. The
size of the row's tuple must be equal to the number of columns.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = []
for column in column_names:
args.append('--column=%s' % column)
if title:
args.append('--title=%s' % title)
if boolstyle:
if not (boolstyle == 'checklist' or boolstyle == 'radiolist'):
raise ValueError('"%s" is not a proper boolean column style.'
% boolstyle)
args.append('--' + boolstyle)
if editable:
args.append('--editable')
if select_col:
args.append('--print-column=%s' % select_col)
if sep != '|':
args.append('--separator=%s' % sep)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
for datum in chain(*data):
args.append(str(datum))
p = run_zenity('--list', *args)
if p.wait() == 0:
return p.stdout.read().strip().split(sep)
def ErrorMessage(text, **kwargs):
"""Show an error message dialog to the user.
This will raise a Zenity Error Dialog with a description of the error.
text - A description of the error.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--text=%s' % text]
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
run_zenity('--error', *args).wait()
def InfoMessage(text, **kwargs):
"""Show an info message dialog to the user.
This will raise a Zenity Info Dialog displaying some information.
text - The information to present to the user.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--text=%s' % text]
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
run_zenity('--info', *args).wait()
def Question(text, **kwargs):
"""Ask the user a question.
This will raise a Zenity Question Dialog that will present the user with an
OK/Cancel dialog box. It returns True if the user clicked OK; False on
Cancel.
text - The question to ask.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--text=%s' % text]
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
return run_zenity('--question', *args).wait() == 0
def Warning(text, **kwargs):
"""Show a warning message dialog to the user.
This will raise a Zenity Warning Dialog with a description of the warning.
It returns True if the user clicked OK; False on cancel.
text - A description of the warning.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = ['--text=%s' % text]
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
return run_zenity('--warning', *args).wait() == 0
def Progress(text='', percentage=0, auto_close=False, pulsate=False, **kwargs):
"""Show a progress dialog to the user.
This will raise a Zenity Progress Dialog. It returns a callback that
accepts two arguments. The first is a numeric value of the percent
complete. The second is a message about the progress.
NOTE: This function sends the SIGHUP signal if the user hits the cancel
button. You must connect to this signal if you do not want your
application to exit.
text - The initial message about the progress.
percentage - The initial percentage to set the progress bar to.
auto_close - True if the dialog should close automatically if it reaches
100%.
pulsate - True is the status should pulsate instead of progress.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = []
if text:
args.append('--text=%s' % text)
if percentage:
args.append('--percentage=%s' % percentage)
if auto_close:
args.append('--auto-close=%s' % auto_close)
if pulsate:
args.append('--pulsate=%s' % pulsate)
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = Popen([zen_exec, '--progress'] + args, stdin=PIPE, stdout=PIPE)
def update(percent, message=''):
if type(percent) == float:
percent = int(percent * 100)
p.stdin.write(str(percent) + '\n')
if message:
p.stdin.write('# %s\n' % message)
return p.returncode
return update
def GetText(text='', entry_text='', password=False, **kwargs):
"""Get some text from the user.
This will raise a Zenity Text Entry Dialog. It returns the text the user
entered or None if the user hit cancel.
text - A description of the text to enter.
entry_text - The initial value of the text entry box.
password - True if text entered should be hidden by stars.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = []
if text:
args.append('--text=%s' % text)
if entry_text:
args.append('--entry-text=%s' % entry_text)
if password:
args.append('--hide-text')
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--entry', *args)
if p.wait() == 0:
return p.stdout.read()[:-1]
def TextInfo(filename=None, editable=False, **kwargs):
"""Show the text of a file to the user.
This will raise a Zenity Text Information Dialog presenting the user with
the contents of a file. It returns the contents of the text box.
filename - The path to the file to show.
editable - True if the text should be editable.
kwargs - Optional command line parameters for Zenity such as height,
width, etc."""
args = []
if filename:
args.append('--filename=%s' % filename)
if editable:
args.append('--editable')
for generic_args in kwargs_helper(kwargs):
args.append('--%s=%s' % generic_args)
p = run_zenity('--text-info', *args)
if p.wait() == 0:
return p.stdout.read()