Search code examples
pythonpython-3.xpyside2

Best way of sorting hexadecimal numbers inside the QTableWidget


I want to know the best way of sorting hexadecimal numbers inside the QTableWidget.

Currently what i do is convert all the hexadecimal values then sort it (ascending/descending). But my problem is since i did convert it to decimal. The values shown in table is in decimal. I want to sort hexadecimal without changing the value shown in table

Here is my current implementation:

from PySide2.QtCore import Qt
from PySide2.QtWidgets import QTableWidget

class NumericData(QTableWidgetItem):
    def __lt__(self, other):
        return (self.data(Qt.UserRole) < other.data(Qt.UserRole))

class Window(QTableWidget):
    def __init__(self):
        super(Window, self).__init__(4, 2)
        for column, values in enumerate((
            ('ABCD', '1DCA', 'BD23', 'FFFFFFFF'),
            (1,2,3,4)
            )):
            for row, value in enumerate(values):
                if column == 0:
                    value = str(int(value, 16))
                else:
                    value = str(value)
                item = NumericData(value)
                item.setData(Qt.UserRole, value)
                self.setItem(row, column, item)
        self.setSortingEnabled(True)
        self.sortItems(0, Qt.AscendingOrder)

Here is the sample table

|--Values--|
|ABCD      |
|1BCD      |
|DEC1      |
|123       |
|2105      |
|AAAAAAAA  |

Solution

  • It is not necessary to use a new role just to save the conversion since if the user changes the value you would have to recalculate that value, you can only pass in the role Qt::DisplayRole.

    Considering this I have implemented the following example:

    from PySide2 import QtCore, QtGui, QtWidgets
    
    
    class HexDelegate(QtWidgets.QStyledItemDelegate):
        def createEditor(self, parent, option, index):
            editor = QtWidgets.QSpinBox(parent)
            editor.setMaximum(2147483647)
            editor.setMinimum(-2147483647 - 1)
            editor.setDisplayIntegerBase(16)
            fnt = editor.font()
            fnt.setCapitalization(QtGui.QFont.AllUppercase)
            editor.setFont(fnt)
            return editor
    
        def setEditorData(self, editor, index):
            editor.setValue(int(index.data(QtCore.Qt.DisplayRole), 16))
    
        def setModelData(self, editor, model, index):
            value = ('{:x}'.format(editor.value())).upper()
            model.setData(index, value, QtCore.Qt.DisplayRole)
    
    
    class NumericData(QtWidgets.QTableWidgetItem):
        def __lt__(self, other):
            return int(self.data(QtCore.Qt.DisplayRole), 16) < int(
                other.data(QtCore.Qt.DisplayRole), 16
            )
    
    
    class Window(QtWidgets.QTableWidget):
        def __init__(self):
            super(Window, self).__init__(4, 2)
            delegate = HexDelegate(self)
            self.setItemDelegateForColumn(0, delegate)
            data = ("ABCD", "1DCA", "BD23", "FFFF"), (1, 2, 3, 4)
            for row, values in enumerate(zip(*data)):
                for col, value in enumerate(values):
                    it = QtWidgets.QTableWidgetItem()
                    it.setData(QtCore.Qt.DisplayRole, value)
                    self.setItem(row, col, it)
            self.setSortingEnabled(True)
            self.sortItems(0, QtCore.Qt.AscendingOrder)
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = Window()
        w.show()
        sys.exit(app.exec_())