core (XMLUI): Dialogs are now managemed in XMLUI:

- currents dialogs are available:
        - Message: a classical informational/error message, usually a popup that user has to close after reading
        - Note: more discreet message, usually a notification with a timeout (user don't need to close manually)
        - Confirm: a Ok/Cancel or Yes/No dialog
        - File: a dialog to get a file or dir path
    - dialog_opt parameter is used to customise dialogs
    - submit_id is used in a similar way as for forms
This commit is contained in:
Goffi 2014-08-11 19:10:24 +02:00
commit 38efb8b0bd

View file

@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from sat.core.i18n import _
from sat.core.constants import Const as C
from sat.core.log import getLogger
log = getLogger(__name__)
from xml.dom import minidom, NotFoundErr
@ -740,8 +741,8 @@ class ListWidget(InputWidget):
@param xmlui
@param options (list[string, tuple]): each option can be given as:
- a string if the label and the value are the same
- a couple if the label and the value differ
- a string if the label and the value are the same
- a couple if the label and the value differ
@param selected (list[string]): list of the selected values
@param style (string)
@param name (string)
@ -772,35 +773,108 @@ class ListWidget(InputWidget):
OptionElement(self, option, value in selected)
## Dialog Elements ##
class DialogElement(Element):
"""Main dialog element """
type = 'dialog'
def __init__(self, parent, type_, level=None):
if not isinstance(parent, TopElement):
raise exceptions.DataError(_("DialogElement must be a direct child of TopElement"))
super(DialogElement, self).__init__(parent.xmlui, parent)
self.elem.setAttribute(C.XMLUI_DATA_TYPE, type_)
self.elem.setAttribute(C.XMLUI_DATA_LVL, level or C.XMLUI_DATA_LVL_DEFAULT)
class MessageElement(Element):
"""Element with the instruction message"""
type = C.XMLUI_DATA_MESS
def __init__(self, parent, message):
if not isinstance(parent, DialogElement):
raise exceptions.DataError(_("MessageElement must be a direct child of DialogElement"))
super(MessageElement, self).__init__(parent.xmlui, parent)
message_txt = self.xmlui.doc.createTextNode(message)
self.elem.appendChild(message_txt)
class ButtonsElement(Element):
"""Buttons element which indicate which set to use"""
type = 'buttons'
def __init__(self, parent, set_):
if not isinstance(parent, DialogElement):
raise exceptions.DataError(_("ButtonsElement must be a direct child of DialogElement"))
super(ButtonsElement, self).__init__(parent.xmlui, parent)
self.elem.setAttribute('set', set_)
class FileElement(Element):
"""File element used for FileDialog"""
type = 'file'
def __init__(self, parent, type_):
if not isinstance(parent, DialogElement):
raise exceptions.DataError(_("FileElement must be a direct child of DialogElement"))
super(FileElement, self).__init__(parent.xmlui, parent)
self.elem.setAttribute('type', type_)
## XMLUI main class
class XMLUI(object):
"""This class is used to create a user interface (form/window/parameters/etc) using SàT XML"""
def __init__(self, panel_type="window", container="vertical", title=None, submit_id=None, session_id=None):
def __init__(self, panel_type="window", container="vertical", dialog_opt=None, title=None, submit_id=None, session_id=None):
"""Init SàT XML Panel
@param panel_type: one of
- window (new window)
- popup
- form (formulaire, depend of the frontend, usually a panel with cancel/submit buttons)
- param (parameters, presentation depend of the frontend)
- C.XMLUI_WINDOW (new window)
- C.XMLUI_POPUP
- C.XMLUI_FORM (formulaire, depend of the frontend, usually a panel with cancel/submit buttons)
- C.XMLUI_PARAM (parameters, presentation depend of the frontend)
- C.XMLUI_DIALOG (one common dialog, presentation depend of frontend)
@param container: disposition of elements, one of:
- vertical: elements are disposed up to bottom
- horizontal: elements are disposed left to right
- pairs: elements come on two aligned columns
(usually one for a label, the next for the element)
- tabs: elemens are in categories with tabs (notebook)
@param dialog_opt: only used if panel_type == C.XMLUI_DIALOG. Dictionnary (string/string) where key can be:
- C.XMLUI_DATA_TYPE: type of dialog, value can be:
- C.XMLUI_DIALOG_MESSAGE (default): an information/error message. Action of user is necessary to close the dialog. Usually the frontend display a classic popup
- C.XMLUI_DIALOG_NOTE: like a C.XMLUI_DIALOG_MESSAGE, but action of user is not necessary to close, at frontend choice (it can be closed after a timeout). Usually the frontend display as a timed out notification
- C.XMLUI_DIALOG_CONFIRM: dialog with 2 choices (usualy "Ok"/"Cancel").
returned data can contain:
- "answer": "true" if answer is "ok", "yes" or equivalent, "false" else
- C.XLMUI_DIALOG_FILE: a file selection dialog
returned data can contain:
- "cancelled": "true" if dialog has been cancelled, not present or "false" else
- "path": path of the choosed file/dir
- C.XMLUI_DATA_MESS: message shown in dialog
- C.XMLUI_DATA_LVL: one of:
- C.XMLUI_DATA_LVL_INFO (default): normal message
- C.XMLUI_DATA_LVL_WARNING: attention of user is important
- C.XMLUI_DATA_LVL_ERROR: something went wrong
- C.XMLUI_DATA_BTNS_SET: one of:
- C.XMLUI_DATA_BTNS_SET_OKCANCEL (default): classical "OK" and "Cancel" set
- C.XMLUI_DATA_BTNS_SET_YESNO: a translated "yes" for OK, and "no" for Cancel
@param title: title or default if None
@param submit_id: callback id to call for panel_type we can submit (form, param)
@param submit_id: callback id to call for panel_type we can submit (form, param, dialog)
@param session_id: use to keep a session attached to the dialog, must be returned by frontends
"""
self._introspect()
if panel_type not in ['window', 'form', 'param', 'popup']:
if panel_type not in [C.XMLUI_WINDOW, C.XMLUI_FORM, C.XMLUI_PARAM, C.XMLUI_POPUP, C.XMLUI_DIALOG]:
raise exceptions.DataError(_("Unknown panel type [%s]") % panel_type)
if panel_type == 'form' and submit_id is None:
if panel_type == C.XMLUI_FORM and submit_id is None:
raise exceptions.DataError(_("form XMLUI need a submit_id"))
if not isinstance(container, basestring):
raise exceptions.DataError(_("container argument must be a string"))
if dialog_opt is not None and panel_type != C.XMLUI_DIALOG:
raise exceptions.DataError(_("dialog_opt can only be used with dialog panels"))
self.type = panel_type
impl = minidom.getDOMImplementation()
@ -811,6 +885,11 @@ class XMLUI(object):
top_element.setAttribute("title", title)
self.submit_id = submit_id
self.session_id = session_id
if panel_type == C.XMLUI_DIALOG:
if dialog_opt is None:
dialog_opt = {}
self._createDialog(dialog_opt)
return
self.main_container = self._createContainer(container, TopElement(self))
self.current_container = self.main_container
@ -836,6 +915,8 @@ class XMLUI(object):
def __getattr__(self, name):
if name.startswith("add") and name not in ('addWidget',): # addWidgetName(...) create an instance of WidgetName
if self.type == C.XMLUI_DIALOG:
raise exceptions.InternalError(_("addXXX can't be used with dialogs"))
class_name = name[3:]+"Widget"
if class_name in globals():
cls = globals()[class_name]
@ -886,6 +967,29 @@ class XMLUI(object):
else:
raise exceptions.DataError("session_id can't be empty")
def _createDialog(self, dialog_opt):
dialog_type = dialog_opt.setdefault(C.XMLUI_DATA_TYPE, C.XMLUI_DIALOG_MESSAGE)
if dialog_type in [C.XMLUI_DIALOG_CONFIRM, C.XMLUI_DIALOG_FILE] and self.submit_id is None:
raise exceptions.InternalError(_("Submit ID must be filled for this kind of dialog"))
top_element = TopElement(self)
level = dialog_opt.get(C.XMLUI_DATA_LVL)
dialog_elt = DialogElement(top_element, dialog_type, level)
try:
MessageElement(dialog_elt, dialog_opt[C.XMLUI_DATA_MESS])
except KeyError:
pass
try:
ButtonsElement(dialog_elt, dialog_opt[C.XMLUI_DATA_BTNS_SET])
except KeyError:
pass
try:
FileElement(dialog_elt, dialog_opt[C.XMLUI_DATA_FILETYPE])
except KeyError:
pass
def _createContainer(self, container, parent=None, **kwargs):
"""Create a container element
@param type: container type (cf init doc)