Esempio n. 1
0
    def __init__(self, size = (800,600), position = (0,0), parent = None):
        '''
        :Parameters:
            ``size``: (int,int)
                Absolute size in pixels.

            ``position``:
                Absolute position in pixels.

            ``parent``: Figure or Window
                Parent Figure or Window
        '''

        EventDispatcher.__init__(self)
        self._size     = size
        self._position = position
        self._parent = parent
        self._figures  = []
        if parent is None:
            w,h = size[0], size[1]
            self._root = Window(width=int(w), height=int(h),
                                caption='Figure', visible=True)
            self._root.push_handlers(self)
            fig = Figure(size=(1.0,1.0), position=(0,0), parent = self)
            self._figures.append(fig)
Esempio n. 2
0
class Growth(object):
    EVENTS = ["ON_MAXED"]

    def __init__(self, target, params):
        self._target = target
        self._params = params
        self.volume = 0.0
        self.events = EventDispatcher(Growth.EVENTS, observer=target)

    def grow(self):
        params = self.current_params()
        if params.growth_volume == 0.0 or self.maxed_out():
            return

        self._target.consume_material(params.consumption_for_growth)
        self.volume += params.growth_volume
        if self.maxed_out():
            self.volume = params.max_volume
            self.events.trigger(self.events.ON_MAXED)

    def current_params(self):
        params = self._params.get(self._target.state(), None)
        if not params:
            params = self._params["default"]
        return params

    def maxed_out(self):
        return self.current_params().has_max_volume and self.volume >= self.current_params().max_volume
Esempio n. 3
0
class Growth(object):
    EVENTS = ['ON_MAXED']

    def __init__(self, target, params):
        self._target = target
        self._params = params
        self.volume = 0.0
        self.events = EventDispatcher(Growth.EVENTS, observer=target)

    def grow(self):
        params = self.current_params()
        if params.growth_volume == 0.0 or self.maxed_out(): return

        self._target.consume_material(params.consumption_for_growth)
        self.volume += params.growth_volume
        if self.maxed_out():
            self.volume = params.max_volume
            self.events.trigger(self.events.ON_MAXED)

    def current_params(self):
        params = self._params.get(self._target.state(), None)
        if not params: params = self._params['default']
        return params

    def maxed_out(self):
        return self.current_params(
        ).has_max_volume and self.volume >= self.current_params().max_volume
Esempio n. 4
0
    def __init__(self, notifier, *args, **kwargs):
        super(LoginInputField, self).__init__(*args, **kwargs)
        self.addClass("vi-login-input")
        self.sinkEvent("onKeyPress")

        self.onKeyPressEvent = EventDispatcher("keyPress")
        self.onKeyPressEvent.register(notifier)
Esempio n. 5
0
    def __init__(self, size=(800, 600), position=(0, 0), parent=None):
        '''
        :Parameters:
            ``size``: (int,int)
                Absolute size in pixels.

            ``position``:
                Absolute position in pixels.

            ``parent``: Figure or Window
                Parent Figure or Window
        '''

        EventDispatcher.__init__(self)
        self._size = size
        self._position = position
        self._parent = parent
        self._figures = []
        if parent is None:
            w, h = size[0], size[1]
            self._root = Window(width=int(w),
                                height=int(h),
                                caption='Figure',
                                visible=True)
            self._root.push_handlers(self)
            fig = Figure(size=(1.0, 1.0), position=(0, 0), parent=self)
            self._figures.append(fig)
Esempio n. 6
0
    def event(self, *args):
        '''Function decorator for an event handler.'''

        if self.parent is None:
            return EventDispatcher.event(self.root,*args)
        else:
            # If the event is 'on_idle', we attache it directly to the window
            if args[0] == 'on_idle' or args[0].__name__ == 'on_idle':
                self.root.push_handlers(*args)
            else:
                return EventDispatcher.event(self,*args)
Esempio n. 7
0
    def event(self, *args):
        '''Function decorator for an event handler.'''

        if self.parent is None:
            return EventDispatcher.event(self.root, *args)
        else:
            # If the event is 'on_idle', we attache it directly to the window
            if args[0] == 'on_idle' or args[0].__name__ == 'on_idle':
                self.root.push_handlers(*args)
            else:
                return EventDispatcher.event(self, *args)
Esempio n. 8
0
    def __init__(self,
                 module,
                 rootNode=None,
                 node=None,
                 isSelector=False,
                 *args,
                 **kwargs):
        """
			@param modul: Name of the modul we shall handle. Must be a list application!
			@type modul: string
			@param rootNode: The rootNode we shall display. If None, we try to select one.
			@type rootNode: String or None
			@param node: The node we shall display at start. Must be a child of rootNode
			@type node: String or None
		"""
        super(TreeWidget, self).__init__()
        self["class"].append("tree")
        self.module = module
        self.rootNode = rootNode
        self.node = node or rootNode
        self.actionBar = ActionBar(module, "tree")
        self.appendChild(self.actionBar)
        self.pathList = html5.Div()
        self.pathList["class"].append("breadcrumb")
        self.appendChild(self.pathList)
        self.entryFrame = SelectableDiv(self.nodeWidget, self.leafWidget)
        self.appendChild(self.entryFrame)
        self.entryFrame.selectionActivatedEvent.register(self)
        self._batchSize = 99
        self._currentCursor = {"node": None, "leaf": None}
        self._currentRequests = []
        self.rootNodeChangedEvent = EventDispatcher("rootNodeChanged")
        self.nodeChangedEvent = EventDispatcher("nodeChanged")
        self.isSelector = isSelector
        if self.rootNode:
            self.reloadData()
        else:
            NetworkService.request(self.module,
                                   "listRootNodes",
                                   successHandler=self.onSetDefaultRootNode)
        self.path = []
        self.sinkEvent("onClick")
        #Proxy some events and functions of the original table
        for f in [
                "selectionChangedEvent", "selectionActivatedEvent",
                "cursorMovedEvent", "getCurrentSelection",
                "selectionReturnEvent"
        ]:
            setattr(self, f, getattr(self.entryFrame, f))
        self.actionBar.setActions(self.defaultActions +
                                  (["select", "close"] if isSelector else []))
Esempio n. 9
0
    def __init__(self,
                 moduleName,
                 boneName,
                 readOnly,
                 isPlainText,
                 languages=None,
                 descrHint=None,
                 *args,
                 **kwargs):
        super(TextEditBone, self).__init__(*args, **kwargs)
        self.moduleName = moduleName
        self.boneName = boneName
        self.readOnly = readOnly
        self.selectedLang = False
        self.isPlainText = isPlainText
        self.languages = languages
        self.descrHint = descrHint
        self.value = {}

        # multilangbone
        if self.languages:
            if "currentlanguage" in conf and conf[
                    "currentlanguage"] in self.languages:
                self.selectedLang = conf["currentlanguage"]
            elif len(self.languages) > 0:
                self.selectedLang = self.languages[0]

            self.langButContainer = html5.Div()
            self.langButContainer["class"].append("languagebuttons")

            for lang in self.languages:
                abut = html5.ext.Button(lang, self.changeLang)
                abut["value"] = lang
                self.langButContainer.appendChild(abut)

            self.appendChild(self.langButContainer)
            self._refreshBtnStates()

        if not readOnly and not self.isPlainText:
            self.input = HtmlEditor()
            self.input.boneName = self.boneName
        else:
            self.input = html5.Textarea()
            if readOnly:
                self.input["readonly"] = True

        self.appendChild(self.input)

        self.sinkEvent("onKeyUp")

        self.changeEvent = EventDispatcher("boneChange")
Esempio n. 10
0
    def __init__(self, checkboxes=False, indexes=False, *args, **kwargs):
        super(SelectTable, self).__init__(*args, **kwargs)

        #Events
        self.selectionChangedEvent = EventDispatcher("selectionChanged")
        self.selectionActivatedEvent = EventDispatcher("selectionActivated")
        self.cursorMovedEvent = EventDispatcher("cursorMoved")
        self.tableChangedEvent = EventDispatcher("tableChanged")

        self.sinkEvent("onDblClick", "onMouseDown", "onMouseUp", "onKeyDown",
                       "onKeyUp", "onMouseOut", "onChange")

        self["tabindex"] = 1

        self._selectedRows = []  # List of row-indexes currently selected
        self._currentRow = None  # Rowindex of the cursor row
        self._isMouseDown = False  # Tracks status of the left mouse button
        self._isCtlPressed = False  # Tracks status of the ctrl key
        self._isShiftPressed = False  # Tracks status of the shift key
        self._ctlStartRow = None  # Stores the row where a multi-selection (using the ctrl key) started
        self._selectionChangedListener = [
        ]  # All objects getting informed when the selection changes
        self._selectionActivatedListeners = [
        ]  # All objects getting informed when items are selected
        self._cursorMovedListeners = [
        ]  # All objects getting informed when the cursor moves

        self.indexes = indexes
        self.indexes_col = 0 if indexes else -1

        self._checkboxes = {
        }  # The checkbox items per row (better to use a dict!)
        self.checkboxes = checkboxes
        self.checkboxes_col = (self.indexes_col + 1) if checkboxes else -1
