[node-patches] Change in ovirt-node[master]: Add and improve several modules

fabiand at fedoraproject.org fabiand at fedoraproject.org
Tue Dec 11 20:09:32 UTC 2012


Fabian Deutsch has uploaded a new change for review.

Change subject: Add and improve several modules
......................................................................

Add and improve several modules

Change-Id: Ibe9d524ab38b006e2bc3f521fa560288a19f0f95
Signed-off-by: Fabian Deutsch <fabiand at fedoraproject.org>
---
M scripts/tui/src/app
A scripts/tui/src/ovirt/node/app.py
A scripts/tui/src/ovirt/node/main.py
M scripts/tui/src/ovirt/node/plugins/__init__.py
M scripts/tui/src/ovirt/node/plugins/example.py
M scripts/tui/src/ovirt/node/tui.py
A scripts/tui/src/ovirt/node/utils.py
A scripts/tui/src/ovirt/node/widgets.py
8 files changed, 450 insertions(+), 211 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/67/9867/1

diff --git a/scripts/tui/src/app b/scripts/tui/src/app
index b4cbd9d..1ea2e40 100755
--- a/scripts/tui/src/app
+++ b/scripts/tui/src/app
@@ -1,3 +1,3 @@
 #!/bin/bash
 
-PYTHONPATH=$PYTHONPATH:. python -B -m ovirt.node.tui "$@"
+PYTHONPATH=$PYTHONPATH:. python -B -m ovirt.node.main "$@"
diff --git a/scripts/tui/src/ovirt/node/app.py b/scripts/tui/src/ovirt/node/app.py
new file mode 100644
index 0000000..d362575
--- /dev/null
+++ b/scripts/tui/src/ovirt/node/app.py
@@ -0,0 +1,39 @@
+"""
+Representing the whole application (not just the TUI).
+Basically the application consists of two parts: Plugins and TUI
+which communicate with each other.
+"""
+
+import logging
+
+import ovirt.node.tui
+
+logging.basicConfig(level=logging.DEBUG,
+                    filename="app.log", filemode="w")
+LOGGER = logging.getLogger(__name__)
+
+
+class Application(object):
+    plugins = []
+
+    ui = None
+
+    def __init__(self):
+        self.ui = ovirt.node.tui.UrwidTUI(self)
+
+    def __load_plugins(self):
+        self.plugins = [m.Plugin() for m in ovirt.node.plugins.load_all()]
+
+        for plugin in self.plugins:
+            LOGGER.debug("Loading plugin %s" % plugin)
+            self.ui.register_plugin(plugin.ui_name(), plugin)
+
+    def __drop_to_shell(self):
+        with self.ui.suspended():
+            ovirt.node.utils.system("reset ; bash")
+
+    def run(self):
+        self.__load_plugins()
+        self.ui.register_hotkey("f12", self.__drop_to_shell)
+        self.ui.footer = "Press ctrl+x or esc to quit."
+        self.ui.run()
diff --git a/scripts/tui/src/ovirt/node/main.py b/scripts/tui/src/ovirt/node/main.py
new file mode 100644
index 0000000..ec8d946
--- /dev/null
+++ b/scripts/tui/src/ovirt/node/main.py
@@ -0,0 +1,10 @@
+"""
+Create an application instance an start it.
+"""
+
+import ovirt.node.app
+
+
+if __name__ == '__main__':
+    app = ovirt.node.app.Application()
+    app.run()
diff --git a/scripts/tui/src/ovirt/node/plugins/__init__.py b/scripts/tui/src/ovirt/node/plugins/__init__.py
index f152529..0fb7c91 100644
--- a/scripts/tui/src/ovirt/node/plugins/__init__.py
+++ b/scripts/tui/src/ovirt/node/plugins/__init__.py
@@ -79,6 +79,26 @@
             A dict of validators
         """
 
+    def validate(self, path, value):
+        """Validates a value against the validator of a given path
+
+        Args:
+            path: A model path for a validator
+            value: The value to be validated
+
+        Returns:
+            True on a valid value or if there is no validator for a path
+
+        Raises:
+            InvalidData on any invalid data
+        """
+        if path in self.validators():
+            msg = self.validators()[path](value)
+            # True and None are allowed values
+            if msg not in [True, None]:
+                raise ovirt.node.plugins.InvalidData(msg)
+        return True
+
     def has_ui(self):
         """Determins if a page for this should be displayed in the UI
 
