QFileDialog как редактор для TableView: как получить результат?

Я использую QFileDialog в качестве редактора для некоторых столбцов в QTableView. Это в основном работает (по модулю некоторых проблем с фокусом, см. здесь):

class DirectorySelectionDelegate(QStyledItemDelegate):    
    def createEditor(self, parent, option, index):
        editor = QFileDialog(parent)
        editor.setFileMode(QFileDialog.Directory)       
        editor.setModal(True)
        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()[0])   

    def updateEditorGeometry(self, editor, option, index):
        r = option.rect
        r.setHeight(600)
        r.setWidth(600)            
        editor.setGeometry(r)

Однако, когда редактор закрыт, я не вижу способа различить Choose и Cancel (или потерял фокус), функция setEditorData вызывается во всех случаях. Я не вижу способа получить результат от QFileDialog, который я получаю как editor, все примеры, которые я могу найти, используют возвращаемое значение от exec_, к которому у меня нет доступа.


person DirkR    schedule 04.04.2014    source источник


Ответы (1)


В setModelData вы можете проверить результат редактора, прежде чем установка данных модели. По умолчанию результатом является QDialog.Rejected, и это должно измениться только в том случае, если пользователь действительно выберет файл:

    def setModelData(self, editor, model, index):
        if editor.result() == QtGui.QDialog.Accepted:
            model.setData(index, editor.selectedFiles()[0])   

ОБНОВЛЕНИЕ:

После некоторого запоздалого тестирования становится очевидным, что независимо от того, как запущен файл-диалог (даже с exec), его result никогда не будет сброшен должным образом в контексте редактора делегата. Поэтому необходима небольшая косвенность. Согласно документам для QFileDialog.filesSelected, этот сигнал всегда и отправляться только тогда, когда диалог принят (даже если нет выбранных файлов). Таким образом, мы можем использовать этот механизм, чтобы вызвать правильный результат диалога, например:

class DirectorySelectionDelegate(QtGui.QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        editor = QtGui.QFileDialog(parent)
        editor.filesSelected.connect(
            lambda: editor.setResult(QtGui.QDialog.Accepted))
        ...

    def setModelData(self, editor, model, index):
        print(editor.result())
        if editor.result() == QtGui.QDialog.Accepted:
            model.setData(index, editor.selectedFiles()[0])
person ekhumoro    schedule 04.04.2014
comment
Интересно, что я всегда получаю 0 (Rejected), независимо от того, нажимаю ли я Choose, Cancel или закрываю диалоговое окно, теряя фокус или просто закрывая его. Что-то здесь не так... - person DirkR; 04.04.2014
comment
@ДиркР. Служит мне правильно, что я не тестировал. Смотрите мой обновленный ответ для правильного решения. - person ekhumoro; 05.04.2014
comment
Гениальный и элегантный. Большое спасибо за ваше решение! - person DirkR; 05.04.2014