Esempio n. 11
0
 def __init__(self, extension, view, module, *args, **kwargs):
     super(RelationalSearch, self).__init__(*args, **kwargs)
     self.view = view
     self.extension = extension
     self.module = module
     self.currentSelection = None
     self.filterChangedEvent = EventDispatcher("filterChanged")
     self.appendChild(html5.TextNode("RELATIONAL SEARCH"))
     self.appendChild(html5.TextNode(extension["name"]))
     self.currentEntry = html5.Span()
     self.appendChild(self.currentEntry)
     btn = html5.ext.Button("Select", self.openSelector)
     self.appendChild(btn)
     btn = html5.ext.Button("Clear", self.clearSelection)
     self.appendChild(btn)
Esempio n. 12
0
 def __init__(self, *args, **kwargs):
     super(Search, self).__init__(*args, **kwargs)
     self.startSearchEvent = EventDispatcher("startSearch")
     self["class"].append("search")
     lblSearch = html5.H2()
     lblSearch.appendChild(html5.TextNode(translate("Fulltext search")))
     self.appendChild(lblSearch)
     self.searchInput = html5.Input()
     self.searchInput["type"] = "text"
     self.appendChild(self.searchInput)
     self.btn = html5.ext.Button(translate("Search"),
                                 callback=self.doSearch)
     self.appendChild(self.btn)
     self.sinkEvent("onKeyDown")
     self.last_search = ""
Esempio n. 13
0
    def __init__(self, moduleName, boneName, readOnly, using, *args, **kwargs):
        super(RecordMultiBone, self).__init__(*args, **kwargs)

        self.addClass("recordbone", "recordbone-multi")

        self.moduleName = moduleName
        self.boneName = boneName
        self.readOnly = readOnly
        self.using = using

        self.changeEvent = EventDispatcher("boneChange")

        self.entries = []
        self.extendedErrorInformation = {}
        self.currentDrag = None
        self.currentOver = None

        self.itemsDiv = html5.Div()
        self.itemsDiv.addClass("recordbone-entries")
        self.appendChild(self.itemsDiv)

        self.addBtn = html5.ext.Button("Add", self.onAddBtnClick)
        self.addBtn.addClass("icon", "add")
        self.appendChild(self.addBtn)

        if self.readOnly:
            self["disabled"] = True

        self.sinkEvent("onDragOver")
Esempio n. 14
0
class ExtendedStringSearch(html5.Div):
    def __init__(self, extension, view, module, *args, **kwargs):
        super(ExtendedStringSearch, self).__init__(*args, **kwargs)
        self.view = view
        self.extension = extension
        self.module = module
        self.opMode = extension["mode"]
        self.filterChangedEvent = EventDispatcher("filterChanged")
        assert self.opMode in ["equals", "from", "to", "prefix", "range"]
        self.appendChild(html5.TextNode(extension["name"]))
        self.sinkEvent("onKeyDown")
        if self.opMode in ["equals", "from", "to", "prefix"]:
            self.input = html5.Input()
            self.input["type"] = "text"
            self.appendChild(self.input)
        elif self.opMode == "range":
            self.input1 = html5.Input()
            self.input1["type"] = "text"
            self.appendChild(self.input1)
            self.appendChild(html5.TextNode("to"))
            self.input2 = html5.Input()
            self.input2["type"] = "text"
            self.appendChild(self.input2)

    def onKeyDown(self, event):
        if html5.isReturn(event):
            self.filterChangedEvent.fire()

    def updateFilter(self, filter):
        if self.opMode == "equals":
            filter[self.extension["target"]] = self.input["value"]
        elif self.opMode == "from":
            filter[self.extension["target"] + "$gt"] = self.input["value"]
        elif self.opMode == "to":
            filter[self.extension["target"] + "$lt"] = self.input["value"]
        elif self.opMode == "prefix":
            filter[self.extension["target"] + "$lk"] = self.input["value"]
        elif self.opMode == "range":
            filter[self.extension["target"] + "$gt"] = self.input1["value"]
            filter[self.extension["target"] + "$lt"] = self.input2["value"]
        return (filter)

    @staticmethod
    def canHandleExtension(extension, view, module):
        return (isinstance(extension, dict) and "type" in extension.keys()
                and (extension["type"] == "string"
                     or extension["type"].startswith("string.")))
Esempio n. 15
0
class RelationalSearch(html5.Div):
    def __init__(self, extension, view, module, *args, **kwargs):
        super(RelationalSearch, self).__init__(*args, **kwargs)
        self.view = view
        self.extension = extension
        self.module = module
        self.currentSelection = None
        self.filterChangedEvent = EventDispatcher("filterChanged")
        self.appendChild(html5.TextNode("RELATIONAL SEARCH"))
        self.appendChild(html5.TextNode(extension["name"]))
        self.currentEntry = html5.Span()
        self.appendChild(self.currentEntry)
        btn = html5.ext.Button("Select", self.openSelector)
        self.appendChild(btn)
        btn = html5.ext.Button("Clear", self.clearSelection)
        self.appendChild(btn)

    def clearSelection(self, *args, **kwargs):
        self.currentSelection = None
        self.filterChangedEvent.fire()

    def openSelector(self, *args, **kwargs):
        currentSelector = ListWidget(self.extension["module"],
                                     selectMode="multi")
        currentSelector.selectionActivatedEvent.register(self)
        conf["mainWindow"].stackWidget(currentSelector)

    def onSelectionActivated(self, table, selection):
        self.currentSelection = selection
        self.filterChangedEvent.fire()

    def updateFilter(self, filter):
        if self.currentSelection:
            self.currentEntry.element.innerHTML = self.currentSelection[0][
                "name"]
            newId = self.currentSelection[0]["key"]
            filter[self.extension["target"] + ".key"] = newId
        else:
            self.currentEntry.element.innerHTML = ""
        return (filter)

    @staticmethod
    def canHandleExtension(extension, view, module):
        return (isinstance(extension, dict) and "type" in extension.keys()
                and (extension["type"] == "relational"
                     or extension["type"].startswith("relational.")))
Esempio n. 16
0
 def __init__(self,
              nodeWidget,
              leafWidget,
              selectionType="both",
              multiSelection=False,
              *args,
              **kwargs):
     super(SelectionContainer, self).__init__(*args, **kwargs)
     self["class"].append("selectioncontainer")
     self["tabindex"] = 1
     self.selectionType = selectionType
     self.multiSelection = multiSelection
     self.nodeWidget = nodeWidget
     self.leafWidget = leafWidget
     self.selectionChangedEvent = EventDispatcher("selectionChanged")
     self.selectionActivatedEvent = EventDispatcher(
         "selectionActivated"
     )  # Double-Click on an currently selected item - ITEM CLICKED !!!!
     self.selectionReturnEvent = EventDispatcher(
         "selectionReturn"
     )  # The current selection should be returned to parent widget
     self.cursorMovedEvent = EventDispatcher("cursorMoved")
     self._selectedItems = []  # List of row-indexes currently selected
     self._currentItem = None  # Rowindex of the cursor row
     self._isMouseDown = False  # Tracks status of the left mouse button
     self._isCtlPressed = False  # Tracks status of the ctrl key
     self._ctlStartRow = None  # Stores the row where a multi-selection (using the ctrl key) started
     self.sinkEvent("onClick", "onDblClick", "onMouseMove", "onMouseDown",
                    "onMouseUp", "onKeyDown", "onKeyUp")
Esempio n. 17
0
class Search(html5.Div):
    def __init__(self, *args, **kwargs):
        super(Search, self).__init__(*args, **kwargs)
        self.startSearchEvent = EventDispatcher("startSearch")
        self["class"].append("search")
        lblSearch = html5.H2()
        lblSearch.appendChild(html5.TextNode(translate("Fulltext search")))
        self.appendChild(lblSearch)
        self.searchInput = html5.Input()
        self.searchInput["type"] = "text"
        self.appendChild(self.searchInput)
        self.btn = html5.ext.Button(translate("Search"),
                                    callback=self.doSearch)
        self.appendChild(self.btn)
        self.sinkEvent("onKeyDown")
        self.last_search = ""

    def doSearch(self, *args, **kwargs):
        if self.searchInput["value"] != self.last_search:
            if len(self.searchInput["value"]):
                self.startSearchEvent.fire(self.searchInput["value"])
            else:
                self.resetSearch()

            self.last_search = self.searchInput["value"]

    def resetSearch(self):
        self.startSearchEvent.fire(None)

    def onKeyDown(self, event):
        if html5.isReturn(event):
            self.doSearch()
            event.preventDefault()
            event.stopPropagation()

    def resetLoadingState(self):
        if "is_loading" in self.btn["class"]:
            self.btn["class"].remove("is_loading")

    def reevaluate(self):
        self.doSearch()

    def focus(self):
        self.searchInput.focus()
Esempio n. 18
0
 def __init__(self, extension, view, modul, *args, **kwargs):
     super(ExtendedSelectMultiSearch, self).__init__(*args, **kwargs)
     self.view = view
     self.extension = extension
     self.module = modul
     self.filterChangedEvent = EventDispatcher("filterChanged")
     self.appendChild(html5.TextNode(extension["name"]))
     self.selectionCb = html5.Select()
     self.appendChild(self.selectionCb)
     o = html5.Option()
     o["value"] = ""
     o.appendChild(html5.TextNode(translate("Ignore")))
     self.selectionCb.appendChild(o)
     for k, v in extension["values"].items():
         o = html5.Option()
         o["value"] = k
         o.appendChild(html5.TextNode(v))
         self.selectionCb.appendChild(o)
     self.sinkEvent("onChange")
