Как фильтровать исполняемые файлы с помощью QFileDialog? (Кроссплатформенное решение)

#python #pyqt #pyqt5 #qfiledialog

#python #pyqt #pyqt5 #qfiledialog

Вопрос:

Документация для QFileDialog.GetOpenFileName не дает никаких указаний о том, как фильтровать только исполняемые файлы с помощью a const QString amp;filter = QString() . Вот код для моего действия с использованием PyQt5:

 from PyQt5.QtWidgets import QAction, QFileDialog
from PyQt5.QtCore import QDir
from os import path


class OpenSourcePortAction(QAction):

    def __init__(self, widget, setSourcePort, config, saveSourcePortPath):
        super().__init__('amp;Open Source Port', widget)
        self.widget = widget
        self.setShortcut('Ctrl O')
        self.setStatusTip('Select a source port')
        self.triggered.connect(self._open)
        self.setSourcePort = setSourcePort
        self.config = config
        self.saveSourcePortPath = saveSourcePortPath

    def _open(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(
            self.widget, "Select a source port", self.config.get("sourcePortDir"), "Source Ports (gzdoom zandronum)", options=options)
        if fileName:
            self.saveSourcePortPath(fileName)
            self.setSourcePort(fileName)
 

В Linux, естественно, у меня нет расширений файлов для исполняемых файлов, но мне нужно фильтровать расширения .exe в Windows (для которых я намерен предоставить версию). Кроме того, нет перегруженного метода, который допускает QDir::Executable . Как я могу использовать QFileDialog.getOpenFileName при фильтрации только исполняемые файлы, независимо от того, на какой платформе он запущен?

Ответ №1:

Если вам нужен более персонализированный фильтр, вам нужно использовать proxyModel, но для этого вы не можете использовать метод GetOpenFileName, поскольку экземпляр QFileDialog нелегко доступен, поскольку это статический метод.

 class ExecutableFilterModel(QSortFilterProxyModel):
    def filterAcceptsRow(self, source_row, source_index):
        if isinstance(self.sourceModel(), QFileSystemModel):
            index = self.sourceModel().index(source_row, 0, source_index)
            fi = self.sourceModel().fileInfo(index)
            return fi.isDir() or fi.isExecutable()
        return super().filterAcceptsRow(source_row, source_index)


class OpenSourcePortAction(QAction):
    def __init__(self, widget, setSourcePort, config, saveSourcePortPath):
        super().__init__("amp;Open Source Port", widget)
        self.widget = widget
        self.setShortcut("Ctrl O")
        self.setStatusTip("Select a source port")
        self.triggered.connect(self._open)
        self.setSourcePort = setSourcePort
        self.config = config
        self.saveSourcePortPath = saveSourcePortPath

    def _open(self):
        proxy_model = ExecutableFilterModel()
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        dialog = QFileDialog(
            self.widget, "Select a source port", self.config.get("sourcePortDir")
        )
        dialog.setOptions(options)
        dialog.setProxyModel(proxy_model)
        if dialog.exec_() == QDialog.Accepted:
            filename = dialog.selectedUrls()[0].toLocalFile()
            self.saveSourcePortPath(fileName)
            self.setSourcePort(fileName)