@@ -152,55 +172,100 @@
 
 
 class Widget(object):
-    _enabled = True
-    _signals = None
+    _signal_cbs = None
+    signals = []
+    signaling_properties = []
 
-    def enabled(self, is_enabled=None):
-        if is_enabled in [True, False]:
-            self.emit_signal("enabled[change]", is_enabled)
-            self._enabled = is_enabled
-        return self._enabled
+    def __init__(self):
+        """Registers all widget signals.
+        All signals must be given in self.signals
+        """
+        for name in self.signals:
+            self._register_signal(name)
+        for name in self.signaling_properties:
+            self._register_signaling_property(name)
+
+    def _register_signal(self, name):
+        """Each signal that get's emitted must be registered using this
+        function.
+
+        This is just to have an overview over the signals.
+        """
+        if self._signal_cbs is None:
+            self._signal_cbs = {}
+        if name not in self._signal_cbs:
+            self._signal_cbs[name] = []
+#            LOGGER.debug("Registered new signal '%s' for '%s'" % (name, self))
 
     def connect_signal(self, name, cb):
-        if self._signals is None:
-            self._signals = {}
-        if name not in self._signals:
-            self._signals[name] = []
-        self._signals[name].append(cb)
+        """Connect an callback to a signal
+        """
+        assert name in self._signal_cbs, "Unregistered signal '%s'" % name
+        self._signal_cbs[name].append(cb)
 
     def emit_signal(self, name, userdata=None):
-        if self._signals is None or \
-           name not in self._signals:
+        """Emit a signal
+        """
+        if self._signal_cbs is None or name not in self._signal_cbs:
             return False
-        for cb in self._signals[name]:
+        for cb in self._signal_cbs[name]:
             LOGGER.debug("CB for sig %s: %s" % (name, cb))
             cb(self, userdata)
+
+    def _register_signaling_property(self, name):
+        LOGGER.debug("Registered new property '%s' for '%s'" % (name, self))
+        if "_%s" % name not in self.__dict__:
+            self.__dict__["_%s" % name] = None
+        self._register_signal("%s[change]" % name)
+
+    def _signaling_property(self, name, valid_value_cb, new_value):
+        if valid_value_cb():
+            self.emit_signal("%s[change]" % name, new_value)
+            self.__dict__["_%s" % name] = new_value
+        return self.__dict__["_%s" % name]
+
+class InputWidget(Widget):
+    signaling_properties = ["enabled"]
+
+    def enabled(self, is_enabled=None):
+        return self._signaling_property("enabled", \
+                                        lambda: is_enabled in [True, False],
+                                        is_enabled)
 
 
 class Label(Widget):
     """Represents a r/o label
     """
-    def __init__(self, label):
-        self.label = label
+    signaling_properties = ["text"]
 
+    def __init__(self, text):
+        self._text = text
+        super(Label, self).__init__()
+
+    def text(self, value=None):
+        return self._signaling_property("text", \
+                                        lambda: value != None,
+                                        value)
 
 class Header(Label):
     pass
 
 
-class Entry(Widget):
+class Entry(InputWidget):
     """Represents an entry field
     TODO multiline
     """
+
     def __init__(self, label, value=None, initial_value_from_model=True,
                  enabled=True):
         self.label = label
         self.value = value
         self.initial_value_from_model = initial_value_from_model
         self._enabled = enabled
+        super(Entry, self).__init__()
 
 
-class Password(Entry):
+class PasswordEntry(Entry):
     pass
 
 
diff --git a/scripts/tui/src/ovirt/node/plugins/example.py b/scripts/tui/src/ovirt/node/plugins/example.py
index fc4150b..fbb28a8 100644
--- a/scripts/tui/src/ovirt/node/plugins/example.py
+++ b/scripts/tui/src/ovirt/node/plugins/example.py
@@ -7,7 +7,7 @@
 
 import ovirt.node.plugins
 import ovirt.node.valid
-from ovirt.node.plugins import Header, Entry, Password
+from ovirt.node.plugins import Header, Entry, PasswordEntry
 
 LOGGER = logging.getLogger(__name__)
 