Esempio n. 19
0
class ExtendedSelectMultiSearch(html5.Div):
    def __init__(self, extension, view, modul, *args, **kwargs):
        super(ExtendedSelectMultiSearch, self).__init__(*args, **kwargs)
        self.view = view
        self.extension = extension
        self.module = modul
        self.filterChangedEvent = EventDispatcher("filterChanged")
        self.appendChild(html5.TextNode(extension["name"]))
        self.selectionCb = html5.Select()
        self.appendChild(self.selectionCb)
        o = html5.Option()
        o["value"] = ""
        o.appendChild(html5.TextNode(translate("Ignore")))
        self.selectionCb.appendChild(o)
        for k, v in extension["values"].items():
            o = html5.Option()
            o["value"] = k
            o.appendChild(html5.TextNode(v))
            self.selectionCb.appendChild(o)
        self.sinkEvent("onChange")

    def onChange(self, event):
        event.stopPropagation()
        self.filterChangedEvent.fire()

    def updateFilter(self, filter):
        val = self.selectionCb["options"].item(
            self.selectionCb["selectedIndex"]).value
        if not val:
            if self.extension["target"] in filter.keys():
                del filter[self.extension["target"]]
        else:
            filter[self.extension["target"]] = val
        return (filter)

    @staticmethod
    def canHandleExtension(extension, view, modul):
        return (isinstance(extension, dict) and "type" in extension.keys()
                and (((extension["type"] == "select"
                       or extension["type"].startswith("select."))
                      and extension.get("multiple", False)) or
                     (extension["type"] == "selectmulti"
                      or extension["type"].startswith("selectmulti."))))
Esempio n. 20
0
    def __init__(self, file, node, context=None, *args, **kwargs):
        """
			:param file: The file to upload
			:type file: A javascript "File" Object
			:param node: Key of the desired node of our parents tree application or None for an anonymous upload.
			:type node: str or None
		"""
        super(Uploader, self).__init__(*args, **kwargs)
        self.uploadSuccess = EventDispatcher("uploadSuccess")
        self.responseValue = None
        self.context = context
        # self.files = files
        r = NetworkService.request("file",
                                   "getUploadURL",
                                   successHandler=self.onUploadUrlAvailable,
                                   secure=True)
        r.file = file
        r.node = node
        conf["mainWindow"].log("progress", self)
        self.parent()["class"].append("is_uploading")
Esempio n. 21
0
    def __init__(self, extension, view, module, *args, **kwargs):
        super(DateRangeFilterPlugin, self).__init__(*args, **kwargs)
        self.view = view
        self.extension = extension
        self.module = module
        self.mutualExclusiveGroupTarget = "daterange-filter"
        self.mutualExclusiveGroupKey = extension["target"]
        self.filterChangedEvent = EventDispatcher("filterChanged")
        title = html5.H2()
        title.appendChild(html5.TextNode(extension["name"]))
        self.appendChild(title)

        # from daterange value
        self.beginDatepicker = html5.Input()
        self.beginDatepicker["type"] = "date"
        self.beginDatepicker["id"] = "begin-date-%s" % self.extension["target"]
        self.beginDatepicker["class"] = "js-extended-date-range-filter"
        beginLabel = html5.Label(translate("Begin date"))
        beginLabel["for"] = "begin-date-%s" % self.extension["target"]
        span = html5.Span()
        span.appendChild(beginLabel)
        span.appendChild(self.beginDatepicker)
        self.appendChild(span)

        # to daterange value
        self.toDatepicker = html5.Input()
        self.toDatepicker["type"] = "date"
        self.toDatepicker["id"] = "to-date-%s" % self.extension["target"]
        self.toDatepicker[
            "class"] = "extended-date-range-filter %s" % self.extension[
                "target"]
        toLabel = html5.Label(translate("End date"))
        toLabel["for"] = "to-date-%s" % self.extension["target"]
        span2 = html5.Span()
        span2.appendChild(toLabel)
        span2.appendChild(self.toDatepicker)
        self.appendChild(span2)
        self.clearButton = html5.ext.Button(translate("Clear filter"),
                                            self.clearFilter)
        self.appendChild(self.clearButton)
        self.sinkEvent("onChange")
Esempio n. 22
0
    def __init__(self, _loadOnDisplay=False, *args, **kwargs):
        super(DataTable, self).__init__()
        self.table = SelectTable(*args, **kwargs)
        self.appendChild(self.table)

        self._loadOnDisplay = _loadOnDisplay  # Load all data content continuously when displaying

        self._model = []  # List of values we are displaying right now
        self._shownFields = []  # List of keys we display from the model
        self._modelIdx = 0  # Internal counter to distinguish between 2 rows with identical data
        self._isAjaxLoading = False  # Determines if we already requested the next batch of rows
        self._dataProvider = None  # Which object to call if we need more data
        self._cellRender = {}  # Map of renders for a given field

        # We re-emit some events with custom parameters
        self.selectionChangedEvent = EventDispatcher("selectionChanged")
        self.selectionActivatedEvent = EventDispatcher("selectionActivated")
        self.tableChangedEvent = EventDispatcher("tableChanged")

        self.table.selectionChangedEvent.register(self)
        self.table.selectionActivatedEvent.register(self)
        self.table.tableChangedEvent.register(self)

        #Proxy some events and functions of the original table
        for f in ["cursorMovedEvent", "setHeader"]:
            setattr(self, f, getattr(self.table, f))

        self.cursorMovedEvent.register(self)
        self["style"]["overflow"] = "scroll"
        self.recalcHeight()
        self.sinkEvent("onScroll")
Esempio n. 23
0
 def __init__(self, extension, view, module, *args, **kwargs):
     super(ExtendedStringSearch, self).__init__(*args, **kwargs)
     self.view = view
     self.extension = extension
     self.module = module
     self.opMode = extension["mode"]
     self.filterChangedEvent = EventDispatcher("filterChanged")
     assert self.opMode in ["equals", "from", "to", "prefix", "range"]
     self.appendChild(html5.TextNode(extension["name"]))
     self.sinkEvent("onKeyDown")
     if self.opMode in ["equals", "from", "to", "prefix"]:
         self.input = html5.Input()
         self.input["type"] = "text"
         self.appendChild(self.input)
     elif self.opMode == "range":
         self.input1 = html5.Input()
         self.input1["type"] = "text"
         self.appendChild(self.input1)
         self.appendChild(html5.TextNode("to"))
         self.input2 = html5.Input()
         self.input2["type"] = "text"
         self.appendChild(self.input2)
Esempio n. 24
0
 def __init__(self, extension, view, module, *args, **kwargs):
     super(ExtendedBooleanSearch, self).__init__(*args, **kwargs)
     self.view = view
     self.extension = extension
     self.module = module
     self.filterChangedEvent = EventDispatcher("filterChanged")
     self.appendChild(html5.TextNode(extension["name"]))
     self.selectionCb = html5.Select()
     self.appendChild(self.selectionCb)
     o = html5.Option()
     o["value"] = ""
     o.appendChild(html5.TextNode(translate("Ignore")))
     self.selectionCb.appendChild(o)
     o = html5.Option()
     o["value"] = "0"
     o.appendChild(html5.TextNode(translate("No")))
     self.selectionCb.appendChild(o)
     o = html5.Option()
     o["value"] = "1"
     o.appendChild(html5.TextNode(translate("Yes")))
     self.selectionCb.appendChild(o)
     self.sinkEvent("onChange")
Esempio n. 25
0
class System:
    _dispatcher = EventDispatcher()

    def __init__(self):
        self._entity = Entity.next()

    def on(self, event, handler):
        self._dispatcher.on(event, self.entity, handler)

    def emit(self, event_type, target, **kwargs):
        self._dispatcher.emit(event_type, target, self.entity, **kwargs)

    @property
    def entity(self):
        return self._entity
Esempio n. 26
0
    def __init__(self, moduleName, boneName, using, readOnly, required, *args,
                 **kwargs):
        super(RecordSingleBone, self).__init__(*args, **kwargs)

        self.addClass("recordbone", "recordbone-single")

        self.moduleName = moduleName
        self.boneName = boneName
        self.readOnly = readOnly
        self.required = required
        self.using = using

        self.mask = None

        self.changeEvent = EventDispatcher("boneChange")

        if self.readOnly:
            self["disabled"] = True
