Exemplo n.º 1
0
 def setData(self, index: QModelIndex, data, role: int = None):
     LOG.debug('setData {0!r:s}'.format(data))
     if not index.isValid():
         return False
     if role == Qt.EditRole:
         if isinstance(data, str):
             LOG.debug("changing row {0:d} name to {1!r:s}".format(
                 index.row(), data))
             self.doc.change_layer_name(index.row(), data)
             self.dataChanged.emit(index, index)
             return True
         else:
             LOG.debug("data type is {0!r:s}".format(type(data)))
     elif role == Qt.CheckStateRole:
         newvalue = True if data == Qt.Checked else False
         LOG.debug('toggle layer visibility for row {} to {}'.format(
             index.row(), newvalue))
         self.doc.toggle_layer_visibility(index.row(), newvalue)
         self.dataChanged.emit(index, index)
         return True
     elif role == Qt.ItemDataRole:
         LOG.warning('attempting to change layer')
         # self.doc.replace_layer()
         # FIXME implement this
         self.dataChanged.emit(index, index)
         return True
     elif role == Qt.DisplayRole:
         if index.isValid():
             LOG.debug("changing row {} name to {0!r:s}".format(
                 index.row(), data))
             self.doc.change_layer_name(index.row(), data)
             return True
     return False
Exemplo n.º 2
0
 def leafs(self, searchedIndex: QModelIndex) -> QModelIndexList:
     leafs = QModelIndexList()
     if searchedIndex.isValid():
         childCount = searchedIndex.model().columnCount(searchedIndex)
         for i in range(childCount):
             leafs += self.searchLeafs(searchedIndex.child(0, i))
     return leafs
Exemplo n.º 3
0
 def data(self, QModelIndex, int_role = None):
     """
     For initial role out, assume
     http://qt-project.org/doc/qt-4.8/qt.html#ItemDataRole-enum
     :param QModelIndex:
     :param int_role:
     :return:
     Qt::DisplayRole	0	The key data to be rendered in the form of text. (QString)
     Qt::DecorationRole	1	The data to be rendered as a decoration in the form of an icon. (QColor, QIcon or QPixmap)
     Qt::EditRole	2	The data in a form suitable for editing in an editor. (QString)
     Qt::ToolTipRole	3	The data displayed in the item's tooltip. (QString)
     Qt::StatusTipRole	4	The data displayed in the status bar. (QString)
     Qt::WhatsThisRole	5	The data displayed for the item in "What's This?" mode. (QString)
     Qt::SizeHintRole	13	The size hint for the item that will be supplied to views. (QSize)
     Roles describing appearance and meta data (with associated types):
     Constant	Value	Description
     Qt::FontRole	6	The font used for items rendered with the default delegate. (QFont)
     Qt::TextAlignmentRole	7	The alignment of the text for items rendered with the default delegate. (Qt::AlignmentFlag)
     Qt::BackgroundRole	8	The background brush used for items rendered with the default delegate. (QBrush)
     Qt::BackgroundColorRole	8	This role is obsolete. Use BackgroundRole instead.
     Qt::ForegroundRole	9	The foreground brush (text color, typically) used for items rendered with the default delegate. (QBrush)
     Qt::TextColorRole	9	This role is obsolete. Use ForegroundRole instead.
     Qt::CheckStateRole	10	This role is used to obtain the checked state of an item. (Qt::CheckState)
     Qt::InitialSortOrderRole	14	This role is used to obtain the initial sort order of a header view section. (Qt::SortOrder). This role was introduced in Qt 4.8.
     """
     if int_role == 0:
         if QModelIndex.isValid():
             i = QModelIndex.row()
             j = QModelIndex.column()
             return QString(str(self.DataFrame.ix[i, j]))
         else:
             return QVariant()
     else:
         return QVariant()