@@ -48,7 +48,7 @@
             ("foo.section", Header("Subsection")),
             ("foo.hostname", Entry(label="Hostname")),
             ("foo.port", Entry(label="Port")),
-            ("foo.password", Password(label="Password")),
+            ("foo.password", PasswordEntry(label="Password")),
         ]
         self._widgets = dict(widgets)
         return widgets
@@ -57,28 +57,29 @@
         """Applies the changes to the plugins model, will do all required logic
         """
         LOGGER.debug("checking %s" % changes)
-        if "foo.bar" in changes:
-            LOGGER.debug("Found foo.bar")
+        if "foo.hostname" in changes:
+            LOGGER.debug("Found foo.hostname")
 
-            if "/" in changes["foo.bar"]:
+            if "/" in changes["foo.hostname"]:
                 raise ovirt.node.plugins.InvalidData("No slash allowed")
 
-            if len(changes["foo.bar"]) < 5:
+            if len(changes["foo.hostname"]) < 5:
                 raise ovirt.node.plugins.Concern("Should be at least 5 chars")
 
             self._model.update(changes)
 
-            if "dis" in changes["foo.bar"]:
-                self._widgets["foo.bar2"].enabled(False)
+            if "dis" in changes["foo.hostname"]:
+                self._widgets["foo.port"].enabled(False)
                 LOGGER.debug("change to dis")
+                self._widgets["foo.section"].text(changes["foo.hostname"])
                 #raise ovirt.node.plugins.ContentRefreshRequest()
             else:
-                self._widgets["foo.bar2"].enabled(True)
+                self._widgets["foo.port"].enabled(True)
 
-        if "foo.bar2" in changes:
-            LOGGER.debug("Found foo.bar2")
+        if "foo.port" in changes:
+            LOGGER.debug("Found foo.port")
 
-            if "/" in changes["foo.bar2"]:
+            if "/" in changes["foo.port"]:
                 raise ovirt.node.plugins.InvalidData("No slashes allowed")
 
         return True
diff --git a/scripts/tui/src/ovirt/node/tui.py b/scripts/tui/src/ovirt/node/tui.py
index c412f2e..6ac711c 100644
--- a/scripts/tui/src/ovirt/node/tui.py
+++ b/scripts/tui/src/ovirt/node/tui.py
@@ -3,90 +3,18 @@
 import urwid
 
 import logging
-import os
 
 import ovirt.node
+import ovirt.node.widgets
 import ovirt.node.plugins
+import ovirt.node.utils
 
-
-logging.basicConfig(level=logging.DEBUG,
-                    filename="app.log", filemode="w")
 LOGGER = logging.getLogger(__name__)
 
 
-class SelectableText(urwid.Text):
-    """A Text widget that can be selected to be highlighted
-    """
-    def selectable(self):
-        return True
-
-    def keypress(self, size, key):
-        return key
-
-
-class PluginMenuEntry(urwid.AttrMap):
-    """An entry in the main menu
-    """
-    __text = None
-
-    def __init__(self, title, plugin):
-        self.__text = SelectableText(title)
-        self.__text.plugin = plugin
-        super(PluginMenuEntry, self).__init__(self.__text, 'menu.entry',
-                                              'menu.entry:focus')
-
-
-class PluginMenu(urwid.WidgetWrap):
-    """The main menu listing all available plugins (which have a UI)
-    """
-    __pages = None
-    __walker = None
-    __list = None
-    __list_attrmap = None
-    __linebox = None
-    __linebox_attrmap = None
-
-    signals = ['changed']
-
-    def __init__(self, pages):
-        self.__pages = pages
-        self.__build_walker()
-        self.__build_list()
-        self.__build_linebox()
-        super(PluginMenu, self).__init__(self.__linebox_attrmap)
-
-    def __build_walker(self):
-        items = []
-        for title, plugin in self.__pages.items():
-            if plugin.has_ui():
-                item = PluginMenuEntry(title, plugin)
-                items.append(item)
-            else:
-                LOGGER.warning("No UI page for plugin %s" % plugin)
-        self.__walker = urwid.SimpleListWalker(items)
-
-    def __build_list(self):
-        self.__list = urwid.ListBox(self.__walker)
-
-        def __on_item_change():
-            widget, position = self.__list.get_focus()
-            plugin = widget.original_widget.plugin
-            urwid.emit_signal(self, "changed", plugin)
-
-        urwid.connect_signal(self.__walker, 'modified', __on_item_change)
-
-        self.__list_attrmap = urwid.AttrMap(self.__list, "main.menu")
-
-    def __build_linebox(self):
-        self.__linebox = urwid.LineBox(self.__list_attrmap)
-        self.__linebox_attrmap = urwid.AttrMap(self.__linebox,
-                                               "main.menu.frame")
-
-    def set_focus(self, n):
-        self.__list.set_focus(n)
-
-
 class UrwidTUI(object):
