def loadUIFiles(self):
        self._sheetPrototypes = {}

        prefs = []

        import wallaby.frontends as frontends
        from twisted.plugin import getCache

        for p in FX.packagePath(FX.appModule + ".prefs"): prefs.append(p)
        for frontend in getCache(frontends):
            for p in FX.packagePath("wallaby.frontends." + frontend + ".prefs"): prefs.append(p)

        import os
        for path in prefs:
            root = re.sub(r'[/\\]','.', path).replace('..', '')
            root = re.sub(r'^.*wallaby\.', 'wallaby.', root)
            files = os.listdir(path)
 
            for file in files:
                if '.py' in file and '.pyc' not in file and 'UI_' in file:
                    basename, ext = os.path.splitext(file)
                    if ext == '.py':
                        mod = FX.imp(root + '.' + basename)
                        print "Loading prefs sheet", root + '.' + basename, mod
                        if mod == None: continue
   
                        import string 
                        cls = basename[0] + string.lower(basename[1]) + basename[2] + string.upper(basename[3]) + basename[4:]
    
                        sheetName = unicode(basename.replace('UI_', ''))
    
                        if not cls in mod.__dict__: continue
                        self._sheetPrototypes[sheetName] = mod.__dict__[cls]
    def _message(self, pillow, feather, thrower=None):
        from wallaby.pf.room import Room
        if self._notFoundLimit > 0 and pillow == Room.Out.NoHandlerFound and feather in self._notFound and self._notFound[feather] == self._notFoundLimit: return

        thrower = str(thrower)
        if '.' in thrower:
            import re
            match = re.match('<([^\s]+)', thrower)
            thrower = match.group(1).split('.')
            thrower = thrower[-2] + "." + thrower[-1]

        out = "|{0:<16}|{1:<48}|{2:<64}|{3}".format(self._roomName,thrower,pillow,feather)

        if pillow == Room.Out.NoHandlerFound:
            if feather not in self._notFound:
                self._notFound[feather] = 1
            else:
                self._notFound[feather] += 1

            if self._notFound[feather] == self._notFoundLimit:
                out += "..."

            out = self.color('1;31', out)

        import wallaby.FX as FX
        FX.debug(out)
    def realQuit(self, shuttime):
        if FXUI.app != None:
            if shuttime > 0:
                print "Shutdown in ", (shuttime-1), "seconds"
                from twisted.internet import reactor
                reactor.callLater(1, self.realQuit, shuttime-1)
                return

            from wallaby.frontends.qt.widgets.baseWidget import BaseWidget
            if FXUI.mainWindow is not None:
                for w in FXUI.mainWindow.findChildren(BaseWidget):
                    w.deregister(True)

            app = FXUI.app
            del FXUI.app
            del FXUI.mainWindow
            FXUI.mainWindow = FXUI.app = None

            print "Stopping Reactor"
            from twisted.internet import reactor
            reactor.stop()

            FX.info("Stopping app")
            print "Stopping App"

            app.exit(0)
            # FXUI.app.quit()
            FX.info("Bye")

            app = None
 def myQuit(self):
     print "Set shutdown flag"
     FX.shutdown = True
     FX.callShutdownCBs()
     shuttime = 0
     from twisted.internet import reactor
     print "Shutdown in ", shuttime, "seconds"
     reactor.callLater(1, self.realQuit, shuttime)
    def __init__(self, widget, cols=None, *args, **ka):
        QtCore.QAbstractTableModel.__init__(self, None)

        self._widget = widget

        self._peer = IncrementalMultiViewer(*args, delegate=self, **ka)

        self._updateChangedDeferred = None
        self._maxRow = self._minRow = -1

        self._columns  = []
        self._types    = []
        self._typeArgs = []
        self._labels   = []
        self._cache    = []
        self._parent   = QtCore.QModelIndex()

        if cols == None: cols = []

        self._minRowHeight = 0
        self._minColumnWidth = 0

        self._loading = 0

        self._sizeHints = {}

        if 'minRowHeight' in ka: self._minRowHeight = ka['minRowHeight']
        if 'minColumnWidth' in ka: self._minColumnWidth = ka['minColumnWidth']
        if 'sizeHints' in ka: self._sizeHints = ka['sizeHints']

        if self._minRowHeight == None: self._minRowHeight = 0
        if self._minColumnWidth == None: self._minColumnWidth = 0
        if self._sizeHints == None: self._sizeHints = {}

        if isinstance(cols, list) and len(cols) > 0 and isinstance(cols[0], dict):
            cols.insert(0, {'path':'id'})
            self._columns = []
            self._labels = []
            self._types = []
            self._typeArgs = []
            for cfg in cols:
                if cfg is None: continue
                self._columns.append(cfg.get('path', None))
                self._labels.append(cfg.get('label', None))
                self._types.append(FX.convertType(cfg.get('type', None)))
                self._typeArgs.append(cfg.get('type-args', None))
        else: 
            cols.insert(0, 'id')
            self._columns, self._labels = FX.splitList(cols, ':')
            self._types, self._typeArgs, self._columns = FX.extractType(self._columns)
    def get(room):
        if room in (None, ""): room = "None"

        if not room in House.rooms:
            if FX.appModule:
                app = FX.appModule
                if room in ("__CONFIG__", "__WIDGETQUERY__"): app = "wallaby.apps.inspector"

                try:
                    from twisted.plugin import getCache
                    pkg = __import__(app + '.rooms', globals(), locals(), ["*"], 0)
                    modules = getCache(pkg)

                    if room.lower() in modules:
                        mod = FX.imp(app + '.rooms.' + room.lower())
                        if mod:
                            cls = room.capitalize()

                            if cls in mod.__dict__:
                                ctx = House.rooms[room] = mod.__dict__[cls](room)
                                return ctx
                except:
                    pass
                        
            # No room template found. Create generic room
            House.rooms[room] = Room(room)

        return House.rooms[room]
    def __init__(self, widget, room, path, cols=['_id'], parent=None, conflictCB=None, isList=True, identifier=None, reverseOrder=False, minRowHeight=None, minColumnWidth=None, wrapInList=False, sizeHints=None, editOnInsert=False, *args):
        QtCore.QAbstractTableModel.__init__(self, parent, *args)

        self._peer   = EmbeddedViewer(room, path, delegate=self, conflictCB=conflictCB, isList=isList, wrapInList=wrapInList, identifier=identifier, editOnInsert=editOnInsert)
        self._widget = widget

        self._reverseOrder = reverseOrder

        self._imageCache = {}

        self._minRowHeight = 0
        self._minColumnWidth = 0
        self._sizeHints = {}

        if minRowHeight != None: self._minRowHeight = int(float(minRowHeight))
        if minColumnWidth != None: self._minColumnWidth = int(float(minColumnWidth))
        if sizeHints != None: self._sizeHints = sizeHints

        self._isList   = isList
        self._wrapInList = wrapInList
        self._columns  = []
        self._labels   = []
        self._types    = []
        self._typeArgs = []
        self._data     = self._emptyData()
        self._parent   = QtCore.QModelIndex()
        self._keys = None
        self._rows = None

        self._length = 0
           
        if isinstance(cols, list) and len(cols) > 0 and isinstance(cols[0], dict):
            self._columns = []
            self._labels = []
            self._types = []
            self._typeArgs = []
            for cfg in cols:
                if cfg is None: continue
                self._columns.append(cfg.get('path', None))
                self._labels.append(cfg.get('label', None))
                self._types.append(FX.convertType(cfg.get('type', None)))
                self._typeArgs.append(cfg.get('type-args', None))
        else: 
            self._columns, self._labels = FX.splitList(cols, ':')
            self._types, self._typeArgs, self._columns = FX.extractType(self._columns)
        self._path = path
    def register(self):
        for c in self.sortable:
            self._sortable[c] = 0

        if len(self._sortable) > 0:
            self.header().setSortIndicatorShown(True)

        if self.multiSelect:
            self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)

        self._columns, self._labels = FX.splitList(self.dbColumns, ':')
        self._types, _, self._columns = FX.extractType(self._columns)

        if self.keyCodePillows != None:
            for kca in self.keyCodePillows:
                kca = unicode(kca)
                code, pillow = kca.split(':')
                feathers = None
                if ',' in pillow:
                    feathers = pillow.split(',')
                    pillow = feathers.pop(0)

                code = eval("QtCore.Qt." + code)

                self._keyCodePillows[code] = (pillow, feather)

        col = 0
        for t in self._types:
            if isinstance(t, dict):
                for k, v in t.items():
                    if len(v) > 0 and v[0] == ':':
                        self.setItemDelegateForColumn(col, ImageDelegate())

            col = col + 1

        if self.doubleClickPillow != None:
            self._peer = ActionButtonPeer(self.room, self.doubleClickPillow, self.doubleClickFeathers, tab=self.doubleClickTab)

        self._model = MultiViewTableModel(self, self.dbColumns, roomName=self.room, view=self.view, viewIdentifier=self.viewIdentifier, viewArguments=self.viewArguments, dataView=self.dataView)
        self.setModel(self._model)
    def createPeers(self):
        for p in self._dynamicPeers: p.destroy(remove=True)

        self._dynamicPeers = []

        observer = House.observer()

        for dct in self._peers:
            name = dct['name']
            if name is None or name == "None": continue

            args = {}
            if 'config' in dct: args = dct['config']

            if not args:
                try:
                    obj = observer.peer(name, self._name)
                except Exception as e:
                    FX.crit("Exception while creating instance of", name)
                    import traceback 
                    traceback.print_exc(file=sys.stdout)

            elif isinstance(args, dict):
                lst = ()

                obj = observer.peer(name, self._name, *lst, **args)

            if not obj:
                FX.crit("Error creating peer", name, "for room", self._name, "with options", args)
            else:
                FX.info("Successfully created peer", name, "for room", self._name)
                self._dynamicPeers.append(obj)
