1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/desktop/dialog.py Mon Dec 03 00:37:15 2007 +0000
1.3 @@ -0,0 +1,422 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +Simple desktop dialogue box support for Python.
1.8 +
1.9 +Copyright (C) 2005, 2006, 2007 Paul Boddie <paul@boddie.org.uk>
1.10 +
1.11 +This library is free software; you can redistribute it and/or
1.12 +modify it under the terms of the GNU Lesser General Public
1.13 +License as published by the Free Software Foundation; either
1.14 +version 2.1 of the License, or (at your option) any later version.
1.15 +
1.16 +This library is distributed in the hope that it will be useful,
1.17 +but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.19 +Lesser General Public License for more details.
1.20 +
1.21 +You should have received a copy of the GNU Lesser General Public
1.22 +License along with this library; if not, write to the Free Software
1.23 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
1.24 +
1.25 +--------
1.26 +
1.27 +Opening Dialogue Boxes (Dialogs)
1.28 +--------------------------------
1.29 +
1.30 +To open a dialogue box (dialog) in the current desktop environment, relying on
1.31 +the automatic detection of that environment, use the appropriate dialogue box
1.32 +class:
1.33 +
1.34 +question = desktop.dialog.Question("Are you sure?")
1.35 +question.open()
1.36 +
1.37 +To override the detected desktop, specify the desktop parameter to the open
1.38 +function as follows:
1.39 +
1.40 +question.open("KDE") # Insists on KDE
1.41 +question.open("GNOME") # Insists on GNOME
1.42 +
1.43 +The dialogue box options are documented in each class's docstring.
1.44 +"""
1.45 +
1.46 +from desktop import use_desktop, _run, _readfrom, _status
1.47 +
1.48 +# Dialogue parameter classes.
1.49 +
1.50 +class String:
1.51 +
1.52 + "A generic parameter."
1.53 +
1.54 + def __init__(self, name):
1.55 + self.name = name
1.56 +
1.57 + def convert(self, value, program):
1.58 + return [value or ""]
1.59 +
1.60 +class Strings(String):
1.61 +
1.62 + "Multiple string parameters."
1.63 +
1.64 + def convert(self, value, program):
1.65 + return value or []
1.66 +
1.67 +class StringKeyword:
1.68 +
1.69 + "A keyword parameter."
1.70 +
1.71 + def __init__(self, keyword, name):
1.72 + self.keyword = keyword
1.73 + self.name = name
1.74 +
1.75 + def convert(self, value, program):
1.76 + return [self.keyword + "=" + (value or "")]
1.77 +
1.78 +class StringKeywords:
1.79 +
1.80 + "Multiple keyword parameters."
1.81 +
1.82 + def __init__(self, keyword, name):
1.83 + self.keyword = keyword
1.84 + self.name = name
1.85 +
1.86 + def convert(self, value, program):
1.87 + l = []
1.88 + for v in value or []:
1.89 + l.append(self.keyword + "=" + v)
1.90 + return l
1.91 +
1.92 +class Integer(String):
1.93 +
1.94 + "An integer parameter."
1.95 +
1.96 + defaults = {
1.97 + "width" : 40,
1.98 + "height" : 15,
1.99 + "list_height" : 10
1.100 + }
1.101 +
1.102 + def convert(self, value, program):
1.103 + if value is None:
1.104 + value = self.defaults[self.name]
1.105 + return [str(int(value))]
1.106 +
1.107 +class IntegerKeyword(Integer):
1.108 +
1.109 + "An integer keyword parameter."
1.110 +
1.111 + def __init__(self, keyword, name):
1.112 + self.keyword = keyword
1.113 + self.name = name
1.114 +
1.115 + def convert(self, value, program):
1.116 + if value is None:
1.117 + value = self.defaults[self.name]
1.118 + return [self.keyword + "=" + str(int(value))]
1.119 +
1.120 +class Boolean(String):
1.121 +
1.122 + "A boolean parameter."
1.123 +
1.124 + values = {
1.125 + "kdialog" : ["off", "on"],
1.126 + "zenity" : ["FALSE", "TRUE"],
1.127 + "Xdialog" : ["off", "on"]
1.128 + }
1.129 +
1.130 + def convert(self, value, program):
1.131 + values = self.values[program]
1.132 + if value:
1.133 + return [values[1]]
1.134 + else:
1.135 + return [values[0]]
1.136 +
1.137 +class MenuItemList(String):
1.138 +
1.139 + "A menu item list parameter."
1.140 +
1.141 + def convert(self, value, program):
1.142 + l = []
1.143 + for v in value:
1.144 + l.append(v.value)
1.145 + l.append(v.text)
1.146 + return l
1.147 +
1.148 +class ListItemList(String):
1.149 +
1.150 + "A menu item list parameter."
1.151 +
1.152 + def convert(self, value, program):
1.153 + l = []
1.154 + for v in value:
1.155 + l.append(v.value)
1.156 + l.append(v.text)
1.157 + boolean = Boolean(None)
1.158 + l.append(boolean.convert(v.status, program))
1.159 + return l
1.160 +
1.161 +# Dialogue argument values.
1.162 +
1.163 +class MenuItem:
1.164 + def __init__(self, value, text):
1.165 + self.value = value
1.166 + self.text = text
1.167 +
1.168 +class ListItem(MenuItem):
1.169 + def __init__(self, value, text, status):
1.170 + MenuItem.__init__(self, value, text)
1.171 + self.status = status
1.172 +
1.173 +# Dialogue classes.
1.174 +
1.175 +class Dialogue:
1.176 +
1.177 + commands = {
1.178 + "KDE" : "kdialog",
1.179 + "GNOME" : "zenity",
1.180 + "X11" : "Xdialog"
1.181 + }
1.182 +
1.183 + def open(self, desktop=None):
1.184 +
1.185 + """
1.186 + Open a dialogue box (dialog) using a program appropriate to the desktop
1.187 + environment in use.
1.188 +
1.189 + If the optional 'desktop' parameter is specified then attempt to use that
1.190 + particular desktop environment's mechanisms to open the dialog instead of
1.191 + guessing or detecting which environment is being used.
1.192 +
1.193 + Suggested values for 'desktop' are "standard", "KDE", "GNOME", "Mac OS X",
1.194 + "Windows".
1.195 +
1.196 + The result of the dialogue interaction may be a string indicating user
1.197 + input (for input, password, menu, radiolist, pulldown), a list of strings
1.198 + indicating selections of one or more items (for checklist), or a value
1.199 + indicating true or false (for question).
1.200 + """
1.201 +
1.202 + # Decide on the desktop environment in use.
1.203 +
1.204 + desktop_in_use = use_desktop(desktop)
1.205 +
1.206 + # Get the program.
1.207 +
1.208 + try:
1.209 + program = self.commands[desktop_in_use]
1.210 + except KeyError:
1.211 + raise OSError, "Desktop '%s' not supported (no known dialogue box command could be suggested)" % desktop_in_use
1.212 +
1.213 + handler, options = self.info[program]
1.214 +
1.215 + cmd = [program]
1.216 + for option in options:
1.217 + if isinstance(option, str):
1.218 + cmd.append(option)
1.219 + else:
1.220 + value = getattr(self, option.name, None)
1.221 + cmd += option.convert(value, program)
1.222 +
1.223 + print cmd
1.224 + return handler(cmd, 0)
1.225 +
1.226 +class Simple(Dialogue):
1.227 + def __init__(self, text, width=None, height=None):
1.228 + self.text = text
1.229 + self.width = width
1.230 + self.height = height
1.231 +
1.232 +class Question(Simple):
1.233 +
1.234 + """
1.235 + A dialogue asking a question and showing response buttons.
1.236 + Options: text, width (in characters), height (in characters)
1.237 + """
1.238 +
1.239 + name = "question"
1.240 + info = {
1.241 + "kdialog" : (_status, ["--yesno", String("text")]),
1.242 + "zenity" : (_status, ["--question", StringKeyword("--text", "text")]),
1.243 + "Xdialog" : (_status, ["--stdout", "--yesno", String("text"), Integer("height"), Integer("width")]),
1.244 + }
1.245 +
1.246 +class Warning(Simple):
1.247 +
1.248 + """
1.249 + A dialogue asking a question and showing response buttons.
1.250 + Options: text, width (in characters), height (in characters)
1.251 + """
1.252 +
1.253 + name = "warning"
1.254 + info = {
1.255 + "kdialog" : (_status, ["--warningyesno", String("text")]),
1.256 + "zenity" : (_status, ["--warning", StringKeyword("--text", "text")]),
1.257 + "Xdialog" : (_status, ["--stdout", "--yesno", String("text"), Integer("height"), Integer("width")]),
1.258 + }
1.259 +
1.260 +class Message(Simple):
1.261 +
1.262 + """
1.263 + A message dialogue.
1.264 + Options: text, width (in characters), height (in characters)
1.265 + """
1.266 +
1.267 + name = "message"
1.268 + info = {
1.269 + "kdialog" : (_status, ["--msgbox", String("text")]),
1.270 + "zenity" : (_status, ["--info", StringKeyword("--text", "text")]),
1.271 + "Xdialog" : (_status, ["--stdout", "--msgbox", String("text"), Integer("height"), Integer("width")]),
1.272 + }
1.273 +
1.274 +class Error(Simple):
1.275 +
1.276 + """
1.277 + An error dialogue.
1.278 + Options: text, width (in characters), height (in characters)
1.279 + """
1.280 +
1.281 + name = "error"
1.282 + info = {
1.283 + "kdialog" : (_status, ["--error", String("text")]),
1.284 + "zenity" : (_status, ["--error", StringKeyword("--text", "text")]),
1.285 + "Xdialog" : (_status, ["--stdout", "--msgbox", String("text"), Integer("height"), Integer("width")]),
1.286 + }
1.287 +
1.288 +class Menu(Simple):
1.289 +
1.290 + """
1.291 + A menu of options, one of which being selectable.
1.292 + Options: text, width (in characters), height (in characters),
1.293 + list_height (in items), items (MenuItem objects)
1.294 + """
1.295 +
1.296 + name = "menu"
1.297 + info = {
1.298 + "kdialog" : (_readfrom, ["--menu", String("text"), MenuItemList("items")]),
1.299 + "zenity" : (_readfrom, ["--list", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
1.300 + MenuItemList("items")]
1.301 + ),
1.302 + "Xdialog" : (_readfrom, ["--stdout", "--menubox",
1.303 + String("text"), Integer("height"), Integer("width"), Integer("list_height"), MenuItemList("items")]
1.304 + ),
1.305 + }
1.306 +
1.307 + def __init__(self, text, titles, items, width=None, height=None, list_height=None):
1.308 + Simple.__init__(self, text, width, height)
1.309 + self.titles = titles
1.310 + self.items = items
1.311 + self.list_height = list_height
1.312 +
1.313 +class RadioList(Menu):
1.314 +
1.315 + """
1.316 + A list of radio buttons, one of which being selectable.
1.317 + Options: text, width (in characters), height (in characters),
1.318 + list_height (in items), items (ListItem objects), titles
1.319 + """
1.320 +
1.321 + name = "radiolist"
1.322 + info = {
1.323 + "kdialog" : (_readfrom, ["--radiolist", String("text"), ListItemList("items")]),
1.324 + "zenity" : (_readfrom,
1.325 + ["--list", "--radiolist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
1.326 + ListItemList("items")]
1.327 + ),
1.328 + "Xdialog" : (_readfrom, ["--stdout", "--radiolist",
1.329 + String("text"), Integer("height"), Integer("width"), Integer("list_height"), ListItemList("items")]
1.330 + ),
1.331 + }
1.332 +
1.333 +class CheckList(Menu):
1.334 +
1.335 + """
1.336 + A list of checkboxes, many being selectable.
1.337 + Options: text, width (in characters), height (in characters),
1.338 + list_height (in items), items (ListItem objects), titles
1.339 + """
1.340 +
1.341 + name = "checklist"
1.342 + info = {
1.343 + "kdialog" : (_readfrom, ["--checklist", String("text"), ListItemList("items")]),
1.344 + "zenity" : (_readfrom,
1.345 + ["--list", "--checklist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
1.346 + ListItemList("items")]
1.347 + ),
1.348 + "Xdialog" : (_readfrom, ["--stdout", "--checklist",
1.349 + String("text"), Integer("height"), Integer("width"), Integer("list_height"), ListItemList("items")]
1.350 + ),
1.351 + }
1.352 +
1.353 +class Pulldown(Menu):
1.354 +
1.355 + """
1.356 + A pull-down menu of options, one of which being selectable.
1.357 + Options: text, width (in characters), height (in characters),
1.358 + entries (list of values)
1.359 + """
1.360 +
1.361 + name = "pulldown"
1.362 + info = {
1.363 + "kdialog" : (_readfrom, ["--combobox", String("text"), Strings("items")]),
1.364 + "zenity" : (_readfrom, ["--list", "--radiolist", StringKeyword("--text", "text"), StringKeywords("--column", "titles"),
1.365 + Strings("items")]
1.366 + ),
1.367 + "Xdialog" : (_readfrom, ["--stdout", "--combobox", String("text"), Integer("height"), Integer("width"), Strings("items")]),
1.368 + }
1.369 +
1.370 +class Input(Simple):
1.371 +
1.372 + """
1.373 + An input dialogue, consisting of an input field.
1.374 + Options: text, width (in characters), height (in characters),
1.375 + input
1.376 + """
1.377 +
1.378 + name = "input"
1.379 + info = {
1.380 + "kdialog" : (_readfrom, ["--inputbox", String("text"), String("data")]),
1.381 + "zenity" : (_readfrom, ["--entry", StringKeyword("--text", "text"), StringKeyword("--entry-text", "data")]),
1.382 + "Xdialog" : (_readfrom, ["--stdout", "--inputbox", String("text"), Integer("height"), Integer("width"), String("data")]),
1.383 + }
1.384 +
1.385 + def __init__(self, text, data, width=None, height=None):
1.386 + Simple.__init__(self, text, width, height)
1.387 + self.data = data
1.388 +
1.389 +class Password(Input):
1.390 +
1.391 + """
1.392 + A password dialogue, consisting of a password entry field.
1.393 + Options: text, width (in characters), height (in characters),
1.394 + input
1.395 + """
1.396 +
1.397 + name = "password"
1.398 + info = {
1.399 + "kdialog" : (_readfrom, ["--password", String("text")]),
1.400 + "zenity" : (_readfrom, ["--password", StringKeyword("--text", "text"), "--hide-text"]),
1.401 + "Xdialog" : (_readfrom, ["--stdout", "--password", "--inputbox", String("text"), Integer("height"), Integer("width")]),
1.402 + }
1.403 +
1.404 +class TextFile(Simple):
1.405 +
1.406 + """
1.407 + A text file input box.
1.408 + Options: text, width (in characters), height (in characters),
1.409 + filename
1.410 + """
1.411 +
1.412 + name = "textfile"
1.413 + info = {
1.414 + "kdialog" : (_readfrom, ["--textbox", String("filename"), String("width"), String("height")]),
1.415 + "zenity" : (_readfrom, ["--textbox", StringKeyword("--filename", "filename"), IntegerKeyword("--width", "width"),
1.416 + IntegerKeyword("--height", "height")]
1.417 + ),
1.418 + "Xdialog" : (_readfrom, ["--stdout", "--textbox", String("text"), Integer("height"), Integer("width")]),
1.419 + }
1.420 +
1.421 + def __init__(self, text, filename, width=None, height=None):
1.422 + Simple.__init__(self, text, width, height)
1.423 + self.filename = filename
1.424 +
1.425 +# vim: tabstop=4 expandtab shiftwidth=4