Exemplo n.º 4
0
    def dropOn(self, event):
        if event.isAccepted():
            return False, None, None, None

        index = QModelIndex()
        row = -1
        col = -1

        if self.viewport().rect().contains(event.pos()):
            index = self.indexAt(event.pos())
            if not index.isValid() or not self.visualRect(index).contains(
                    event.pos()):
                index = self.rootIndex()

        if self.model().supportedDropActions() & event.dropAction():
            if index != self.rootIndex():
                dropIndicatorPosition = self.position(event.pos(),
                                                      self.visualRect(index),
                                                      index)
                if dropIndicatorPosition == QAbstractItemView.AboveItem:
                    row = index.row()
                    col = index.column()
                elif dropIndicatorPosition == QAbstractItemView.BelowItem:
                    row = index.row() + 1
                    col = index.column()
                else:
                    row = index.row()
                    col = index.column()

            if not self.droppingOnItself(event, index):
                return True, row, col, index

        return False, None, None, None
Exemplo n.º 5
0
    def apply(self):
        if not self.__dialog:
            self.createDialog()

        self.__datasource.applied = False
        sourceType = unicode(self.__dialog.ui.typeComboBox.currentText())
        self.__datasource.dataSourceName = unicode(
            self.__dialog.ui.nameLineEdit.text())

        if sourceType in self.__dialog.imp.keys():
            self.__dialog.imp[sourceType].fromForm(self.__datasource)

        self.__datasource.dataSourceType = sourceType
        self.__datasource.doc = unicode(
            self.__dialog.ui.docTextEdit.toPlainText()).strip()

        index = QModelIndex()
        if hasattr(self.__dialog, "view") and self.__dialog.view \
                and self.__dialog.view.model():
            if hasattr(self.__dialog.view, "currentIndex"):
                index = self.__dialog.view.currentIndex()
                finalIndex = self.__dialog.view.model().createIndex(
                    index.row(), 2,
                    index.parent().internalPointer())
                self.__dialog.view.expand(index)

        row = index.row()
        column = index.column()
        parent = index.parent()

        if self.__dialog.root:
            self.updateNode(index)

            if index.isValid():
                index = self.__dialog.view.model().index(row, column, parent)
                self.__dialog.view.setCurrentIndex(index)
                self.__dialog.view.expand(index)

            if hasattr(self.__dialog, "view") and self.__dialog.view \
                    and self.__dialog.view.model():
                self.__dialog.view.model().emit(
                    SIGNAL("dataChanged(const QModelIndex &,"
                           " const QModelIndex &)"), index.parent(),
                    index.parent())
                if index.column() != 0:
                    index = self.__dialog.view.model().index(
                        index.row(), 0, index.parent())
                self.__dialog.view.model().emit(
                    SIGNAL("dataChanged(const QModelIndex &,"
                           " const QModelIndex &)"), index, finalIndex)
                self.__dialog.view.expand(index)

        if not self.__datasource.tree:
            self.createNodes()

        self.__datasource.applied = True

        return True
Exemplo n.º 6
0
 def sectionSizeFromContents(self, logicalIndex: int) -> QSize:
     if self._pd.headerModel:
         curLeafIndex = QModelIndex(self._pd.leafIndex(logicalIndex))
         if curLeafIndex.isValid():
             styleOption = QStyleOptionHeader(
                 self.styleOptionForCell(logicalIndex))
             s = QSize(self._pd.cellSize(curLeafIndex, self, styleOption))
             curLeafIndex = curLeafIndex.parent()
             while curLeafIndex.isValid():
                 if self.orientation() == Qt.Horizontal:
                     s.setHeight(s.height() + self._pd.cellSize(
                         curLeafIndex, self, styleOption).height())
                 else:
                     s.setWidth(s.width() + self._pd.cellSize(
                         curLeafIndex, self, styleOption).width())
                 curLeafIndex = curLeafIndex.parent()
             return s
     return super().sectionSizeFromContents(logicalIndex)
