class EmbeddedViewTable(QtGui.QTableView, BaseWidget, EnableLogic, EditLogic, TriggeredPillowsLogic):
    __metaclass__ = QWallabyMeta

    room = Meta.property("string")
    path = Meta.property("string")
    reverseOrder = Meta.property("bool")
    identifier = Meta.property("string")
    isList = Meta.property("bool", default=True)
    dbColumns = Meta.property("list")
    wrapInList = Meta.property("bool")
    sizeHints = Meta.property("dict")

    notSelectableIfDisabled = Meta.property("bool", default=False)

    doubleClickPillow = Meta.property("string", extended=True)
    doubleClickFeathers = Meta.property("string", extended=True)
    doubleClickTab = Meta.property("string", extended=True)

    autoResizeCells = Meta.property("bool", extended=True)
    minRowHeight = Meta.property("int", extended=True)
    minColumnWidth = Meta.property("int", extended=True)

    alternateRowColors = Meta.property("bool", default=False)

    editOnInsert = Meta.property("bool")

    triggers = Meta.property("list", readOnly=True, default=["", "clicked", "double-clicked", "key"])

    def __init__(self, parent=None):
        QtGui.QTableView.__init__(self, parent)
        BaseWidget.__init__(self, QtGui.QTableView)
        EnableLogic.__init__(self)
        EditLogic.__init__(self, Editor, self.getData)
        TriggeredPillowsLogic.__init__(self)

        self.setSortingEnabled(False)

        self.horizontalHeader().setStretchLastSection(True)

        self._popup = None
        self._model = None
        self._actionPeer = None
        self._ignoreClick = False

        self._proxyModel = None
        self._selectedRow = None

        self._isEnabled = False

        # self.setAlternatingRowColors(True)
        self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

        self.verticalHeader().sectionMoved.connect(self.reorderRows)
        self.verticalHeader().setMovable(False)

        self.verticalHeader().sectionClicked.connect(self._itemClicked)

        self.clicked.connect(self._itemClicked)
        self.doubleClicked.connect(self._itemDoubleClicked)

        self._autoColumns = []

        self._imageDelegate = ImageDelegate()
        self._progressDelegate = ProgressDelegate()
        self._comboDelegates = []

    def editCell(self, row, col):
        idx = self._model.createIndex(row, col)
        if self._proxyModel is not None:
            idx = self._proxyModel.mapFromSource(idx)

        QtGui.QTableView.setCurrentIndex(self, idx)
        QtGui.QTableView.edit(self, idx, QtGui.QTableView.AllEditTriggers, None)

    def selectRow(self, row):
        if self._proxyModel is not None:
            idx = self._model.createIndex(row, 0)
            idx = self._proxyModel.mapFromSource(idx)
            row = idx.row()

        QtGui.QTableView.selectRow(self, row)

    def newData(self):
        if not self.autoResizeCells:
            return

        self.horizontalHeader().resizeSections(QtGui.QHeaderView.ResizeToContents)
        self.verticalHeader().resizeSections(QtGui.QHeaderView.ResizeToContents)
        self.horizontalHeader().setStretchLastSection(True)

        # for c in self._autoColumns:
        #    self.horizontalHeader().setResizeMode(c, QtGui.QHeaderView.ResizeToContents)

        if len(self._autoColumns) > 0:
            self.verticalHeader().setResizeMode(QtGui.QHeaderView.ResizeToContents)

    def _resolve(self, value, **ka):
        self._model.resolve(data=value, **ka)

    def getData(self):
        self._model.getData()

    def deregister(self, remove=False):
        EnableLogic.deregister(self, remove)
        EditLogic.deregister(self, remove)
        TriggeredPillowsLogic.deregister(self, remove)

        if self._model:
            FXUI.mainWindow.settings().setValue(self._template + "_headerState", self.horizontalHeader().saveState())

        if self._model:
            self._model.destroyPeers(remove)
        if self._actionPeer:
            self._actionPeer.destroy(remove)
        self._actionPeer = None

    def reorderRows(self, row, oldIndex, newIndex):
        if not self._isEnabled:
            return

        if self._model != None:
            self._model.reorderRows(row, oldIndex, newIndex)

    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 restoreSettings(self):
        headerState = FXUI.mainWindow.settings().value(self._template + "_headerState")
        # if headerState: self.horizontalHeader().restoreState(headerState)

    def _itemDoubleClicked(self, index):
        # FIXME
        self._ignoreClick = True

        self.trigger("double-clicked")
        if self._actionPeer:
            self._actionPeer.buttonClicked(index.row())

    def _itemClicked(self, index):
        if self._ignoreClick:
            self._ignoreClick = False
            # return

        self.resetSelection()
        self.trigger("clicked")

    def setEnabled(self, enabled):
        self._isEnabled = enabled

        self.verticalHeader().setMovable(enabled)

        if self.notSelectableIfDisabled:
            QtGui.QTableView.setEnabled(self, enabled)
            return

        if not enabled:
            self.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        else:
            self.setEditTriggers(QtGui.QAbstractItemView.DoubleClicked)

    def keyPressEvent(self, event):
        import wallaby.FXUI as FXUI

        if self.trigger("key", FXUI.key_event_to_name(event)):
            event.accept()
        else:
            event.ignore()
            QtGui.QTableView.keyPressEvent(self, event)

            if self.state() != QtGui.QAbstractItemView.EditingState:
                self.resetSelection()

    # def selectionChanged(self, selected, deselected):
    #     QtGui.QTableView.selectionChanged(self, selected, deselected)
    #     sel = self.selectionModel().selectedIndexes()
    #     if len(sel) == 0:
    #         self._model.doSelect(None)
    #     else:
    #         self._model.doSelect(sel[0].row())

    def resetSelection(self):
        sel = self.selectionModel().selectedIndexes()
        if len(sel) == 0:
            self._model.doSelect(None)
        else:
            if self._proxyModel != None:
                sel = self._proxyModel.mapToSource(sel[0])
            else:
                sel = sel[0]

            self._selectedRow = sel.row()

            self._model.doSelect(self._selectedRow)
            self.scrollTo(sel)
    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)