Esempio n. 27
0
    def __init__(self,
                 module,
                 rootNode=None,
                 isSelector=False,
                 context=None,
                 *args,
                 **kwargs):
        """
			@param module: Name of the modul we shall handle. Must be a hierarchy application!
			@type module: string
			@param rootNode: The repository we shall display. If none, we try to select one.
			@type rootNode: String or None
		"""
        super(HierarchyWidget, self).__init__()
        self.module = module
        self.rootNode = rootNode
        self.actionBar = ActionBar(module, "hierarchy")
        self.appendChild(self.actionBar)
        self.entryFrame = html5.Ol()
        self.entryFrame["class"].append("hierarchy")
        self.appendChild(self.entryFrame)
        self.selectionChangedEvent = EventDispatcher("selectionChanged")
        self.selectionActivatedEvent = EventDispatcher("selectionActivated")
        self.rootNodeChangedEvent = EventDispatcher("rootNodeChanged")
        self._currentCursor = None
        self._currentRequests = []
        self.addClass("supports_drop")
        self.isSelector = isSelector
        self._expandedNodes = []
        self.context = context

        if self.rootNode:
            self.reloadData()
        else:
            NetworkService.request(self.module,
                                   "listRootNodes",
                                   self.context or {},
                                   successHandler=self.onSetDefaultRootNode,
                                   failureHandler=self.showErrorMsg)

        self.path = []
        self.sinkEvent("onClick", "onDblClick")

        ##Proxy some events and functions of the original table
        #for f in ["selectionChangedEvent","selectionActivatedEvent","cursorMovedEvent","getCurrentSelection"]:
        #	setattr( self, f, getattr(self.table,f))
        self.actionBar.setActions(
            ["selectrootnode", "add", "edit", "clone", "delete"] +
            (["select", "close"] if isSelector else []) + ["reload"])
        self.sinkEvent("onDrop", "onDragOver")
Esempio n. 28
0
class Uploader(html5.Progress):
    """
		Uploads a file to the server while providing visual feedback of the progress.
	"""
    def __init__(self, file, node, context=None, *args, **kwargs):
        """
			:param file: The file to upload
			:type file: A javascript "File" Object
			:param node: Key of the desired node of our parents tree application or None for an anonymous upload.
			:type node: str or None
		"""
        super(Uploader, self).__init__(*args, **kwargs)
        self.uploadSuccess = EventDispatcher("uploadSuccess")
        self.responseValue = None
        self.context = context
        # self.files = files
        r = NetworkService.request("file",
                                   "getUploadURL",
                                   successHandler=self.onUploadUrlAvailable,
                                   secure=True)
        r.file = file
        r.node = node
        conf["mainWindow"].log("progress", self)
        self.parent()["class"].append("is_uploading")

    def onUploadUrlAvailable(self, req):
        """
			Internal callback - the actual upload url (retrieved by calling /file/getUploadURL) is known.
		"""
        r = NetworkService.request("",
                                   "/admin/skey",
                                   successHandler=self.onSkeyAvailable)
        r.file = req.file
        r.node = req.node
        r.destUrl = req.result

    def onSkeyAvailable(self, req):
        """
			Internal callback - the Security-Key is known.
		"""
        formData = eval("new FormData();")
        formData.append("file", req.file)

        if self.context:
            for k, v in self.context.items():
                formData.append(k, v)

        if req.node and str(req.node) != "null":
            formData.append("node", req.node)

        formData.append("skey", NetworkService.decode(req))
        self.xhr = eval("new XMLHttpRequest()")
        self.xhr.open("POST", req.destUrl)
        self.xhr.onload = self.onLoad
        self.xhr.upload.onprogress = self.onProgress
        self.xhr.send(formData)

    def onLoad(self, *args, **kwargs):
        """
			Internal callback - The state of our upload changed.
		"""
        if self.xhr.status == 200:
            self.responseValue = json.loads(self.xhr.responseText)
            DeferredCall(self.onSuccess, _delay=1000)
        else:
            DeferredCall(self.onFailed, self.xhr.status, _delay=1000)

    def onProgress(self, event):
        """
			Internal callback - further bytes have been transmitted
		"""
        if event.lengthComputable:
            complete = int(event.loaded / event.total * 100)
            self["value"] = complete
            self["max"] = 100

    def onSuccess(self, *args, **kwargs):
        """
			Internal callback - The upload succeeded.
		"""
        for v in self.responseValue["values"]:
            self.uploadSuccess.fire(self, v)

        NetworkService.notifyChange("file")
        self.replaceWithMessage("Upload complete", isSuccess=True)

    def onFailed(self, errorCode, *args, **kwargs):
        self.replaceWithMessage("Upload failed with status code %s" %
                                errorCode,
                                isSuccess=False)

    def replaceWithMessage(self, message, isSuccess):
        self.parent()["class"].remove("is_uploading")
        self.parent()["class"].remove("log_progress")
        if isSuccess:
            self.parent()["class"].append("log_success")
        else:
            self.parent()["class"].append("log_failed")
        msg = html5.Span()
        msg.appendChild(html5.TextNode(message))
        self.parent().appendChild(msg)
        self.parent().removeChild(self)