Exemplo n.º 7
0
 def searchLeafs(self, currentIndex: QModelIndex) -> QModelIndexList:
     res = QModelIndexList()
     if currentIndex.isValid():
         childCount = currentIndex.model().columnCount(currentIndex)
         if childCount:
             for i in range(childCount):
                 res += self.searchLeafs(currentIndex.child(0, i))
         else:
             res.push_back(currentIndex)
     return res
Exemplo n.º 8
0
    def rowCount(self, parent):
        if parent is None:
            parent = QModelIndex()

        if parent.column() > 0:
            return 0

        if not parent.isValid():
            return len(self.__root)
        else:
            return len(parent.internalPointer())
Exemplo n.º 9
0
    def rowCount(self, parent):
        if parent is None:
            parent = QModelIndex()

        if parent.column() > 0:
            return 0

        if not parent.isValid():
            return len(self.__root)
        else:
            return len(parent.internalPointer())
Exemplo n.º 10
0
 def paintSection(self, painter: QPainter, rect: QRect, logicalIndex: int):
     if rect.isValid():
         leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex))
         if leafIndex.isValid():
             if self.orientation() == Qt.Horizontal:
                 self._pd.paintHorizontalSection(
                     painter, rect, logicalIndex, self,
                     self.styleOptionForCell(logicalIndex), leafIndex)
             else:
                 self._pd.paintVerticalSection(
                     painter, rect, logicalIndex, self,
                     self.styleOptionForCell(logicalIndex), leafIndex)
             return
     super().paintSection(painter, rect, logicalIndex)
Exemplo n.º 11
0
    def _rItem2Index(self, item, parent=None):
        if parent is None:
            parent = QModelIndex()
        if item == self.getItem(parent):
            return parent

        if not parent.isValid() or parent.internalPointer().populated:
            for i in range(self.rowCount(parent)):
                index = self.index(i, 0, parent)
                index = self._rItem2Index(item, index)
                if index.isValid():
                    return index

        return QModelIndex()
Exemplo n.º 12
0
    def _rItem2Index(self, item, parent=None):
        if parent is None:
            parent = QModelIndex()
        if item == self.getItem(parent):
            return parent

        if not parent.isValid() or parent.internalPointer().populated:
            for i in range(self.rowCount(parent)):
                index = self.index(i, 0, parent)
                index = self._rItem2Index(item, index)
                if index.isValid():
                    return index

        return QModelIndex()
Exemplo n.º 13
0
    def index(self, row, column, parent=None):
        if parent is None:
            parent = QModelIndex()

        if not self.hasIndex(row, column, parent):
            return QModelIndex()

        if not parent.isValid():
            parent_item = self.__root
        else:
            parent_item = parent.internalPointer()

        child_item = parent_item.child(row)

        return self.createIndex(row, column, child_item)
Exemplo n.º 14
0
    def index(self, row, column, parent=None):
        if parent is None:
            parent = QModelIndex()

        if not self.hasIndex(row, column, parent):
            return QModelIndex()

        if not parent.isValid():
            parent_item = self.__root
        else:
            parent_item = parent.internalPointer()

        child_item = parent_item.child(row)

        return self.createIndex(row, column, child_item)
Exemplo n.º 15
0
 def findLeaf(self, currentIndex: QModelIndex, sectionIndex: int,
              currentLeafIndex: int) -> QModelIndex:
     if currentIndex.isValid():
         childCount = currentIndex.model().columnCount(currentIndex)
         if childCount:
             for i in range(childCount):
                 res, currentLeafIndex = self.findLeaf(
                     currentIndex.child(0, i), sectionIndex,
                     currentLeafIndex)
                 if res.isValid():
                     return res, currentLeafIndex
         else:
             currentLeafIndex += 1
             if currentLeafIndex == sectionIndex:
                 return currentIndex, currentLeafIndex
     return QModelIndex(), currentLeafIndex