+    app = None
+
     __pages = {}
     __hotkeys = {}
 
@@ -105,16 +33,17 @@
                ('main.menu.frame', 'light gray', ''),
                ('plugin.widget.entry', 'dark gray', ''),
                ('plugin.widget.entry.frame', 'light gray', ''),
-               ('plugin.widget.disabled', 'light gray', 'dark gray'),
+               ('plugin.widget.disabled', 'dark gray', 'light gray'),
                ('plugin.widget.notice', 'light red', ''),
                ('plugin.widget.header', 'light blue', 'light gray'),
                ]
 
-    def __init__(self):
-        pass
+    def __init__(self, app):
+        LOGGER.info("Creating urwid tui for '%s'" % app)
+        self.app = app
 
     def __build_menu(self):
-        self.__menu = PluginMenu(self.__pages)
+        self.__menu = ovirt.node.widgets.PluginMenu(self.__pages)
 
         def menu_item_changed(plugin):
             self.__change_to_page(plugin)
@@ -132,78 +61,58 @@
         return urwid.Frame(body, header, footer)
 
     def __build_widget_for_item(self, plugin, path, item):
+        item_to_widget_map = {
+            ovirt.node.plugins.Label: ovirt.node.widgets.Label,
+            ovirt.node.plugins.Header: ovirt.node.widgets.Header,
+            ovirt.node.plugins.Entry: ovirt.node.widgets.Entry,
+            ovirt.node.plugins.PasswordEntry: ovirt.node.widgets.PasswordEntry
+        }
+
+        assert type(item) in item_to_widget_map.keys(), \
+               "No widget for item type"
+
         widget = None
+        widget_class = item_to_widget_map[type(item)]
 
-        if type(item) is ovirt.node.plugins.Entry or \
-            type(item) is ovirt.node.plugins.Password:
-            label_text = urwid.Text("\n" + item.label + ":")
-            label = label_text
-            mask = None
-            if type(item) is ovirt.node.plugins.Password:
-                mask = "*"
-            edit = urwid.Edit(mask=mask)
-            edit_attrmap = urwid.AttrMap(edit, "plugin.widget.entry")
-            linebox = urwid.LineBox(edit_attrmap)
-            linebox_attrmap = urwid.AttrMap(linebox,
-                                            "plugin.widget.entry.frame")
-            entry = linebox_attrmap
-            main_widget = urwid.Columns([label, entry])
-
-            notice_text = urwid.Text("")
-            notice_attrmap = urwid.AttrMap(notice_text, "plugin.widget.notice")
-            notice_widget = notice_attrmap
-
-            widget = urwid.Pile([main_widget, notice_widget])
-
+        if type(item) in [ovirt.node.plugins.Entry, \
+                          ovirt.node.plugins.PasswordEntry]:
+            value = None
             if item.initial_value_from_model:
                 value = plugin.model()[path]
-                if value:
-                    edit.set_edit_text(value)
 
-            def on_change(widget, new_value):
-                LOGGER.debug("Widget content changed for path '%s'" % path)
+            widget = widget_class(item.label, value)
+
+            def on_item_enabled_change_cb(w, v):
+                LOGGER.debug("Model changed, updating widget '%s': %s" % (w, v))
+                if widget.selectable() != v:
+                    widget.enable(v)
+            item.connect_signal("enabled[change]", on_item_enabled_change_cb)
+
+            def on_widget_value_change(widget, new_value):
+                LOGGER.debug("Widget changed, updating model '%s'" % path)
 
                 try:
-                    if path in plugin.validators():
-                        msg = plugin.validators()[path](new_value)
-                        # True and None are allowed
-                        if msg not in [True, None]:
-                            raise ovirt.node.plugins.InvalidData(msg)
-
+                    plugin.validate(path, new_value)
                     plugin._on_ui_change({path: new_value})