Esempio n. 29
0
class SelectTable(html5.Table):
    """
		Provides an Html-Table which allows for row selections.

		Parent widgets can register for certain events:

			- selectionChanged: called if the current _multi_ selection changes. (Ie the user
				holds ctrl and clicks a row). The selection might contain no, one or multiple rows.
				Its also called if the cursor moves. Its called if the user simply double
				clicks a row. So its possible to receive a selectionActivated event without an
				selectionChanged Event.
			- selectionActivated: called if a selection is activated, ie. a row is double-clicked or Return
			 	is pressed.
			- cursorMoved: called when the currently active row changes. The user can select the current row
				with a single click or by moving the cursor up and down using the arrow keys.
	"""
    def __init__(self, checkboxes=False, indexes=False, *args, **kwargs):
        super(SelectTable, self).__init__(*args, **kwargs)

        #Events
        self.selectionChangedEvent = EventDispatcher("selectionChanged")
        self.selectionActivatedEvent = EventDispatcher("selectionActivated")
        self.cursorMovedEvent = EventDispatcher("cursorMoved")
        self.tableChangedEvent = EventDispatcher("tableChanged")

        self.sinkEvent("onDblClick", "onMouseDown", "onMouseUp", "onKeyDown",
                       "onKeyUp", "onMouseOut", "onChange")

        self["tabindex"] = 1

        self._selectedRows = []  # List of row-indexes currently selected
        self._currentRow = None  # Rowindex of the cursor row
        self._isMouseDown = False  # Tracks status of the left mouse button
        self._isCtlPressed = False  # Tracks status of the ctrl key
        self._isShiftPressed = False  # Tracks status of the shift key
        self._ctlStartRow = None  # Stores the row where a multi-selection (using the ctrl key) started
        self._selectionChangedListener = [
        ]  # All objects getting informed when the selection changes
        self._selectionActivatedListeners = [
        ]  # All objects getting informed when items are selected
        self._cursorMovedListeners = [
        ]  # All objects getting informed when the cursor moves

        self.indexes = indexes
        self.indexes_col = 0 if indexes else -1

        self._checkboxes = {
        }  # The checkbox items per row (better to use a dict!)
        self.checkboxes = checkboxes
        self.checkboxes_col = (self.indexes_col + 1) if checkboxes else -1

    def onAttach(self):
        super(SelectTable, self).onAttach()
        self.focus()

    def setHeader(self, headers):
        """
			Sets the table-headers to 'headers'
			:param headers: list of strings
			:type headers: list
		"""

        tr = html5.Tr()

        # Extra column for Index#s
        if self.indexes:
            th = html5.Th()
            th["class"] = "index"
            tr.appendChild(th)

        # Extra column for checkboxes
        if self.checkboxes:
            th = html5.Th()  # fixme..
            th["class"] = "check"
            tr.appendChild(th)

        # Now every title column
        for head in headers:
            th = html5.Th()
            th.appendChild(html5.TextNode(head))
            tr.appendChild(th)

        self.head.removeAllChildren()
        self.head.appendChild(tr)

    def getTrByIndex(self, idx):
        """
			Retrieves the TR element by the given row number
			:param idx: Rownumber to retrieve the tr of
			:type idx: int
			:returns: HTMLTableRowElement
		"""
        for c in self.body._children:
            if idx <= 0:
                return c
            idx -= c["rowspan"]

        return None

    def getIndexByTr(self, tr):
        """
			Returns the rowNumber for the given tr element or None if
			the given tr element is invalid.
			:param tr: A HTMLTableRowElement of this table
			:type tr: HTMLTableRowElement
			:returns: int or None
		"""
        idx = 0
        for c in self.body._children:
            if c.element == tr:
                return (idx)
            idx += c["rowspan"]
        return (idx)

    def _rowForEvent(self, event):
        """
			Determines the row number for the given event
		"""
        try:
            # Chromium
            tc = event.srcElement
        except:
            # Firefox
            tc = event.target

        if tc is None:
            return (None)

        tr = tc.parentElement

        while (tr.parentElement is not None):
            if tr.parentElement == self.body.element:
                return (tr)
            tr = tr.parentElement

        return (None)

    def onChange(self, event):
        tr = self._rowForEvent(event)
        if tr is None:
            return

        row = self.getIndexByTr(tr)

        if self.checkboxes and html5.utils.doesEventHitWidgetOrChildren(
                event, self._checkboxes[row]):
            self._checkboxes[row]["checked"] = row in self._selectedRows

    def onMouseDown(self, event):
        tr = self._rowForEvent(event)
        if tr is None:
            return

        row = self.getIndexByTr(tr)

        if self._isCtlPressed:
            if row in self._selectedRows:
                for x in self._selectedRows:
                    self.getTrByIndex(x).removeClass(
                        "is_focused")  # remove focus
                self.removeSelectedRow(row)
            else:
                self.addSelectedRow(row)
                self.setCursorRow(row, False)  # set focus
            event.preventDefault()

        elif self._isShiftPressed:
            self.unSelectAll()
            for i in (range(self._ctlStartRow, row +
                            1) if self._ctlStartRow <= row else range(
                                row, self._ctlStartRow + 1)):
                self.addSelectedRow(i)
            self.setCursorRow(row, False)  # set focus
            event.preventDefault()

        elif self.checkboxes and html5.utils.doesEventHitWidgetOrChildren(
                event, self._checkboxes[row]):
            if row in self._selectedRows:
                self.removeSelectedRow(row)
            else:
                self.addSelectedRow(row)

        else:
            self._isMouseDown = True

            if self.checkboxes:
                if row in self._selectedRows:
                    self.removeSelectedRow(row)
                else:
                    self.addSelectedRow(row)

            self.setCursorRow(self.getIndexByTr(tr),
                              removeExistingSelection=not self.checkboxes)

        self.focus()

    def onMouseOut(self, event):
        self._isMouseDown = False

    def onMouseUp(self, event):
        self._isMouseDown = False

    def onKeyDown(self, event):
        if html5.isArrowDown(event):  # Arrow down

            if self._currentRow is None:
                self.setCursorRow(0)

            else:
                if self._isCtlPressed or self._isShiftPressed:

                    if self._ctlStartRow > self._currentRow:
                        self.removeSelectedRow(self._currentRow)
                    else:
                        self.addSelectedRow(self._currentRow)

                        if self._currentRow + 1 < self.getRowCount():
                            self.addSelectedRow(self._currentRow + 1)

                if self._currentRow + 1 < self.getRowCount():
                    self.setCursorRow(
                        self._currentRow + 1,
                        removeExistingSelection=(not self._isShiftPressed
                                                 and not self._isCtlPressed))

            event.preventDefault()

        elif html5.isArrowUp(event):  # Arrow up

            if self._currentRow is None:
                self.setCursorRow(0)
            else:

                if self._isCtlPressed or self._isShiftPressed:  # Check if we extend a selection
                    if self._ctlStartRow < self._currentRow:
                        self.removeSelectedRow(self._currentRow)
                    else:
                        self.addSelectedRow(self._currentRow)

                        if self._currentRow > 0:
                            self.addSelectedRow(self._currentRow - 1)

                if self._currentRow > 0:  # Move the cursor if possible
                    self.setCursorRow(
                        self._currentRow - 1,
                        removeExistingSelection=(not self._isShiftPressed
                                                 and not self._isCtlPressed))

            event.preventDefault()

        elif html5.isReturn(event):  # Return

            if len(self._selectedRows) > 0:
                self.selectionActivatedEvent.fire(self, self._selectedRows)
                event.preventDefault()
                return

            if self._currentRow is not None:
                self.selectionActivatedEvent.fire(self, [self._currentRow])
                event.preventDefault()
                return

        elif html5.isControl(event):  # Ctrl
            self._isCtlPressed = True
            self._ctlStartRow = self._currentRow or 0
            if self._currentRow is not None:
                self.addSelectedRow(
                    self._currentRow)  # add already selected row to selection

        elif html5.isShift(event):  # Shift
            self._isShiftPressed = True
            try:
                self._ctlStartRow = self._currentRow or self._selectedRows[
                    0] or 0
            except:
                self._ctlStartRow = 0

    def onKeyUp(self, event):
        if html5.isControl(event):
            self._isCtlPressed = False
            self._ctlStartRow = None

            # leave selection mode if there is only one row selected and return to normal focus
            if len(self._selectedRows) == 1:
                for row in self.getCurrentSelection():
                    self.removeSelectedRow(row)

        elif html5.isShift(event):
            self._isShiftPressed = False
            self._ctlStartRow = None

    def onDblClick(self, event):
        if self._currentRow is not None:
            self.selectionActivatedEvent.fire(self, [self._currentRow])
        event.preventDefault()

    def addSelectedRow(self, row):
        """
			Marks a row as selected
		"""
        if row in self._selectedRows:
            return

        self._selectedRows.append(row)

        tr = self.getTrByIndex(row)
        tr["class"].append("is_selected")

        if self.checkboxes:
            self._checkboxes[row]["checked"] = True

        self.selectionChangedEvent.fire(self, self.getCurrentSelection())

    def removeSelectedRow(self, row):
        """
			Removes 'row' from the current selection (if any)
			:param row: Number of the row to unselect
			:type row: int
		"""
        if not row in self._selectedRows:
            return

        self._selectedRows.remove(row)

        tr = self.getTrByIndex(row)
        tr["class"].remove("is_selected")

        if self.checkboxes:
            self._checkboxes[row]["checked"] = False

        self.selectionChangedEvent.fire(self, self.getCurrentSelection())

    def selectRow(self, newRow):
        """
			Sets the current selection to 'row'.
			Any previous selection is removed.
			:param newRow: Number of the row to select
			:type newRow: int
		"""
        self.setCursorRow(newRow)

        for row in self._selectedRows[:]:
            if row != newRow:
                self.removeSelectedRow(row)

        if not newRow in self._selectedRows:
            self._selectedRows.append(newRow)
            tr = self.getTrByIndex(newRow)
            tr["class"].append("is_selected")

        self.selectionChangedEvent.fire(self, self.getCurrentSelection())

    def setCursorRow(self, row, removeExistingSelection=True):
        """
			Move the cursor to row 'row'.
			If removeExistingSelection is True, the current selection (if any) is invalidated.
		"""
        if self._currentRow is not None:
            self.getTrByIndex(self._currentRow)["class"].remove("is_focused")

        self._currentRow = row
        if self._currentRow is not None:
            self.getTrByIndex(self._currentRow)["class"].append("is_focused")
            self.cursorMovedEvent.fire(self, row)

        if removeExistingSelection:
            for row in self._selectedRows[:]:
                self.removeSelectedRow(row)
            self.selectionChangedEvent.fire(self, self.getCurrentSelection())

        DeferredCall(self.focusRow, row)

    def focusRow(self, row):
        tr = self.getTrByIndex(row)
        # fixme: Re-implement maybe later?

    def getCurrentSelection(self):
        """
			Returns a list of currently selected row-numbers
			:returns: list
		"""
        if self._selectedRows:
            return self._selectedRows[:]
        elif self._currentRow is not None:
            return [self._currentRow]

        return None

    def clear(self):
        """
			Hook the clear() method so we can reset some internal states, too
		"""
        super(SelectTable, self).clear()
        self._currentRow = None
        self._selectedRows = []

        self.selectionChangedEvent.fire(self, self.getCurrentSelection())
        self.tableChangedEvent.fire(self, self.getRowCount())

    def removeRow(self, row):
        """
			Hook the removeRow method so we can reset some internal states, too
		"""
        if row in self._selectedRows:
            self._selectedRows.remove(row)
            self.selectionChangedEvent.fire(self)

        if self._currentRow == row:
            self._currentRow = None
            self.cursorMovedEvent.fire(self)

        self.tableChangedEvent.fire(self, self.getRowCount())
        super(SelectTable, self).removeRow(row)

    def _extraCols(self):
        return int(self.checkboxes) + int(self.indexes)

    def prepareCol(self, row, col):
        """
		Lets hook up the original removeRow function to optionally
		provide index and checkbox columns.
		"""
        super(SelectTable, self).prepareCol(row, col + self._extraCols() - 1)

        if self.checkboxes:
            checkbox = html5.Input()
            checkbox["type"] = "checkbox"
            checkbox["class"].append("check")
            checkbox["checked"] = False

            self["cell"][row][self.checkboxes_col] = checkbox
            self._checkboxes[row] = checkbox

        if self.indexes:
            lbl = html5.Label(str(row + 1))
            lbl["class"].append("index")
            self["cell"][row][self.indexes_col] = lbl

        self.tableChangedEvent.fire(self, self.getRowCount())

    def setCell(self, row, col, val):
        """
		Interface for self["cell"] that directs to the correct cell if extra columns are
		configured for this SelectTable.
		"""
        self["cell"][row][col + self._extraCols()] = val

    def selectAll(self):
        """
		Selects all entries of the table.
		"""
        self._selectedRows = range(0, self.getRowCount())

        for row in self._selectedRows:
            tr = self.getTrByIndex(row)

            if not "is_selected" in tr["class"]:
                tr["class"].append("is_selected")

            if self.checkboxes:
                self._checkboxes[row]["checked"] = True

        self.selectionChangedEvent.fire(self, self.getCurrentSelection())
        return len(self._selectedRows)

    def unSelectAll(self):
        """
		Unselects all entries of the table.
		"""
        unsel = len(self._selectedRows)

        for row in self._selectedRows:
            tr = self.getTrByIndex(row)
            tr["class"].remove("is_selected")

            if self.checkboxes:
                self._checkboxes[row]["checked"] = False

        self._selectedRows = []
        self.selectionChangedEvent.fire(self, self.getCurrentSelection())
        return unsel

    def invertSelection(self):
        """
		Inverts the current selection on the whole table currently displayed.
		"""
        current = self._selectedRows[:]
        self._selectedRows = []

        for row in range(0, self.getRowCount()):
            tr = self.getTrByIndex(row)

            if row in current:
                tr["class"].remove("is_selected")
            else:
                self._selectedRows.append(row)
                tr["class"].append("is_selected")

            if self.checkboxes:
                self._checkboxes[row]["checked"] = row in self._selectedRows

        self.selectionChangedEvent.fire(self, self.getCurrentSelection())
        return len(self._selectedRows), len(current)