Exemplo n.º 16
0
    def __update(self):
        """Update the current description.
        """
        if self.__currentIndex != -1:
            index = self.model().index(self.__currentIndex, 0)
        else:
            index = QModelIndex()

        if not index.isValid():
            description = ""
            name = ""
            path = ""
            svg = NO_PREVIEW_SVG
        else:
            description = qtcompat.qunwrap(index.data(Qt.WhatsThisRole))
            if description:
                description = six.text_type(description)
            else:
                description = u"No description."

            description = escape(description)
            description = description.replace("\n", "<br/>")

            name = qtcompat.qunwrap(index.data(Qt.DisplayRole))
            if name:
                name = six.text_type(name)
            else:
                name = "Untitled"

            name = escape(name)
            path = qtcompat.qunwrap(index.data(Qt.StatusTipRole))
            path = six.text_type(path)

            svg = qtcompat.qunwrap(index.data(previewmodel.ThumbnailSVGRole))
            svg = six.text_type(svg)

        desc_text = self.__template.format(description=description, name=name)

        self.__label.setText(desc_text)

        self.__path.setText(path)

        if not svg:
            svg = NO_PREVIEW_SVG

        if svg:
            self.__image.load(QByteArray(svg.encode("utf-8")))
Exemplo n.º 17
0
 def on_sectionResized(self, logicalIndex: int):
     if self.isSectionHidden(logicalIndex):
         return
     leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex))
     if leafIndex.isValid():
         leafsList = QModelIndexList(
             self._pd.leafs(self._pd.findRootIndex(leafIndex)))
         for n in range(leafsList.indexOf(leafIndex), 0, -1):
             logicalIndex -= 1
             w = self.viewport().width()
             h = self.viewport().height()
             pos = self.sectionViewportPosition(logicalIndex)
             r = QRect(pos, 0, w - pos, h)
             if self.orientation() == Qt.Horizontal:
                 if self.isRightToLeft():
                     r.setRect(0, 0, pos + self.sectionSize(logicalIndex),
                               h)
             else:
                 r.setRect(0, pos, w, h - pos)
             self.viewport().update(r.normalized())
Exemplo n.º 18
0
    def __update(self):
        """Update the current description.
        """
        if self.__currentIndex != -1:
            index = self.model().index(self.__currentIndex, 0)
        else:
            index = QModelIndex()

        if not index.isValid():
            description = ""
            name = ""
            path = ""
            svg = NO_PREVIEW_SVG
        else:
            description = str(index.data(Qt.WhatsThisRole))
            if not description:
                description = "No description."

            description = escape(description)
            description = description.replace("\n", "<br/>")

            name = str(index.data(Qt.DisplayRole))
            if not name:
                name = "Untitled"

            name = escape(name)
            path = str(index.data(Qt.StatusTipRole))

            svg = str(index.data(previewmodel.ThumbnailSVGRole))

        desc_text = self.__template.format(description=description, name=name)

        self.__label.setText(desc_text)

        self.__path.setText(path)

        if not svg:
            svg = NO_PREVIEW_SVG

        if svg:
            self.__image.load(QByteArray(svg.encode("utf-8")))
Exemplo n.º 19
0
    def data(self, index: QModelIndex, role: int = None):
        if not index.isValid():
            return None
        row = index.row()
        # LOG.debug("getting data for row %d" % row)
        # col = index.column()
        el = self.listing
        info = el[row] if row < len(self.doc) else None
        if not info:
            return None

        # pass auxiliary info about the layer through the Qt.UserRole for use when displaying
        eq_content = self._last_equalizer_values.get(info[INFO.UUID], None)
        if role == Qt.UserRole:
            # get the animation order also
            animation_order = self.doc.layer_animation_order(row)
            return (eq_content, animation_order)

        elif role == Qt.EditRole:
            return self.doc.current_layer_set[
                index.row()] if index.row() < len(self.doc) else None
        elif role == Qt.CheckStateRole:
            check = Qt.Checked if self.doc.is_layer_visible(
                row) else Qt.Unchecked
            return check
        elif role == Qt.ToolTipRole:
            if not eq_content:
                return None
            value, normalized = eq_content[:2]
            return str(value)
        elif role == Qt.DisplayRole:
            # lao = self.doc.layer_animation_order(row)
            name = info[INFO.DISPLAY_NAME]
            # return  ('[-]  ' if lao is None else '[{}]'.format(lao+1)) + el[row]['name']
            # if leroy:
            #     data = '[%.2f] ' % leroy[0]
            #     return data + name
            return name
        return None