Exemple #10
0
    def __dequeue(self):
        calls = []
        statefullCnt = 0

        for pillow in self._statefullQueue:
            if pillow not in self._statefullPillows: continue

            for ident, (args, ka) in self._statefullPillows[pillow].items():
                statefullCnt += len(self._statefullQueue[pillow])

                for catcher, passThrower in self._statefullQueue[pillow]:
                    if passThrower and 'me' in ka:
                        call = (catcher, args, {"thrower":ka['me']})
                    else:
                        call = (catcher, args, {})

                    calls.append(call)

        self._statefullQueue = {}

        for call in self._normalQueue:
            calls.append(call)

        # print "[", self._name, "] Queue sizes:", statefullCnt, len(self._normalQueue) 

        self._normalQueue = []

        for catcher, args, ka in calls: 
            try:
                catcher(*args, **ka)
            except Exception as e:
                FX.crit("Exception while throwing pillow")
                import traceback 
                traceback.print_exc(file=sys.stdout)

        self._dequeueCall = None
        if len(self._statefullQueue) + len(self._normalQueue) > 0: self.__dequeueRequest()
    def scan(self, peers=None):
        fqPeers = []

        if peers is None:
            import wallaby.pf.peer as peers
            from twisted.plugin import getCache
            peers = getCache(peers)
            root = "wallaby.pf.peer"

            for peer in peers:
                fqPeers.append(root + "." + peer)
        else:
            fqPeers = peers

        for fqPeer in fqPeers:
            
            mod = FX.imp(fqPeer)
            root, basename = fqPeer.rsplit('.', 1)

            if mod == None: continue

            cls = string.upper(basename[0]) + basename[1:]                       

            if not cls in mod.__dict__: continue

            fqn = root + '.' + basename + '.' + cls

            self._fqn[cls] = fqn

            if re.search(r"\.room", root) != None:
                self._rooms[cls] = mod.__dict__[cls]
            else:
                self._peers[cls] = mod.__dict__[cls]

            self._objectTypes[fqn] = mod.__dict__[cls].ObjectType

            for base in mod.__dict__[cls].__bases__:
                fqBase = base.__module__ + '.' + base.__name__
                if not fqBase in self._extendedBy:
                    self._extendedBy[fqBase] = set()

                self._extendedBy[fqBase].add(fqn)

                if not fqn in self._bases:
                    self._bases[fqn] = set()

                self._bases[fqn].add(fqBase)

            if 'Receiving' in mod.__dict__[cls].__dict__:
                for fqa in mod.__dict__[cls].Receiving:
                    pillow = None
                    try:
                        pillow = fqa.split('.')[2]
                    except:
                        print "Split error:", fqa

                    pillow = pillow.replace('!', '')
                    fqa = fqa.replace('!', '')

                    if not pillow in self._inBoundPillows: self._inBoundPillows[pillow] = []
                    if not fqa in self._inBoundPillowsFQ: self._inBoundPillowsFQ[fqa] = []
                    if not fqn in self._inBoundPillowsPerPeer: self._inBoundPillowsPerPeer[fqn] = []
                    self._inBoundPillows[pillow].append(fqn)
                    self._inBoundPillowsFQ[fqa].append(fqn)
                    self._inBoundPillowsPerPeer[fqn].append(fqa)


            for pillow in mod.__dict__[cls].InPillows:
                pillow = pillow.replace('!', '')

                fqa = cls + '.In.' + pillow
                fqa = fqa.replace('!', '')

                if not pillow in self._inBoundPillows: self._inBoundPillows[pillow] = []
                if not fqa in self._inBoundPillowsFQ: self._inBoundPillowsFQ[fqa] = []
                if not fqn in self._inBoundPillowsPerPeer: self._inBoundPillowsPerPeer[fqn] = []
                self._inBoundPillows[pillow].append(fqn)
                self._inBoundPillowsFQ[fqa].append(fqn)
                self._inBoundPillowsPerPeer[fqn].append(fqa)

            if 'Sending' in mod.__dict__[cls].__dict__:
                for fqa in mod.__dict__[cls].Sending:
                    pillow = None
                    try:
                        pillow = fqa.split('.')[2]
                    except:
                        print "Split error:", fqa

                    fqa = fqa.replace('!', '')
                    pillow = pillow.replace('!', '')

                    if not pillow in self._outBoundPillows: self._outBoundPillows[pillow] = []
                    if not fqa in self._outBoundPillowsFQ: self._outBoundPillowsFQ[fqa] = []
                    if not fqn in self._outBoundPillowsPerPeer: self._outBoundPillowsPerPeer[fqn] = []
                    self._outBoundPillows[pillow].append(fqn)
                    self._outBoundPillowsFQ[fqa].append(fqn)
                    self._outBoundPillowsPerPeer[fqn].append(fqa)

            for pillow in mod.__dict__[cls].OutPillows:
                pillow = pillow.replace('!', '')

                fqa = cls + '.Out.' + pillow
                fqa = fqa.replace('!', '')
                if not pillow in self._outBoundPillows: self._outBoundPillows[pillow] = []
                if not fqa in self._outBoundPillowsFQ: self._outBoundPillowsFQ[fqa] = []
                if not fqn in self._outBoundPillowsPerPeer: self._outBoundPillowsPerPeer[fqn] = []
                self._outBoundPillows[pillow].append(fqn)
                self._outBoundPillowsFQ[fqa].append(fqn)
                self._outBoundPillowsPerPeer[fqn].append(fqa)
    def __init__(self, appName = 'example', checkRoom = None, suggest = False, options=None):
        splash = None

        FXUI.app = QtGui.QApplication(sys.argv)
        FXUI.app.setApplicationName("wallaby - " + appName)

        for s in ['16', '32', '64', '128', '256']:
            FXUI.app.setWindowIcon(QtGui.QIcon(QtGui.QPixmap(':/icons/images/wallaby_logo_' + s + '.png')))

        pixmap = QtGui.QPixmap(":/images/images/wallaby_splash.png")
        splash = QtGui.QSplashScreen(pixmap)
        splash.show()
        splash.raise_()
        FXUI.app.processEvents()

        if USES_PYSIDE or FXUI.qt4reactor:
            print "Install qt4reactor. USES_PYSIDE =", USES_PYSIDE
            import wallaby.frontends.qt.reactor.qt4reactor as qtreactor
            qtreactor.install()
        else:
            threadedselect.install()
             
            from twisted.internet import reactor
            ii = Interleaver()
            reactor.interleave(ii.toInterleave)
            reactor.suggestThreadPoolSize(50)

        FXUI.mineIcon = QtGui.QIcon(':/icons/images/mine.png')
        FXUI.theirsIcon = QtGui.QIcon(':/icons/images/theirs.png')

        tapp = twisted.application.service.Application("gui")
        service  = FXLogger('wallaby.log')
        service.setServiceParent(tapp)
        service.startService()

        FX.appModule = 'wallaby.apps.' + appName

        try:
            from twisted.plugin import getCache
            pkg = __import__(FX.appModule, globals(), locals(), ["*"], 0)
            if pkg is not None and len(pkg.__path__) > 0 and os.path.exists(pkg.__path__[0]):
                FX.appPath = pkg.__path__[0]
            else:
                FX.appPath = os.path.join(".", "wallaby", "apps", appName)
        except:
            FX.appPath = os.path.join(".", "wallaby", "apps", appName)

        FXUI.css = None

        try:
            print "importing", options.module, "from", FX.appModule
            if options.module == "WallabyApp2" and os.path.exists(os.path.join(FX.appPath, "mainWindow.py")):
                mod = FX.imp(FX.appModule + '.mainWindow', False)
                if os.path.exists(os.path.join(FX.appPath, "mainWindow.css")):
                    FXUI.css = open(os.path.join(FX.appPath, "mainWindow.css")).read()
            else:
                module = options.module
                module = module[0].lower() + module[1:]
                mod = FX.imp(FX.appModule + '.' + module, False)

                if os.path.exists(os.path.join(FX.appPath, module + ".css")):
                    FXUI.css = open(os.path.join(FX.appPath, module + ".css")).read()
        except:
            mod = None

        if mod == None:
            FX.crit('Module', FX.appModule, 'not found')
            reactor.callWhenRunning(self.myQuit)
            if USES_PYSIDE or FXUI.qt4reactor: reactor.runReturn()
            FXUI.app.exec_()
            return

        try:
            FXUI.mainWindow = mod.MainWindow(self.myQuit, options)
            if FXUI.css is not None:
                FXUI.app.setStyle("plastique")
                FXUI.mainWindow.setStyleSheet(FXUI.css)
        except Exception as e:
            import traceback
            traceback.print_exc(file=sys.stdout)

            from twisted.internet import reactor
            reactor.callWhenRunning(self.myQuit)
            if USES_PYSIDE or FXUI.qt4reactor: reactor.runReturn()
            FXUI.app.exec_()
            return

        FXUI.mainWindow.setSplash(splash)

        from twisted.internet import reactor
        reactor.callWhenRunning(self.run, mod, options, checkRoom)

        FXUI.mainWindow.enabled = False
        FXUI.mainWindow.configure()
        FXUI.mainWindow.show()
        FXUI.mainWindow.raise_()

        signal.signal(signal.SIGINT, self.sigint_handler)
        signal.signal(signal.SIGTERM, self.sigint_handler)

        # self.gc = GarbageCollector(FXUI.mainWindow, True)

        if USES_PYSIDE or FXUI.qt4reactor: reactor.runReturn()
        FXUI.app.exec_()
    def register(self):
        EnableLogic.register(self)
        TriggeredPillowsLogic.register(self)

        self._sortable = {}
        self._sortField = {"__default__": "__default__"}

        sortable = []

        self.setAlternatingRowColors(self.alternateRowColors)

        converted = False
        for c in self.sortable:
            if c is None: 
                sortable.append(None)
                continue
                
            if isinstance(c, (unicode, str)):
                if ':' in c:
                    c, field = c.split(':')
                else:
                    field = c

                sortable.append({'sortPath': field, 'path': c})
                converted = True
            else:
                sortable.append(c)

        if converted: self.sortable = sortable

        for c in self.sortable:
            if c is None: continue

            field = c.get('sortPath', None)
            c = c.get('path', None)
               
            self._sortable[c] = 0
            self._sortField[c] = field

        if len(self._sortable) > 0:
            self.horizontalHeader().setSortIndicatorShown(True)
        else:
            self.horizontalHeader().setSortIndicatorShown(False)

        if self.multiSelect:
            self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        else:
            self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)

        if isinstance(self.dbColumns, list) and len(self.dbColumns) > 0 and isinstance(self.dbColumns[0], (str, unicode)):
            columns, labels = FX.splitList(self.dbColumns, ':')
            types, args, columns = FX.extractType(columns, json=False)

            dbColumns = []

            # convert old format
            for i in range(len(columns)):
                dbColumns.append({
                    'path': columns[i],
                    'label': labels[i],
                    'type': types[i],
                    'type-args': args[i]
                })

            self.dbColumns = dbColumns

        self._columns = []
        self._labels = []
        self._types = []
        for cfg in self.dbColumns:
            if cfg is None: continue
            self._columns.append(cfg.get('path', None))
            self._labels.append(cfg.get('label', None))
            self._types.append(FX.convertType(cfg.get('type', None)))

        if self.orderPath != None:
            self.verticalHeader().setMovable(True) 

        if self.keyCodePillows != None:
            for kca in self.keyCodePillows:
                kca = unicode(kca)
                lst = kca.split(':')
                code = lst.pop(0)
                if len(lst) >= 2:
                    room = lst.pop(0)
                else:
                    room = self.room

                pillow = lst.pop(0)

                feathers = None
                if ',' in pillow:
                    feathers = pillow.split(',')
                    pillow = feathers.pop(0)

                code = eval("QtCore.Qt." + code)

                self._keyCodePillows[code] = (room, pillow, feathers)


        self._autoColumns = []
        col = 0
        for t in self._types:
            hasDelegate = False
            if isinstance(t, dict):
                for k, v in t.items():
                    if not hasDelegate and len(v) > 0 and v[0] == ':':
                        self.setItemDelegateForColumn(col+1, self._imageDelegate)
                        self._autoColumns.append(col+1)
                        hasDelegate = True
            elif t == "progress":
                self.setItemDelegateForColumn(col+1, self._progressDelegate)
            elif t == "image":
                self.setItemDelegateForColumn(col+1, self._imageDelegate)
                self._autoColumns.append(col+1)
                hasDelegate = True

            col = col + 1

        if self.doubleClickPillow != None:
            self._actionPeer = ActionButtonPeer(self.room, self.doubleClickPillow, self.doubleClickFeathers, tab=self.doubleClickTab)

        from wallaby.frontends.qt.models.multiViewTableModel import MultiViewTableModel
        self._model = MultiViewTableModel(self, self.dbColumns, room=self.room, view=self.view, viewIdentifier=self.viewIdentifier, viewArguments=self.viewArguments, dataView=self.dataView, orderPath=self.orderPath, minRowHeight=self.minRowHeight, minColumnWidth=self.minColumnWidth, queryDocID=self.queryDocID, sizeHints=self.sizeHints)
        self.setModel(self._model)

        if self.idVisible:
            self.setColumnHidden(0, False)
        else:
            self.setColumnHidden(0, True)