-                    notice_text.set_text("")
+                    widget.notice = ""
 
                 except ovirt.node.plugins.Concern as e:
                     LOGGER.error("Concern when updating: %s" % e)
 
                 except ovirt.node.plugins.InvalidData as e:
-                    notice_text.set_text(e.message)
+                    widget.notice = e.message
                     LOGGER.error("Invalid data when updating: %s" % e)
+            urwid.connect_signal(widget, 'change', on_widget_value_change)
 
-            urwid.connect_signal(edit, 'change', on_change)
+        elif type(item) in [ovirt.node.plugins.Header, \
+                            ovirt.node.plugins.Label]:
+            widget = widget_class(item.text())
 
-            def foo(w, v):
-                if edit.selectable() == v:
-                    return True
-                else:
-                    edit.selectable = lambda: v
-                    LOGGER.debug("dissing")
-                    if v:
-                        edit_attrmap.set_attr_map({None: ""})
-                    else:
-                        edit_attrmap.set_attr_map({
-                            None: "plugin.widget.disabled"
-                            })
-            item.connect_signal("enabled[change]", foo)
-
-        elif type(item) is ovirt.node.plugins.Header:
-            label = urwid.Text("\n  %s\n" % item.label)
-            label_attrmap = urwid.AttrMap(label, "plugin.widget.header")
-            widget = label_attrmap
-
-        elif type(item) is ovirt.node.plugins.Label:
-            label = urwid.Text(item.label)
-            widget = urwid.AttrMap(label, "plugin.widget.label")
+            def on_item_text_change_cb(w, v):
+                LOGGER.debug("Model changed, updating widget '%s': %s" % (w, v))
+#                widget.text(v)
+                self.popup("foo")
+            item.connect_signal("text[change]", on_item_text_change_cb)
 
         return widget
 
@@ -234,7 +143,15 @@
     def __filter_hotkeys(self, keys, raw):
         key = str(keys)
         LOGGER.debug("Keypress: %s" % key)
+        if type(self.__loop.widget) is ovirt.node.widgets.ModalDialog:
+            LOGGER.debug("Modal dialog escape: %s" % key)
+            dialog = self.__loop.widget
+            if dialog.escape_key in keys:
+                self.__loop.widget = dialog.previous_widget
+            return
+
         if key in self.__hotkeys.keys():
+            LOGGER.debug("Running hotkeys: %s" % key)
             self.__hotkeys[key]()
         return keys
 
@@ -245,18 +162,9 @@
     def popup(self, msg=None, buttons=None):
         LOGGER.debug("Launching popup")
 