Exemplo n.º 20
0
 def data(self, index: QtCore.QModelIndex, role: int=QtCore.Qt.DisplayRole):
     alignment = {
         FieldType.bool: QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter,
         FieldType.date: QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter,
         FieldType.int: QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
         FieldType.float: QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter,
         FieldType.str: QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
     }
     col = index.column()
     fld = self.query_manager.table.fields[col]
     val = self.visible_data[index.row()][col]
     try:
         if not index.isValid():
             return
         elif role == QtCore.Qt.TextAlignmentRole:
             return alignment[fld.dtype]
         elif role == QtCore.Qt.DisplayRole:
             if col in self.foreign_keys.keys():
                 return self.foreign_keys[col][val]
             return fld.format_value(val)
     except Exception as e:
         self.error_signal.emit('Error modeling data: {}'.format(e))
Exemplo n.º 21
0
 def data(self,
          index: QtCore.QModelIndex,
          role: int = QtCore.Qt.DisplayRole):
     alignment = {
         FieldType.bool: QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter,
         FieldType.date: QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter,
         FieldType.int: QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
         FieldType.float: QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter,
         FieldType.str: QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter,
     }
     col = index.column()
     fld = self.query_manager.table.fields[col]
     val = self.visible_data[index.row()][col]
     try:
         if not index.isValid():
             return
         elif role == QtCore.Qt.TextAlignmentRole:
             return alignment[fld.dtype]
         elif role == QtCore.Qt.DisplayRole:
             if col in self.foreign_keys.keys():
                 return self.foreign_keys[col][val]
             return fld.format_value(val)
     except Exception as e:
         self.error_signal.emit('Error modeling data: {}'.format(e))