Exemple #14
0
    def _throw(self, pillow, feathers="", **ka):
        try:
            wcPeers     = None
            normalPeers = None
            singlePeers = None

            if pillow == None: 
                # print "WARNING - skipping none pillow"
                return

            # decode json feathers
            if feathers != None and isinstance(feathers, (str, unicode)) and feathers.startswith('json:'):
                jsonString = '{"object":' + feathers.replace('json:', '', 1) + '}'
                try: 
                    import json
                    feathers = json.loads(jsonString)
                    feathers = feathers["object"]
                except Exception as e:
                    print "Error while parsing json", jsonString, e
                    feathers = None

            # save statefull pillow for resending
            if pillow.endswith("!"):
                identifier = "__any__"
                try: identifier = feathers.identifier()
                except: pass

                if pillow not in self._statefullPillows: self._statefullPillows[pillow] = {}

                self._statefullPillows[pillow][identifier] = ((pillow, feathers), ka)
                self._statefullQueue[pillow] = []

            # create copies of peers to avoid race conditions
            # FIXME: this can result in calls of unallocated QObject methods!!! 
            if "*" in self._pillows:
                wcPeers = copy.copy(self._pillows["*"])

            if pillow in self._pillows:
                normalPeers = copy.copy(self._pillows[pillow])

            if pillow in self._singlePillows:
                singlePeers = copy.copy(self._singlePillows[pillow])
                del self._singlePillows[pillow]

            for peers in (wcPeers, normalPeers, singlePeers):
                if peers != None and pillow != Room.Out.NoHandlerFound:
                    for (catcher, passThrower) in peers:
                        if passThrower and 'me' in ka:
                            self.__enqueue(catcher, pillow, feathers, passThrower=passThrower, thrower=ka['me'])
                        else:
                            self.__enqueue(catcher, pillow, feathers, passThrower=passThrower)

            # Send a "NoHandlerFound" pillow if not already handled
            if normalPeers == None and singlePeers == None and pillow != Room.Out.NoHandlerFound:
                self._throw(Room.Out.NoHandlerFound, pillow, thrower=self)

        except Exception as e:
            FX.crit("Exception while throwing pillow", pillow)
            import traceback 
            traceback.print_exc(file=sys.stdout)

        self.__dequeueRequest()
    def register(self):
        EnableLogic.register(self)
        EditLogic.register(self)
        TriggeredPillowsLogic.register(self)

        self.setAlternatingRowColors(self.alternateRowColors)

        if (
            isinstance(self.dbColumns, list)
            and len(self.dbColumns) > 0
            and isinstance(self.dbColumns[0], (str, unicode))
        ):
            columns, labels = FX.splitList(self.dbColumns, ":")
            types, args, columns = FX.extractType(columns, json=False)

            dbColumns = []

            # convert old format
            for i in range(len(columns)):
                dbColumns.append({"path": columns[i], "label": labels[i], "type": types[i], "type-args": args[i]})

            self.dbColumns = dbColumns

        self._columns = []
        self._labels = []
        self._types = []
        for cfg in self.dbColumns:
            if cfg is None:
                continue

            self._columns.append(cfg.get("path", None))
            self._labels.append(cfg.get("label", None))
            self._types.append(FX.convertType(cfg.get("type", None)))

        self._autoColumns = []
        self._comboDelegate = []
        col = 0
        for t in self._types:
            hasDelegate = False
            if t is None:
                col = col + 1
                continue
            if isinstance(t, dict):
                for k, v in t.items():
                    if not hasDelegate and len(v) > 0 and v[0] == ":":
                        self.setItemDelegateForColumn(col, self._imageDelegate)
                        self._autoColumns.append(col)
                        hasDelegate = True
            elif "image" in t:
                self.setItemDelegateForColumn(col, self._imageDelegate)
                self._autoColumns.append(col)
                hasDelegate = True
            elif t == "progress":
                self.setItemDelegateForColumn(col, self._progressDelegate)
            elif t == "comboedit":
                self._comboDelegate.append(ComboBoxDelegate(self, col))
                self.setItemDelegateForColumn(col, self._comboDelegate[-1])

            col = col + 1

        from wallaby.frontends.qt.models.embeddedViewTableModel import EmbeddedViewTableModel

        self._model = EmbeddedViewTableModel(
            self,
            self.room,
            self.path,
            self.dbColumns,
            conflictCB=self._conflict,
            isList=self.isList,
            identifier=self.identifier,
            reverseOrder=self.reverseOrder,
            minRowHeight=self.minRowHeight,
            minColumnWidth=self.minColumnWidth,
            wrapInList=self.wrapInList,
            sizeHints=self.sizeHints,
            editOnInsert=self.editOnInsert,
        )

        if FXUI.mainWindow.options() != None and FXUI.mainWindow.options().app != "inspector":
            self._proxyModel = QtGui.QSortFilterProxyModel(self)
            self._proxyModel.setSourceModel(self._model)
            self._proxyModel.setFilterRegExp(
                QtCore.QRegExp("^(?!inspector-|itest-)", QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp2)
            )
            # proxyModel.setFilterRegExp(QtCore.QRegExp("^inspector", QtCore.Qt.CaseInsensitive, QtCore.QRegExp.RegExp2))

            # proxyModel.setFilterKeyColumn(0)
            self.setModel(self._proxyModel)
        else:
            self.setModel(self._model)

        if self.doubleClickPillow != None:
            self._actionPeer = ActionButtonPeer(
                self.room, self.doubleClickPillow, self.doubleClickFeathers, tab=self.doubleClickTab, translate=True
            )

        QtCore.QTimer.singleShot(0, self.restoreSettings)
    def loadUIFiles(self):
        # Do not reload widgets if not changed
        if self.sheets is None or self.sheets == self._lastSheets: return
        self._lastSheets = self.sheets

        self.clear()

        isheets = []

        self._sheetPrototypes = {}

        import wallaby.frontends as frontends
        from twisted.plugin import getCache

        for p in FX.packagePath(FX.appModule + ".isheet"): isheets.append(p)
        for frontend in getCache(frontends):
            for p in FX.packagePath("wallaby.frontends." + frontend + ".isheet"): isheets.append(p)

        import os
        for path in isheets:
            root = re.sub(r'[/\\]','.', path).replace('..', '')
            root = re.sub(r'^.*wallaby\.', 'wallaby.', root)
            files = os.listdir(path)
            for file in files:
                if '.py' in file and '.pyc' not in file and 'UI_' in file:
                    basename, ext = os.path.splitext(file)

                    if ext != '.py': continue

                    mod = FX.imp(root + '.' + basename)
                    if mod == None: continue

                    cls = basename[0] + string.lower(basename[1]) + basename[2] + string.upper(basename[3]) + basename[4:]
    
                    sheetName = unicode(basename.replace('UI_', ''))

                    sheetCache = None

                    if sheetName in self._sheetPrototypes: 
                        continue

                    if re.match(self.sheets, sheetName) is None: 
                        continue

                    if not self.isMultiPage():
                        p = self.parent()
                        while p != None and (not isinstance(p, Container) or not p.isMultiPage()):
                            p = p.parent()

                        if p is not None:
                            sheetCache = p.sheetCache

                            if sheetName in sheetCache:
                                self._sheet = sheetCache[sheetName]
                                return

                    if not cls in mod.__dict__:
                        for key, val in mod.__dict__.items():
                            if key.startswith("Ui_"):
                                cls = key
                                break

                    if not cls in mod.__dict__: continue

                    self._sheetPrototypes[sheetName] = mod.__dict__[cls]

                    sheet = QtGui.QWidget(self)
                    sheet.ui = self._sheetPrototypes[sheetName]()
                    sheet.ui.setupUi(sheet)
                    sheet.setObjectName(sheetName + "Sheet") 

                    if sheetCache is not None:
                        self._sheet = sheet
                        sheetCache[sheetName] = sheet
                        # also add the cached sheet to the current widget
                        # to allow nested widgets to also be loaded

                    self.addChildWidget(sheet)