is it possible to reorder QSqlTableModel from QListView?

235 Views Asked by At

I'm trying to reorder this QSqlTableModel from a QListView but it seems impossible i tried every thing i found on the internet ( offical documentation, examples forums blogs ) but Nothing happend,i activated the moving action and override flags method mimeData method, honnestly i don't know if i did it correctly. the drag action is working but the problem is on dragging i think.

Here is my advanced programm

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
import sys, os


def create_connection():
    db = QSqlDatabase.addDatabase("QSQLITE")
    db.setDatabaseName("medias.sqlite")
    if not db.open():
        print(db.lastError().text())
        return False

    q = QSqlQuery()
    if not q.exec(
        """
    CREATE TABLE IF NOT EXISTS fichiers (
        id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
        path VARCHAR(300) NOT NULL
    )
    """
    ):
        print(q.lastError().text())
        return False
    print(db.tables())
    return True
class listModel(QSqlTableModel):
    def __init__(self,*args, **kwargs):
        super(listModel, self).__init__(*args, **kwargs)
        self.setEditStrategy(QSqlTableModel.OnFieldChange)
        print('mimetype', self.mimeTypes())
        self.setTable("fichiers")
        self.select()

    def flags(self, index):
        return Qt.ItemIsEditable | Qt.ItemIsDragEnabled | Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsDropEnabled

    def ajouter(self, fichier):
        rec = self.record()
        rec.setValue("path", fichier)
        self.insertRecord(-1, rec)
        self.select()

    def mimeData(self, indexes):
        types = self.mimeTypes()
        mimeData = QMimeData()
        print('mimedata', mimeData)
        encodedData = QByteArray()
        stream = QDataStream(encodedData, QIODevice.WriteOnly)
        for index in indexes:
            if not index.isValid():
                continue
            if index.isValid():
                node = index.internalPointer()
                text = self.data(index, Qt.DisplayRole)
        mimeData.setData(types[0], encodedData)
        return mimeData

    def supportedDragActions(self):
        return Qt.MoveAction

    def supportedDropActions(self):
        return Qt.MoveAction 

    def dropMimeData(self, data, action, row, column, parent):
        if action == Qt.MoveAction:
            print ("Moving")
            self.insertRows(row, 1, QModelIndex())
            idx = self.index(row, 0, QModelIndex())
            self.setData(idx, self.mimeTypes())
            return True
        if row != -1:
            beginRow = row
        elif parent.isValid():
            beginRow = parent.row()
        else:
            beginRow = rowCount(QModelIndex())
        

class StyledItemDelegate(QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        data = str(index.data())
        text = data.split('/')[-1]
        option.text = f"{index.row() + 1} -          {text}"

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setGeometry(900, 180, 800, 600)
        self.setWindowTitle("Media Display")
        self.setWindowIcon(QIcon('favicon.png'))

        self.model = listModel()
        self.listview = QListView()
        delegate = StyledItemDelegate(self.listview)
        self.listview.setItemDelegate(delegate)
        self.listview.setModel(self.model)
        self.listview.setModelColumn(1)
        self.listview.setAcceptDrops(True)
        self.listview.setDragEnabled(True)
        self.listview.setDragDropOverwriteMode(True)
        self.listview.viewport().setAcceptDrops(True)
        # self.listview.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.listview.setDropIndicatorShown(True)
        self.listview.setDragDropMode(QAbstractItemView.InternalMove)
        self.init_ui()

    def addImage(self):
        fichier_base, _ = QFileDialog.getOpenFileName(
            self, "select video", QDir.homePath(), "Images (*.png *.xpm *.jpg *.jpeg)"
        )
        if fichier_base:
            self.model.ajouter(fichier_base)

    def clearDb(self):
        query = QSqlQuery()
        query.exec("DELETE FROM fichiers")
        self.model.select()

    def init_ui(self):
        self.add_img_btn = QPushButton("Add image ")
        self.add_img_btn.setFixedWidth(100)
        self.add_img_btn.clicked.connect(self.addImage)
        self.clear_db_btn = QPushButton("clear DB")
        self.clear_db_btn.setFixedWidth(100)
        self.clear_db_btn.clicked.connect(self.clearDb)

        group_btns = QHBoxLayout()
        main_app = QVBoxLayout()
        main_app.addWidget(self.listview)
        main_app.addLayout(group_btns)
        group_btns.addWidget(self.add_img_btn)
        group_btns.addWidget(self.clear_db_btn)
        widget = QWidget()
        vboxlay = QHBoxLayout(widget)
        vboxlay.addLayout(main_app)
        self.setCentralWidget(widget)


if __name__ == "__main__":
    app = QApplication(sys.argv)

    if not create_connection():
        sys.exit(-1)
    window = MainWindow()
    window.setStyleSheet("background-color:#fff;")
    window.show()
    sys.exit(app.exec_()) 
1

There are 1 best solutions below

2
On

I hate to be "that guy" but... what do you actually expect to be able to do, here?

A QSQLTableModel is a representation of an SQL table, which will have its specific ordering. You are able to sort the records in different ways (with .sort() or, if you need anything more complex, by piping it through a QSortFilterProxyModel). Implementing an arbitrary ordering where you can drag and drop elements in different places, though, is not something I would expect to be able to do with an SQL table. If you really need something like that, you would probably have to implement your own custom model, on which you "load" the sql-fetched data but which you then manage on your own. There you can implement your own ordering scheme, which you can manipulate from the view.