Exemplo n.º 22
0
class _TagModel(QAbstractItemModel):
    jumpToTagDone = pyqtSignal()

    def __init__(self, *args):
        QAbstractItemModel.__init__(self, *args)
        self._tags = []

        self._currentTagIndex = QModelIndex()

        defBaseColor = QApplication.instance().palette().base().color()
        # yellow or maroon
        brightBg = QColor('#ffff80') if defBaseColor.lightnessF(
        ) > 0.5 else QColor('#800000')
        self._currentTagBrush = QBrush(brightBg)

        core.workspace().cursorPositionChanged.connect(
            self._onCursorPositionChanged)
        self._updateCurrentTagTimer = QTimer()
        self._updateCurrentTagTimer.setInterval(300)
        self._updateCurrentTagTimer.timeout.connect(
            self._updateCurrentTagAndEmitSignal)

    def setTags(self, tags):
        self.beginResetModel()
        self._tags = tags
        self._updateCurrentTag(False)
        self.endResetModel()

    def _onCursorPositionChanged(self):
        """If position is updated on every key pressing - cursor movement might be slow
        Update position, when movement finished
        """
        self._updateCurrentTagTimer.stop()
        self._updateCurrentTagTimer.start()

    def _updateCurrentTagAndEmitSignal(self):
        self._updateCurrentTag(True)

    def _updateCurrentTag(self, emitChanged):
        old = self._currentTagIndex

        # Workspace might be None, if core terminated
        if core.workspace() is not None and \
           core.workspace().currentDocument() is not None:
            lineNumber = core.workspace().currentDocument(
            ).qutepart.cursorPosition[0]
            self._currentTagIndex = self._indexForLineNumber(lineNumber)
        else:
            self._currentTagIndex = QModelIndex()

        if emitChanged:
            if old != self._currentTagIndex and \
               old.isValid():
                self.dataChanged.emit(old, old)
            if self._currentTagIndex.isValid():
                self.dataChanged.emit(self._currentTagIndex,
                                      self._currentTagIndex)

    def index(self, row, column, parent):
        if row < 0 or column != 0:
            return QModelIndex()

        if not parent.isValid():  # top level
            if row < len(self._tags):
                return self.createIndex(row, column, self._tags[row])
            else:
                return QModelIndex()
        else:  # nested
            parentTag = parent.internalPointer()
            if row < len(parentTag.children):
                return self.createIndex(row, column, parentTag.children[row])
            else:
                return QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QModelIndex()

        tag = index.internalPointer()
        if tag.parent is not None:
            parent = tag.parent
            if parent.parent:
                try:
                    row = parent.parent.children.index(parent)
                except ValueError:
                    return QModelIndex()
            else:
                try:
                    row = self._tags.index(parent)
                except ValueError:
                    return QModelIndex()

            return self.createIndex(row, 0, parent)
        else:
            return QModelIndex()

    def rowCount(self, index):
        if index.isValid():
            tag = index.internalPointer()
            return len(tag.children)
        else:
            return len(self._tags)

    def columnCount(self, index):
        return 1

    def data(self, index, role):
        if not index.isValid():
            return None

        if role == Qt.DisplayRole:
            tag = index.internalPointer()
            return tag.name
        elif role == Qt.BackgroundRole:
            return self._currentTagBrush if index == self._currentTagIndex else None
        else:
            return None

    def onActivated(self, index):
        tag = index.internalPointer()

        document = core.workspace().currentDocument()
        if document is not None:
            core.workspace().cursorPositionChanged.disconnect(
                self._onCursorPositionChanged)
            document.qutepart.cursorPosition = (tag.lineNumber, 0)
            core.workspace().cursorPositionChanged.connect(
                self._onCursorPositionChanged)
            self._updateCurrentTagAndEmitSignal()

            document.qutepart.centerCursor()
            document.qutepart.setFocus()
            self.jumpToTagDone.emit()

    def tagPathForIndex(self, index):
        tag = index.internalPointer()
        return _tagPath(tag)

    def indexForTagPath(self, tagPath):
        def findTag(tagList, name):
            for tag in tagList:
                if tag.name == name:
                    return tag
            else:
                return None

        def findPath(currentTag, childTags, parts):
            if not parts:
                return currentTag

            part = parts[0]
            tag = findTag(childTags, part)
            if tag is not None:
                return findPath(tag, tag.children, parts[1:])
            else:
                return currentTag

        parts = tagPath.split('.')
        tag = findPath(None, self._tags, parts)
        if tag is not None:
            row = tag.parent.children.index(
                tag) if tag.parent else self._tags.index(tag)
            return self.createIndex(row, 0, tag)
        else:
            return QModelIndex()

    def _indexForLineNumber(self, number):
        def recursiveTagGenerator(tags):
            for childRow, childTag in enumerate(tags):
                yield childRow, childTag
                for gcRow, grandChild in recursiveTagGenerator(
                        childTag.children):
                    yield gcRow, grandChild

        prevRow, prevTag = None, None
        for row, tag in recursiveTagGenerator(self._tags):
            if tag.lineNumber == number:
                return self.createIndex(row, 0, tag)
            elif tag.lineNumber > number and \
                 prevTag is not None and \
                 prevTag.lineNumber <= number:
                return self.createIndex(prevRow, 0, prevTag)
            else:
                prevRow, prevTag = row, tag
        else:
            if prevTag is not None and \
               prevTag.lineNumber <= number: # the last tag is current
                return self.createIndex(prevRow, 0, prevTag)

        return QModelIndex()
Exemplo n.º 23
0
def on_sectionResized(self, logicalIndex: int):
if self.isSectionHidden(logicalIndex):
    return