Esempio n. 30
0
class DataTable(html5.Div):
    """
		Provides kind of MVC on top of SelectTable.
	"""
    def __init__(self, _loadOnDisplay=False, *args, **kwargs):
        super(DataTable, self).__init__()
        self.table = SelectTable(*args, **kwargs)
        self.appendChild(self.table)

        self._loadOnDisplay = _loadOnDisplay  # Load all data content continuously when displaying

        self._model = []  # List of values we are displaying right now
        self._shownFields = []  # List of keys we display from the model
        self._modelIdx = 0  # Internal counter to distinguish between 2 rows with identical data
        self._isAjaxLoading = False  # Determines if we already requested the next batch of rows
        self._dataProvider = None  # Which object to call if we need more data
        self._cellRender = {}  # Map of renders for a given field

        # We re-emit some events with custom parameters
        self.selectionChangedEvent = EventDispatcher("selectionChanged")
        self.selectionActivatedEvent = EventDispatcher("selectionActivated")
        self.tableChangedEvent = EventDispatcher("tableChanged")

        self.table.selectionChangedEvent.register(self)
        self.table.selectionActivatedEvent.register(self)
        self.table.tableChangedEvent.register(self)

        #Proxy some events and functions of the original table
        for f in ["cursorMovedEvent", "setHeader"]:
            setattr(self, f, getattr(self.table, f))

        self.cursorMovedEvent.register(self)
        self["style"]["overflow"] = "scroll"
        self.recalcHeight()
        self.sinkEvent("onScroll")

    def recalcHeight(self, *args, **kwargs):
        self["style"]["max-height"] = "%spx" % (
            int(eval("window.top.innerHeight")) - 280)

    def setDataProvider(self, obj):
        """
			Register's 'obj' as the provider for this table.
			It must provide a onNextBatchNeeded function, which must fetch and
			feed new rows using add() or reset the dataProvider to None if no more
			rows are available.
			Notice: If the bottom of the table is reached, onNextBatchNeeded will only be called once.
			No further calls will be made until add() or setDataProvider() has been called afterwards.
		"""
        assert obj==None or "onNextBatchNeeded" in dir(obj),\
         "The dataProvider must provide a 'onNextBatchNeeded' function"

        self._dataProvider = obj
        self._isAjaxLoading = False

        if "is_loading" in self.table["class"]:
            self.table["class"].remove("is_loading")

    def onCursorMoved(self, table, row):
        """
			Ensure the table scrolls according to the position of its cursor
		"""
        tr = table.getTrByIndex(row)
        if tr is None:
            return
        return  #FIXME
        if self.element.scrollTop > tr.offsetTop:
            self.element.scrollTop = tr.offsetTop
        elif self.element.scrollTop + self.element.clientHeight < tr.offsetTop:
            self.element.scrollTop = tr.offsetTop + tr.clientHeight - self.element.clientHeight

    def getRowCount(self):
        """
			Returns the total amount of rows currently known.
			:returns: int
		"""
        return (len(self._model))

    def add(self, obj):
        """
			Adds an row to the model
			:param obj: Dictionary of values for this row
			:type obj: dict
		"""
        obj["_uniqeIndex"] = self._modelIdx
        self._modelIdx += 1
        self._model.append(obj)
        self._renderObject(obj)
        self._isAjaxLoading = False
        if "is_loading" in self.table["class"]:
            self.table["class"].remove("is_loading")
        self.testIfNextBatchNeededImmediately()

    def extend(self, objList):
        """
			Adds multiple rows at once.
			Much faster than calling add() multiple times.
		"""
        self.table.prepareGrid(len(objList), len(self._shownFields))
        for obj in objList:
            obj["_uniqeIndex"] = self._modelIdx
            self._modelIdx += 1
            self._model.append(obj)
            self._renderObject(obj, tableIsPrepared=True)
            self._isAjaxLoading = False
            if "is_loading" in self.table["class"]:
                self.table["class"].remove("is_loading")
        self.testIfNextBatchNeededImmediately()

    def testIfNextBatchNeededImmediately(self):
        """
			Test if we display enough entries so that our contents are scrollable.
			Otherwise, we'll never request a second batch
		"""

        sumHeight = 0
        for c in self.table._children:
            if "clientHeight" in dir(c.element):
                sumHeight += c.element.clientHeight
        if not sumHeight:  # We'll get no height if not visible, so we'll append our self to the body for a moment
            parent = self.parent()
            parent.removeChild(self)
            html5.Body().appendChild(self)
            sumHeight = self.table.element.clientHeight
            html5.Body().removeChild(self)
            parent.appendChild(self)

        if (not self._isAjaxLoading and
            (self._loadOnDisplay
             or not sumHeight > int(self["style"]["max-height"][:-2]))):

            if self._dataProvider:
                self._isAjaxLoading = True
                if not "is_loading" in self.table["class"]:
                    self.table["class"].append("is_loading")
                self._dataProvider.onNextBatchNeeded()

    def remove(self, objOrIndex):
        """
			Removes 'obj' from the table.
			'obj' may be an row-index or an object recieved by any eventListener.
			It _cannot_ be any original object passed to 'add' - it _must_ be recived by an eventListener!
		"""
        if isinstance(objOrIndex, dict):
            assert objOrIndex in self._model, "Cannot remove unknown object from Table"
            objOrIndex = self._model.index(objOrIndex)
        if isinstance(objOrIndex, int):
            assert objOrIndex > 0 and objOrIndex < len(
                self._model), "Modelindex out of range"
            self._model.remove(self._model[objOrIndex])
            self.table.removeRow(objOrIndex)
        else:
            raise TypeError("Expected int or dict, got %s" %
                            str(type(objOrIndex)))

    def clear(self, keepModel=False):
        """
			Flushes the whole table.
		"""
        self.table.clear()
        if not keepModel:
            self._model = []

    def _renderObject(self, obj, tableIsPrepared=False):
        """
			Renders the object to into the table.
			Does nothing if the list of _shownFields is empty.
			:param obj: Dictionary of values for this row
			:type obj: dict
		"""
        if not self._shownFields:
            return

        rowIdx = self._model.index(obj)
        cellIdx = 0

        if not tableIsPrepared:
            self.table.prepareCol(rowIdx, len(self._shownFields) - 1)

        for field in self._shownFields:
            if field in self._cellRender.keys():
                lbl = self._cellRender[field].render(obj, field)
            elif field in obj.keys():
                lbl = html5.Label(obj[field])
            else:
                lbl = html5.Label("...")

            self.table.setCell(rowIdx, cellIdx, lbl)
            cellIdx += 1

    def rebuildTable(self):
        """
			Rebuilds the entire table.
			Useful if something fundamental changed (ie. the cell renderer or the list of visible fields)
		"""
        self.clear(keepModel=True)
        self.table.prepareGrid(len(self._model), len(self._shownFields))
        for obj in self._model:
            self._renderObject(obj, tableIsPrepared=True)

    def setShownFields(self, fields):
        """
			Sets the list of _shownFields.
			This causes the whole table to be rebuild.
			Be careful if calling this function often on a large table!
			:param fields: List of model-keys which will be displayed.
			:type fields: list
		"""
        self._shownFields = fields
        self.rebuildTable()

    def onScroll(self, event):
        """
			Check if we got a scroll event and need to fetch another set of rows from our dataProvider
		"""
        if self._loadOnDisplay:
            return

        self.recalcHeight()

        if ((self.element.scrollTop + self.element.clientHeight) >=
                self.element.scrollHeight and not self._isAjaxLoading):

            if self._dataProvider:

                self._isAjaxLoading = True
                if not "is_loading" in self.table["class"]:
                    self.table["class"].append("is_loading")

                self._dataProvider.onNextBatchNeeded()

    def onSelectionChanged(self, table, rows):
        """
			Re-emit the event. Maps row-numbers to actual models.
		"""
        vals = [self._model[x] for x in (rows or [])]
        self.selectionChangedEvent.fire(self, vals)

    def onSelectionActivated(self, table, rows):
        """
			Re-emit the event. Maps row-numbers to actual models.
		"""
        vals = [self._model[x] for x in rows]
        self.selectionActivatedEvent.fire(self, vals)

    def onTableChanged(self, table, rowCount):
        """
			Re-emit the event.
		"""
        self.tableChangedEvent.fire(self, rowCount)

    def getCurrentSelection(self):
        """
			Override the getCurrentSelection method to
			yield actual models, not row-numbers.
		"""
        rows = self.table.getCurrentSelection()
        if not self._model or not rows:
            return ([])
        return ([self._model[x] for x in rows])

    def setCellRender(self, field, render):
        """
			Sets the render for cells of 'field' to render.
			A cell render receives the data for a given cell and returns
			the appropriate widget to display that data for the table.
		"""
        if render is None:
            if field in self._cellRender.keys():
                del self._cellRender[field]
        else:
            assert "render" in dir(
                render), "The render must provide a 'render' method"
            self._cellRender[field] = render
        self.rebuildTable()

    def setCellRenders(self, renders):
        """
			Like setCellRender, but sets multiple renders at one.
			Much faster than calling setCellRender repeatedly.
		"""
        assert isinstance(renders, dict)
        for field, render in renders.items():
            if render is None:
                if field in self._cellRender.keys():
                    del self._cellRender[field]
            else:
                assert "render" in dir(
                    render), "The render must provide a 'render' method"
                self._cellRender[field] = render
        self.rebuildTable()

    def activateCurrentSelection(self):
        """
			Emits the selectionActivated event if there's currently a selection

		"""
        selection = self.getCurrentSelection()
        if len(selection) > 0:
            self.selectionActivatedEvent.fire(self, selection)
