126 lines
4.3 KiB
Python
Executable File
126 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import sys
|
|
from PyQt6.QtCore import (Qt, QAbstractTableModel, QModelIndex, QSortFilterProxyModel)
|
|
from PyQt6.QtWidgets import (QApplication, QMainWindow, QTableView, QLineEdit, QVBoxLayout, QWidget)
|
|
|
|
class CustomTableModel(QAbstractTableModel):
|
|
def __init__(self, data):
|
|
super().__init__()
|
|
self._data = data
|
|
|
|
def rowCount(self, parent=QModelIndex()):
|
|
return len(self._data)
|
|
|
|
def columnCount(self, parent=QModelIndex()):
|
|
return 2 # Row number and data
|
|
|
|
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
|
|
if role == Qt.ItemDataRole.DisplayRole:
|
|
row, col = index.row(), index.column()
|
|
if col == 0:
|
|
return row + 1 # Row number (1-based index)
|
|
elif col == 1:
|
|
return self._data[row]
|
|
|
|
def setData(self, index, value, role=Qt.ItemDataRole.EditRole):
|
|
if role == Qt.ItemDataRole.EditRole and index.isValid():
|
|
self._data[index.row()] = value
|
|
self.dataChanged.emit(index, index, [Qt.ItemDataRole.EditRole])
|
|
return True
|
|
return False
|
|
|
|
def flags(self, index):
|
|
default_flags = Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled
|
|
if index.isValid():
|
|
return default_flags | Qt.ItemFlag.ItemIsDragEnabled | Qt.ItemFlag.ItemIsDropEnabled
|
|
return default_flags | Qt.ItemFlag.ItemIsDropEnabled
|
|
|
|
def removeRow(self, row):
|
|
self.beginRemoveRows(QModelIndex(), row, row)
|
|
self._data.pop(row)
|
|
self.endRemoveRows()
|
|
|
|
def insertRow(self, row, value):
|
|
self.beginInsertRows(QModelIndex(), row, row)
|
|
self._data.insert(row, value)
|
|
self.endInsertRows()
|
|
|
|
def moveRows(self, sourceParent, sourceRow, count, destinationParent, destinationRow):
|
|
if sourceRow < destinationRow:
|
|
destinationRow -= 1
|
|
|
|
self.beginMoveRows(sourceParent, sourceRow, sourceRow, destinationParent, destinationRow)
|
|
row_data = self._data.pop(sourceRow)
|
|
self._data.insert(destinationRow, row_data)
|
|
self.endMoveRows()
|
|
return True
|
|
|
|
class ProxyModel(QSortFilterProxyModel):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.filterString = ""
|
|
|
|
def setFilterString(self, text):
|
|
self.filterString = text
|
|
self.invalidateFilter()
|
|
|
|
def filterAcceptsRow(self, source_row, source_parent):
|
|
if self.filterString:
|
|
data = self.sourceModel().data(self.sourceModel().index(source_row, 1), Qt.ItemDataRole.DisplayRole)
|
|
return self.filterString in str(data)
|
|
return True
|
|
|
|
class TableView(QTableView):
|
|
def __init__(self, model):
|
|
super().__init__()
|
|
self.setModel(model)
|
|
self.setDragDropMode(QTableView.DragDropMode.InternalMove)
|
|
self.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
|
|
self.setSortingEnabled(False)
|
|
self.setDragDropOverwriteMode(False)
|
|
|
|
def dropEvent(self, event):
|
|
source_index = self.indexAt(event.pos())
|
|
if not source_index.isValid():
|
|
return
|
|
|
|
destination_row = source_index.row()
|
|
dragged_row = self.currentIndex().row()
|
|
|
|
if dragged_row != destination_row:
|
|
self.model().sourceModel().moveRows(QModelIndex(), dragged_row, 1, QModelIndex(), destination_row)
|
|
super().dropEvent(event)
|
|
self.model().layoutChanged.emit() # Refresh model to update row numbers
|
|
|
|
class MainWindow(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.data = ["dog", "hog", "don", "cat", "bat"]
|
|
|
|
self.baseModel = CustomTableModel(self.data)
|
|
self.proxyModel = ProxyModel()
|
|
self.proxyModel.setSourceModel(self.baseModel)
|
|
|
|
self.view = TableView(self.proxyModel)
|
|
|
|
self.filterLineEdit = QLineEdit()
|
|
self.filterLineEdit.setPlaceholderText("Filter by substring")
|
|
self.filterLineEdit.textChanged.connect(self.proxyModel.setFilterString)
|
|
|
|
layout = QVBoxLayout()
|
|
layout.addWidget(self.filterLineEdit)
|
|
layout.addWidget(self.view)
|
|
|
|
container = QWidget()
|
|
container.setLayout(layout)
|
|
self.setCentralWidget(container)
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
window = MainWindow()
|
|
window.show()
|
|
sys.exit(app.exec())
|
|
|