leafIndex = QModelIndex(self._pd.leafIndex(logicalIndex))
if leafIndex.isValid():
    leafsList = QModelIndexList(self._pd.leafs(self._pd.findRootIndex(leafIndex)))
    for n in range(leafsList.indexOf(leafIndex), 0, -1):
        logicalIndex-=1
        w = self.viewport().width()
        h = self.viewport().height()
        pos = self.sectionViewportPosition(logicalIndex)
        r = QRect(pos, 0, w - pos, h)
        if self.orientation() == Qt.Horizontal:
            if self.isRightToLeft():
                r.setRect(0, 0, pos + self.sectionSize(logicalIndex), h)
        else:
            r.setRect(0, pos, w, h - pos)
        self.viewport().update(r.normalized())

def setModel(self, model):
    super().setModel(model)
    model.layoutChanged.connect(self.layoutChanged)
    self.layoutChanged()

def layoutChanged(self):
    if self.model():
        self._pd.initFromNewModel(self.orientation(), self.model())
        axis = ("column", "row")[self.orientation()!=Qt.Horizontal]
        cnt = getattr(self.model(), axis+"Count")(QModelIndex())
        if cnt:
            self.initializeSections(0, cnt-1)
MultiIndexHeaderView=HierarchicalHeaderView

class DataFrameModel(QtCore.QAbstractTableModel):
    #na_values:least|greatest - for sorting
    options = {"striped": True, "stripesColor": "#fafafa", "na_values": "least",
               "tooltip_min_len": 21}
    def __init__(self, dataframe=None):
        super().__init__()
        self.setDataFrame(dataframe if dataframe is not None else pd.DataFrame())

    def setDataFrame(self, dataframe):
        self.df = dataframe.copy()
        #        self.df_full = self.df
        self.layoutChanged.emit()

    def rowCount(self, parent):
        return len(self.df)

    def columnCount(self, parent):
        return len(self.df.columns)

    def readLevel(self, y=0, xs=0, xe=None, orient=None):
        c = getattr(self.df, ("columns", "index")[orient!=HorizontalHeaderDataRole])
        if not hasattr(c, "levels"): #not MultiIndex
            return [QtGui.QStandardItem(str(i)) for i in c]
        sibl = []
        section_start, v, xe = xs, None, xe or len(c)
        for i in range(xs, xe):
            label = c.labels[y][i]
            if label!=v:
                if y+1<len(c.levels) and i>xs:
                    children = self.readLevel(y+1, section_start, i, orient=orient)
                    sibl[-1].appendRow(children)
                item = QtGui.QStandardItem(str(c.levels[y][label]))
                sibl.append(item)
                section_start = i
                v=label
        if y+1<len(c.levels):
            children = self.readLevel(y+1, section_start, orient=orient)
            sibl[-1].appendRow(children)
        return sibl

    def data(self, index, role):
        row, col = index.row(), index.column()
        if role in (Qt.DisplayRole, Qt.ToolTipRole):
            ret = self.df.iat[row, col]
            if ret is not None and ret==ret: #convert to str except for None, NaN, NaT
                if isinstance(ret, float):
                    ret = "{:n}".format(ret)
                elif isinstance(ret, datetime.date):
                    #FIXME: show microseconds optionally
                    ret = ret.strftime(("%x", "%c")[isinstance(ret, datetime.datetime)])
                else: ret = str(ret)
                if role == Qt.ToolTipRole:
                    if len(ret)<self.options["tooltip_min_len"]: ret = ""
                return ret
        elif role == Qt.BackgroundRole:
            if self.options["striped"] and row%2:
                return QBrush(QColor(self.options["stripesColor"]))
        elif role in (HorizontalHeaderDataRole, VerticalHeaderDataRole):
            hm = QtGui.QStandardItemModel()
            hm.appendRow(self.readLevel(orient=role))
            return hm

    def reorder(self, oldIndex, newIndex, orientation):
        "Reorder columns / rows"
        horizontal = orientation==Qt.Horizontal
        cols = list(self.df.columns if horizontal else self.df.index)
        cols.insert(newIndex, cols.pop(oldIndex))
        self.df = self.df[cols] if horizontal else self.df.T[cols].T
        return True

    #    def filter(self, filt=None):
    #        self.df = self.df_full if filt is None else self.df[filt]
    #        self.layoutChanged.emit()

    def headerData(self, section, orientation, role):
        if role != Qt.DisplayRole: return
        label = getattr(self.df, ("columns", "index")[orientation!=Qt.Horizontal])[section]
        #        return label if type(label) is tuple else label
        return ("\n", " | ")[orientation!=Qt.Horizontal].join(str(i) for i in label) if type(label) is tuple else str(label)

    def dataFrame(self):
        return self.df

    def sort(self, column, order):
        #        print("sort", column, order) #FIXME: double sort after setSortingEnabled(True)
        if len(self.df):
            asc = order==Qt.AscendingOrder
            na_pos = 'first' if (self.options["na_values"]=="least")==asc else 'last'
            self.df.sort_values(self.df.columns[column], ascending=asc,
                                inplace=True, na_position=na_pos)
            self.layoutChanged.emit()