Esempio n. 31
0
 def __init__(self, target, params):
     self._target = target
     self._params = params
     self.volume = 0.0
     self.events = EventDispatcher(Growth.EVENTS, observer=target)
Esempio n. 32
0
class SelectionContainer(html5.Ul):
    """
		Provides a Container, which allows selecting its contents.
		Designed to be used within a tree widget, as it distinguishes between
		two different types of content (nodes and leafs) and allows selections to
		be restricted to a certain kind.
	"""
    def __init__(self,
                 nodeWidget,
                 leafWidget,
                 selectionType="both",
                 multiSelection=False,
                 *args,
                 **kwargs):
        super(SelectionContainer, self).__init__(*args, **kwargs)
        self["class"].append("selectioncontainer")
        self["tabindex"] = 1
        self.selectionType = selectionType
        self.multiSelection = multiSelection
        self.nodeWidget = nodeWidget
        self.leafWidget = leafWidget
        self.selectionChangedEvent = EventDispatcher("selectionChanged")
        self.selectionActivatedEvent = EventDispatcher(
            "selectionActivated"
        )  # Double-Click on an currently selected item - ITEM CLICKED !!!!
        self.selectionReturnEvent = EventDispatcher(
            "selectionReturn"
        )  # The current selection should be returned to parent widget
        self.cursorMovedEvent = EventDispatcher("cursorMoved")
        self._selectedItems = []  # List of row-indexes currently selected
        self._currentItem = None  # Rowindex of the cursor row
        self._isMouseDown = False  # Tracks status of the left mouse button
        self._isCtlPressed = False  # Tracks status of the ctrl key
        self._ctlStartRow = None  # Stores the row where a multi-selection (using the ctrl key) started
        self.sinkEvent("onClick", "onDblClick", "onMouseMove", "onMouseDown",
                       "onMouseUp", "onKeyDown", "onKeyUp")

    def setCurrentItem(self, item):
        """
			Sets the  currently selected item (=the cursor) to 'item'
			If there was such an item before, its unselected afterwards.
		"""
        if self._currentItem:
            self._currentItem["class"].remove("cursor")
        self._currentItem = item
        if item:
            item["class"].append("cursor")

    def onClick(self, event):
        self.focus()
        for child in self._children:
            if html5.utils.doesEventHitWidgetOrChildren(event, child):
                self.setCurrentItem(child)
                if self._isCtlPressed:
                    self.addSelectedItem(child)
        if not self._isCtlPressed:
            self.clearSelection()
        if self._selectedItems:
            self.selectionChangedEvent.fire(self, self._selectedItems[:])
        elif self._currentItem:
            self.selectionChangedEvent.fire(self, [self._currentItem])
        else:
            self.selectionChangedEvent.fire(self, [])

    def onDblClick(self, event):
        for child in self.children():

            if html5.utils.doesEventHitWidgetOrChildren(event, child):
                if self.selectionType == "both" or self.selectionType == child.skelType:
                    self.selectionActivatedEvent.fire(self, [child])
                    break

    def activateCurrentSelection(self):
        """
			Emits the selectionActivated event if there's currently a selection

		"""
        if len(self._selectedItems) > 0:
            self.selectionActivatedEvent.fire(self, self._selectedItems)

        elif self._currentItem is not None:
            self.selectionActivatedEvent.fire(self, [self._currentItem])

    def returnCurrentSelection(self):
        """
			Emits the selectionReturn event if there's currently a selection

		"""
        selection = []
        if len(self._selectedItems) > 0:
            selection = self._selectedItems
        # self.selectionReturnEvent.fire( self, self._selectedItems )
        elif self._currentItem is not None:
            selection = [self._currentItem]
        if self.selectionType == "node":
            selection = [
                x for x in selection if isinstance(x, self.nodeWidget)
            ]
        elif self.selectionType == "leaf":
            selection = [
                x for x in selection if isinstance(x, self.leafWidget)
            ]
        self.selectionReturnEvent.fire(self, selection)

    def onKeyDown(self, event):
        if html5.isReturn(event):  # Return
            self.activateCurrentSelection()
            event.preventDefault()
            return
        elif html5.isControl(
                event):  # and "multi" in (self.selectMode or ""): #Ctrl
            self._isCtlPressed = True

    def onKeyUp(self, event):
        if html5.isControl(event):
            self._isCtlPressed = False

    def clearSelection(self):
        for child in self._children[:]:
            self.removeSelectedItem(child)

    def addSelectedItem(self, item):
        # if not self.multiSelection:
        #	return
        if self.selectionType == "node" and isinstance(item, self.nodeWidget) or \
         self.selectionType == "leaf" and isinstance(item, self.leafWidget) or \
         self.selectionType == "both":
            if not item in self._selectedItems:
                self._selectedItems.append(item)
                item["class"].append("selected")

    def removeSelectedItem(self, item):
        if not item in self._selectedItems:
            return
        self._selectedItems.remove(item)
        item["class"].remove("selected")

    def clear(self):
        self.clearSelection()
        for child in self._children[:]:
            self.removeChild(child)
        self.selectionChangedEvent.fire(self, [])

    def getCurrentSelection(self):
        if len(self._selectedItems) > 0:
            return self._selectedItems[:]
        if self._currentItem:
            return [self._currentItem]
        return None
Esempio n. 33
0
class TextEditBone(html5.Div):

	def __init__(self, moduleName, boneName, readOnly, isPlainText, languages=None, descrHint=None, *args, **kwargs):
		super(TextEditBone, self).__init__(*args, **kwargs)
		self.boneName = boneName
		self.readOnly = readOnly
		self.selectedLang = False
		self.isPlainText = isPlainText
		self.languages = languages
		self.descrHint = descrHint
		self.valuesdict = dict()

		# multilangbone
		if self.languages:
			self.value = {lng: "" for lng in self.languages}

			if "currentlanguage" in conf and conf["currentlanguage"] in self.languages:
				self.selectedLang = conf["currentlanguage"]
			elif len(self.languages) > 0:
				self.selectedLang = self.languages[0]

			self.langButContainer = html5.Div()
			self.langButContainer["class"].append("languagebuttons")

			for lang in self.languages:
				abut = html5.ext.Button(lang, self.changeLang)
				abut["value"] = lang
				self.langButContainer.appendChild(abut)

			self.appendChild(self.langButContainer)
			self.refreshLangButContainer()
		else:
			self.value = ""

		if not readOnly and not self.isPlainText:
			self.input = HtmlEditor()
			self.input.boneName = self.boneName
		else:
			self.input = html5.Textarea()
			if readOnly:
				self.input["readonly"] = True

		self.appendChild(self.input)

		self.sinkEvent("onKeyUp")

		self.changeEvent = EventDispatcher("boneChange")
		self._changeTimeout = None

	def _setDisabled(self, disable):
		"""
			Reset the is_active flag (if any)
		"""
		super(TextEditBone, self)._setDisabled(disable)
		if not disable and not self._disabledState and "is_active" in self.parent()["class"]:
			self.parent()["class"].remove("is_active")

	def changeLang(self, btn):
		self.valuesdict[self.selectedLang] = self.input["value"]
		self.selectedLang = btn["value"]
		if self.selectedLang in self.valuesdict.keys():
			self.input["value"] = self.valuesdict[self.selectedLang]
		else:
			self.input["value"] = ""

		self.refreshLangButContainer()

	def refreshLangButContainer(self):
		for abut in self.langButContainer._children:

			if abut["value"] in self.valuesdict and self.valuesdict[abut["value"]]:
				if not "is_filled" in abut["class"]:
					abut["class"].append("is_filled")
			else:
				if not "is_unfilled" in abut["class"]:
					abut["class"].append("is_unfilled")

			if abut["value"] == self.selectedLang:
				if not "is_active" in abut["class"]:
					abut["class"].append("is_active")
			else:
				abut["class"].remove("is_active")

	@staticmethod
	def fromSkelStructure(moduleName, boneName, skelStructure, *args, **kwargs):
		readOnly = "readonly" in skelStructure[boneName].keys() and skelStructure[boneName]["readonly"]
		isPlainText = "validHtml" in skelStructure[boneName].keys() and not skelStructure[boneName]["validHtml"]
		langs = skelStructure[boneName]["languages"] if (
			"languages" in skelStructure[boneName].keys() and skelStructure[boneName]["languages"]) else None
		descr = skelStructure[boneName]["descr"] if "descr" in skelStructure[boneName].keys() else None
		return TextEditBone(moduleName, boneName, readOnly, isPlainText, langs, descrHint=descr)

	def unserialize(self, data):
		self.valuesdict.clear()
		if self.boneName in data.keys():
			if self.languages:
				for lang in self.languages:
					if self.boneName in data.keys() and isinstance(data[self.boneName], dict) and lang in data[
						self.boneName].keys():
						self.valuesdict[lang] = data[self.boneName][lang]
					else:
						self.valuesdict[lang] = ""
				self.input["value"] = self.valuesdict[self.selectedLang]
			else:
				self.input["value"] = data[self.boneName] if data[self.boneName] else ""

	def serializeForPost(self):
		if self.selectedLang:
			self.valuesdict[self.selectedLang] = self.input["value"]
			return {self.boneName: self.valuesdict}
		else:
			return {self.boneName: self.input["value"]}

	def serializeForDocument(self):
		return self.serializeForPost()

	def setExtendedErrorInformation(self, errorInfo):
		pass

	def onKeyUp(self, event):
		if not self.changeEvent.queue:
			return

		if self._changeTimeout:
			html5.window.clearTimeout(self._changeTimeout)

		self._changeTimeout = html5.window.setTimeout(lambda: self.changeEvent.fire(self), 2500)

	@staticmethod
	def checkForTextBone(moduleName, boneName, skelStucture, *args, **kwargs):
		return skelStucture[boneName]["type"] == "text"
