Question

I have a QTableView with associated QAbstractTableModel that contains directory names in some columns. I would like to use a QFileDialog as the editor to change those columns. This a little unusual, as the editor is not going to be inside the table cell (not enough space).

I got the basics working using a QStyledItemDelegate:

class DirectorySelectionDelegate(QStyledItemDelegate):

    def createEditor(self, parent, option, index):        
        editor = QFileDialog(parent)
        editor.setFileMode(QFileDialog.Directory)       
        editor.resize(400, 400)
        return editor   

    def setEditorData(self, editor, index):
        val = index.model().data(index, Qt.DisplayRole)
        fs = val.rsplit(os.path.sep, 1)
        if len(fs) == 2:
            bdir, vdir = fs
        else:
            bdir = "."
            vdir = fs[0]

        editor.setDirectory(bdir)        
        editor.selectFile(vdir)                    

    def setModelData(self, editor, model, index):
        model.setData(index, editor.selectedFiles())

When double-clicking the cell it starts a QFileDialog, I can select the directory I want and on Choose it is set in the model.

However, if for whatever reason the QFileDialog loses focus it is closed, and the data is set to the original value. I would prefer the dialog to be open until the user clicks Cancel or Choose, but I cannot find a way to do that.

Bonus question: for some reason the dialog ignores the resize() call and starts up very small (which makes losing the focus all the more likely). How can I change the size of the dialog?

Was it helpful?

Solution

This is expected behaviour.

The standard views are not containers of widgets, each cell is drawn when necessary. The widget used for editing is only created and superimposed on top of the view whenever an editing trigger is generated. The delegate is then called to create the appropriate editing widget and the location and size of the cell are passed in as an argument.

The view retains ownership of the editor widget because, whenever focus is lost, you can obviously not be able to edit anymore so the view deletes the editor.

If you do not pass anything back in the setModelData function, the model will not be updated. It is not correct to say that the model is set back to the original data because it never gets changed in the first place.

What I would suggest you try is setting the QFileDialog to open modally (editor.setModal(true)) so that the dialog has to be closed before focus can be transferred to another widget.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top