-        class Dialog(urwid.PopUpLauncher):
-
-            def create_pop_up(self):
-                return urwid.Filler(urwid.Text("Fooo"))
-
-            def get_pop_up_parameters(self):
-                return {'left': 0,
-                        'top': 1,
-                        'overlay_width': 30,
-                        'overlay_height': 4}
-        dialog = Dialog(self.__page_frame)
-        dialog.open_pop_up()
+        dialog = ovirt.node.widgets.ModalDialog(urwid.Filler(urwid.Text(msg)), "Title",
+                        "esc", self.__loop.widget)
+        self.__loop.widget = dialog
 
     def suspended(self):
         """Supspends the screen to do something in the foreground
@@ -300,34 +208,3 @@
                               self.palette,
                               input_filter=self.__filter_hotkeys)
         self.__loop.run()
-
-
-class App(object):
-    plugins = []
-
-    ui = None
-
-    def __init__(self, ui):
-        self.ui = ui
-
-    def __load_plugins(self):
-        self.plugins = [m.Plugin() for m in ovirt.node.plugins.load_all()]
-
-        for plugin in self.plugins:
-            LOGGER.debug("Adding plugin %s" % plugin)
-            self.ui.register_plugin(plugin.ui_name(), plugin)
-
-    def __drop_to_shell(self):
-        with self.ui.suspended():
-            os.system("reset ; bash")
-
-    def run(self):
-        self.__load_plugins()
-        self.ui.register_hotkey("f12", self.__drop_to_shell)
-        self.ui.footer = "Press ctrl+x or esc to quit."
-        self.ui.run()
-
-if __name__ == '__main__':
-    ui = UrwidTUI()
-    app = App(ui)
-    app.run()
diff --git a/scripts/tui/src/ovirt/node/utils.py b/scripts/tui/src/ovirt/node/utils.py
new file mode 100644
index 0000000..bd6b070
--- /dev/null
+++ b/scripts/tui/src/ovirt/node/utils.py
@@ -0,0 +1,57 @@
+"""
+Some convenience functions
+"""
+
+import subprocess
+import logging
+
+LOGGER = logging.getLogger(__name__)
+
+
+def popen_closefds(*args, **kwargs):
+    """subprocess.Popen wrapper to not leak file descriptors
+
+    Args:
+        cmd: Cmdline to be run
+
+    Returns:
+        Popen object
+    """
+    kwargs.update({
+        "close_fds": True
+    })
+    return subprocess.Popen(*args, **kwargs)
+
+
+def system(cmd):
+    """Run a non-interactive command, or where the user shall input something
+
+    Args:
+        cmd: Cmdline to be run
+
+    Returns:
+        retval of the process
+    """
+    return popen_closefds(cmd, shell=True).wait()
+
+
+def pipe(cmd, stdin=None):
+    """Run a command interactively and cath it's output.
+    This functions allows to pass smoe input to a running command.
+
+    Args:
+        cmd: Commandline to be run
+
+    Returns:
+        A tuple (success, stdout)
+    """
+
+    LOGGER.debug("run '%s'" % cmd)
+    system_cmd = popen_closefds(cmd, shell=True, stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+    stdout, stderr = system_cmd.communicate(stdin)
+    if stdout:
+        LOGGER.debug("out '%s'" % stdout)
+    if stderr:
+        LOGGER.warning("error '%s'" % stderr)
+    return (system_cmd.returncode == 0, stdout)
diff --git a/scripts/tui/src/ovirt/node/widgets.py b/scripts/tui/src/ovirt/node/widgets.py
new file mode 100644
index 0000000..471841d
--- /dev/null
+++ b/scripts/tui/src/ovirt/node/widgets.py
@@ -0,0 +1,190 @@
+"""
+Widgets for oVirt Node's urwid TUI
+"""
+import urwid
+import logging
+
+LOGGER = logging.getLogger(__name__)
+
+
+class SelectableText(urwid.Text):
+    """A Text widget that can be selected to be highlighted
+    """
+    def selectable(self):
+        return True
+
+    def keypress(self, size, key):
+        return key
+
+
+class PluginMenuEntry(urwid.AttrMap):
+    """An entry in the main menu
+    """
+    __text = None
+
+    def __init__(self, title, plugin):
+        self.__text = SelectableText(title)
+        self.__text.plugin = plugin
+        super(PluginMenuEntry, self).__init__(self.__text, 'menu.entry',
+                                              'menu.entry:focus')
+
+
+class PluginMenu(urwid.WidgetWrap):
+    """The main menu listing all available plugins (which have a UI)
+    """
+    __pages = None
+    __walker = None
+    __list = None
+    __list_attrmap = None
+    __linebox = None
+    __linebox_attrmap = None
+
+    signals = ['changed']
+
+    def __init__(self, pages):
+        self.__pages = pages
+        self.__build_walker()
+        self.__build_list()
+        self.__build_linebox()
+        super(PluginMenu, self).__init__(self.__linebox_attrmap)
+
+    def __build_walker(self):
+        items = []
+        for title, plugin in self.__pages.items():
+            if plugin.has_ui():
+                item = PluginMenuEntry(title, plugin)
+                items.append(item)
+            else:
+                LOGGER.warning("No UI page for plugin %s" % plugin)
+        self.__walker = urwid.SimpleListWalker(items)
+
+    def __build_list(self):
+        self.__list = urwid.ListBox(self.__walker)
+
+        def __on_item_change():
+            widget, position = self.__list.get_focus()
+            plugin = widget.original_widget.plugin
+            urwid.emit_signal(self, "changed", plugin)
+
+        urwid.connect_signal(self.__walker, 'modified', __on_item_change)
+
+        self.__list_attrmap = urwid.AttrMap(self.__list, "main.menu")
+
+    def __build_linebox(self):
+        self.__linebox = urwid.LineBox(self.__list_attrmap)
+        self.__linebox_attrmap = urwid.AttrMap(self.__linebox,
+                                               "main.menu.frame")
+
+    def set_focus(self, n):
+        self.__list.set_focus(n)
+
+
+class DialogBox(urwid.WidgetWrap):
+    def __init__(self, body, title, bodyattr=None, titleattr=None):
+        self.body = urwid.LineBox(body)
+        self.title = urwid.Text(title)
+        if titleattr is not None:
+            self.title = urwid.AttrMap(self.title, titleattr)
+        if bodyattr is not None:
+            self.body = urwid.AttrMap(self.body, bodyattr)
+
+        box = urwid.Overlay(self.title, self.body,
+                            align='center',
+                            valign='top',
+                            width=len(title),
+                            height=None,
+                            )
+        urwid.WidgetWrap.__init__(self, box)
+
+    def selectable(self):
+        return self.body.selectable()
+
+    def keypress(self, size, key):
+        return self.body.keypress(size, key)
+
+
+class ModalDialog(urwid.Overlay):
+    def __init__(self, body, title, escape_key, previous_widget, bodyattr=None,
+                 titleattr=None):
+        self.escape_key = escape_key
+        self.previous_widget = previous_widget
+
+        if type(body) in [str, unicode]:
+            body = urwid.Text(body)
+
+        box = DialogBox(body, title, bodyattr, titleattr)
+
+        super(ModalDialog, self).__init__(box, previous_widget, 'center',
+                                          ('relative', 70), 'middle',
+                                          ('relative', 70))
+
+
+class Label(urwid.WidgetWrap):
+    """A read only widget representing a label
+    """
+
+    def __init__(self, text):
+        self._label = urwid.Text(text)
+        self._label_attrmap = urwid.AttrMap(self._label,
+                                            "plugin.widget.label")
+        super(Label, self).__init__(self._label_attrmap)
+
+    def text(self, value=None):
+        if value != None:
+            self._label.set_text(value)
+        return self._label.get_text()
+
+class Header(Label):
+    """A read only widget representing a header
+    """
+
+    def __init__(self, text):
+        super(Header, self).__init__("\n  %s\n" % text)
+        self._label_attrmap.set_attr_map({None: "plugin.widget.header"})
+
+
+class Entry(urwid.WidgetWrap):
+
+    signals = ['change']
+
+    notice = property(lambda self: self._notice.get_text(), \
+                      lambda self, v: self._notice.set_text(v))
+
+    selectable = lambda self: True
+
+    def enable(self, is_enabled):
+        self.selectable = lambda: is_enabled
+        if is_enabled:
+            self._edit_attrmap.set_attr_map({None: ""})
+        else:
+            self._edit_attrmap.set_attr_map({
+                None: "plugin.widget.disabled"
+                })
+
+    def __init__(self, label, value=None, mask=None):
+        self._label = urwid.Text("\n" + label + ":")
+        self._edit = urwid.Edit(mask=mask)
+        self._edit_attrmap = urwid.AttrMap(self._edit, "plugin.widget.entry")
+        self._linebox = urwid.LineBox(self._edit_attrmap)
+        self._linebox_attrmap = urwid.AttrMap(self._linebox,
+                                              "plugin.widget.entry.frame")
+        self._columns = urwid.Columns([self._label, self._linebox_attrmap])
+
+        self._notice = urwid.Text("")
+        self._notice_attrmap = urwid.AttrMap(self._notice,
+                                             "plugin.widget.notice")
+
+        self._pile = urwid.Pile([self._columns, self._notice_attrmap])
+
+        if value:
+            self._edit.set_edit_text(value)
+
+        def on_widget_change_cb(widget, new_value):
+            urwid.emit_signal(self, 'change', self, new_value)
+        urwid.connect_signal(self._edit, 'change', on_widget_change_cb)
+
+        super(Entry, self).__init__(self._pile)
+
+class PasswordEntry(Entry):
+    def __init__(self, label, value=None):
+        super(PasswordEntry, self).__init__(label, value, mask="*")


--
To view, visit http://gerrit.ovirt.org/9867
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibe9d524ab38b006e2bc3f521fa560288a19f0f95
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Fabian Deutsch <fabiand at fedoraproject.org>



More information about the node-patches mailing list