Esempio n. 34
0
class TreeWidget(html5.Div):
    nodeWidget = NodeWidget
    leafWidget = LeafWidget
    defaultActions = [
        "add.node", "add.leaf", "selectrootnode", "edit", "delete", "reload"
    ]

    def __init__(self,
                 module,
                 rootNode=None,
                 node=None,
                 selectMode=None,
                 *args,
                 **kwargs):
        """
			:param module: Name of the module we shall handle. Must be a list application!
			:type module: str
			:param rootNode: The rootNode we shall display. If None, we try to select one.
			:type rootNode: str or None
			:param node: The node we shall display at start. Must be a child of rootNode
			:type node: str or None
		"""
        super(TreeWidget, self).__init__()
        self.addClass("tree")

        self.module = module
        self.rootNode = rootNode
        self.node = node or rootNode
        self.actionBar = ActionBar(module, "tree")
        self.appendChild(self.actionBar)
        self.pathList = html5.Ul()
        self.pathList["class"].append("breadcrumb")
        self.appendChild(self.pathList)
        self.entryFrame = SelectionContainer(self.nodeWidget, self.leafWidget)
        self.appendChild(self.entryFrame)
        self.entryFrame.selectionActivatedEvent.register(self)
        self._batchSize = 99
        self._currentCursor = {"node": None, "leaf": None}
        self._currentRequests = []
        self.rootNodeChangedEvent = EventDispatcher("rootNodeChanged")
        self.nodeChangedEvent = EventDispatcher("nodeChanged")

        assert selectMode in [
            None, "single", "multi", "single.leaf", "single.node",
            "multi.leaf", "multi.node"
        ]
        self.selectMode = selectMode

        if self.rootNode:
            self.reloadData()
            self.rebuildPath()
        else:
            NetworkService.request(self.module,
                                   "listRootNodes",
                                   successHandler=self.onSetDefaultRootNode)

        self.sinkEvent("onClick")

        # Proxy some events and functions of the original table
        for f in [
                "selectionChangedEvent", "selectionActivatedEvent",
                "cursorMovedEvent", "getCurrentSelection",
                "selectionReturnEvent"
        ]:
            setattr(self, f, getattr(self.entryFrame, f))

        self.actionBar.setActions(self.defaultActions + (
            ["select", "close"] if self.selectMode else []))

    def showErrorMsg(self, req=None, code=None):
        """
			Removes all currently visible elements and displays an error message
		"""
        self.actionBar["style"]["display"] = "none"
        self.entryFrame["style"]["display"] = "none"
        errorDiv = html5.Div()
        errorDiv["class"].append("error_msg")
        if code and (code == 401 or code == 403):
            txt = "Access denied!"
        else:
            txt = "An unknown error occurred!"
        errorDiv["class"].append("error_code_%s" % (code or 0))
        errorDiv.appendChild(html5.TextNode(txt))
        self.appendChild(errorDiv)

    def onAttach(self):
        super(TreeWidget, self).onAttach()
        NetworkService.registerChangeListener(self)

    def onDetach(self):
        super(TreeWidget, self).onDetach()
        NetworkService.removeChangeListener(self)

    def onDataChanged(self, module, **kwargs):
        if module != self.module:

            isRootNode = False
            for k, v in conf["modules"].items():
                if (k == module and v.get("handler") == "list"
                        and v.get("rootNodeOf") == self.module):
                    isRootNode = True
                    break

            if not isRootNode:
                return

        if "selectrootnode" in self.actionBar.widgets.keys():
            self.actionBar.widgets["selectrootnode"].update()

        self.reloadData()

    def onSelectionActivated(self, div, selection):
        if not selection:
            return

        item = selection[0]

        if item.skelType == "node":
            self.setNode(item.data["key"])

        elif item.skelType == "leaf" and "leaf" in (self.selectMode or ""):
            self.returnCurrentSelection()

    def activateCurrentSelection(self):
        return self.entryFrame.activateCurrentSelection()

    def returnCurrentSelection(self):
        conf["mainWindow"].removeWidget(self)
        return self.entryFrame.returnCurrentSelection()

    def onClick(self, event):
        super(TreeWidget, self).onClick(event)
        for c in self.pathList._children:
            # Test if the user clicked inside the path-list
            if html5.utils.doesEventHitWidgetOrParents(event, c):
                self.setNode(c.data["key"])
                return

    def onSetDefaultRootNode(self, req):
        data = NetworkService.decode(req)
        if len(data) > 0:
            self.setRootNode(data[0]["key"], self.node)

    def setRootNode(self, rootNode, node=None):
        self.rootNode = rootNode
        self.node = node or rootNode
        self.rootNodeChangedEvent.fire(rootNode)
        if node:
            self.nodeChangedEvent.fire(node)
        self.reloadData()
        self.rebuildPath()

    def setNode(self, node):
        self.node = node
        self.nodeChangedEvent.fire(node)
        self.reloadData()
        self.rebuildPath()

    def rebuildPath(self):
        """
			Rebuild the displayed path-list.
		"""
        self.pathList.removeAllChildren()

        NetworkService.request(self.module,
                               "view/node/%s" % self.node,
                               successHandler=self.onPathRequestSucceded)

    def onPathRequestSucceded(self, req):
        """
			Rebuild the displayed path-list according to request data
		"""
        answ = NetworkService.decode(req)
        skel = answ["values"]

        if skel["parentdir"] and skel["parentdir"] != skel["key"]:
            c = self.nodeWidget(self.module, skel, answ["structure"])

            NetworkService.request(self.module,
                                   "view/node/%s" % skel["parentdir"],
                                   successHandler=self.onPathRequestSucceded)

        else:
            c = self.nodeWidget(self.module, {
                "key": self.rootNode,
                "name": "root"
            }, [])
            c.addClass("is_rootnode")

        self.pathList.prependChild(c)

    def reloadData(self, paramsOverride=None):
        assert self.node is not None, "reloadData called while self.node is None"
        self.entryFrame.clear()
        self._currentRequests = []
        if paramsOverride:
            params = paramsOverride.copy()
        else:
            params = {"node": self.node}

        if "amount" not in params:
            params["amount"] = self._batchSize

        r = NetworkService.request(self.module,
                                   "list/node",
                                   params,
                                   successHandler=self.onRequestSucceded,
                                   failureHandler=self.showErrorMsg)
        r.reqType = "node"
        self._currentRequests.append(r)
        r = NetworkService.request(self.module,
                                   "list/leaf",
                                   params,
                                   successHandler=self.onRequestSucceded,
                                   failureHandler=self.showErrorMsg)
        r.reqType = "leaf"
        self._currentRequests.append(r)

        from handler.tree import TreeHandler  # import must be here, otherwise it throws an importError
        if isinstance(conf["mainWindow"].currentPane, TreeHandler):
            conf["theApp"].setPath(self.module + "/list/" + self.node)

    def onRequestSucceded(self, req):
        if not req in self._currentRequests:
            return

        self._currentRequests.remove(req)
        data = NetworkService.decode(req)

        for skel in data["skellist"]:
            if req.reqType == "node":
                n = self.nodeWidget(self.module, skel, data["structure"])
            else:
                n = self.leafWidget(self.module, skel, data["structure"])

            self.entryFrame.appendChild(n)

        self.entryFrame.sortChildren(self.getChildKey)

        if "cursor" in data.keys() and len(
                data["skellist"]) == req.params["amount"]:
            self._currentCursor[req.reqType] = data["cursor"]

            req.params["cursor"] = data["cursor"]
            r = NetworkService.request(self.module,
                                       "list/%s" % req.reqType,
                                       req.params,
                                       successHandler=self.onRequestSucceded,
                                       failureHandler=self.showErrorMsg)
            r.reqType = req.reqType
            self._currentRequests.append(r)
        else:
            self._currentCursor[req.reqType] = None

        self.actionBar.resetLoadingState()

    def getChildKey(self, widget):
        """
			Derives a string used to sort the entries in our entryframe
		"""
        name = (widget.data.get("name") or "").lower()

        if isinstance(widget, self.nodeWidget):
            return "0-%s" % name
        elif isinstance(widget, self.leafWidget):
            return "1-%s" % name
        else:
            return "2-"

    @staticmethod
    def canHandle(moduleName, moduleInfo):
        return moduleInfo["handler"].startswith("tree.")

    @staticmethod
    def render(moduleName, adminInfo, context):
        rootNode = context.get(conf["vi.context.prefix"] +
                               "rootNode") if context else None
        return TreeWidget(module=moduleName,
                          rootNode=rootNode,
                          context=context)