if __name__=="__main__":
    import sys, locale
    locale.setlocale(locale.LC_ALL, '') #system locale settings
    app = QtGui.QApplication(sys.argv)
    form = QtGui.QWidget()
    form.setAttribute(Qt.WA_DeleteOnClose) #http://stackoverflow.com/a/27178019/1119602
    form.setMinimumSize(700, 260)
    view = QtGui.QTableView()
    QtGui.QVBoxLayout(form).addWidget(view)
    form.show()

    #Prepare data
    tuples=[('bar', 'one', 'q'), ('bar', 'two', 'q'), ('baz', 'one', 'q'), ('baz', 'two', 'q'),
            ('foo', 'one', 'q'), ('foo', 'two', 'q'), ('qux', 'one', 'q'), ('qux', 'two', 'q')]
    index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second', 'third'])
    df=pd.DataFrame(pd.np.random.randn(6, 6), index=index[:6], columns=index[:6])
    print("DataFrame:\n%s"%df)

    #Prepare view
    #    oldh, oldv = view.horizontalHeader(), view.verticalHeader()
    #    oldh.setParent(form), oldv.setParent(form) #Save old headers for some reason
    MultiIndexHeaderView(Qt.Horizontal, view)
    MultiIndexHeaderView(Qt.Vertical, view)
    view.horizontalHeader().setMovable(True) #reorder DataFrame columns manually

    #Set data
    view.setModel(DataFrameModel(df))
    view.resizeColumnsToContents()
    view.resizeRowsToContents()

    #Set sorting enabled (after setting model)
    view.setSortingEnabled(True)
    sys.exit(app.exec())
Exemplo n.º 24
0
 def parentFromIndex(self, index):
     index = QModelIndex(
         index)  # explicitly convert from QPersistentModelIndex
     if index.isValid():
         return index.internalPointer()
     return self._root
Exemplo n.º 25
0
 def parentIndexes(self, index: QModelIndex) -> QModelIndexList:
     indexes = QModelIndexList()
     while index.isValid():
         indexes.push_front(index)
         index = index.parent()
     return indexes
Exemplo n.º 26
0
 def parentFromIndex(self, index):
     index = QModelIndex(index)  # explicitly convert from QPersistentModelIndex
     if index.isValid():
         return index.internalPointer()
     return self._root
Exemplo n.º 27
0
 def itemFromIndex(self, index):
     index = QModelIndex(index)  # explicitly convert from QPersistentModelIndex
     if index.isValid():
         return index.internalPointer().childAt(index.row())
     return self._root
Exemplo n.º 28
0
 def itemFromIndex(self, index):
     index = QModelIndex(
         index)  # explicitly convert from QPersistentModelIndex
     if index.isValid():
         return index.internalPointer().childAt(index.row())
     return self._root