eric7/EricWidgets/EricDirFileDialog.py

Thu, 30 Dec 2021 11:17:58 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 30 Dec 2021 11:17:58 +0100
branch
eric7
changeset 8881
54e42bc2437a
parent 8406
45d7d0eec4d3
permissions
-rw-r--r--

Updated copyright for 2022.

# -*- coding: utf-8 -*-

# Copyright (c) 2021 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a dialog to select files and directories simultaneously.
"""

from PyQt6.QtCore import pyqtSlot, QItemSelection
from PyQt6.QtGui import QFileSystemModel
from PyQt6.QtWidgets import QFileDialog, QPushButton, QLineEdit, QTreeView


class EricDirFileDialog(QFileDialog):
    """
    Derived QFileDialog to select files and directories simultaneously.
    
    For this purpose the none native file dialog is used.
    """
    def __init__(self, parent=None, caption="", directory="", filterStr=""):
        """
        Constructor
        
        @param parent parent widget of the dialog
        @type QWidget
        @param caption window title of the dialog
        @type str
        @param directory working directory of the dialog
        @type str
        @param filterStr filter string for the dialog
        @type str
        """
        self.__selectedFilesFolders = []
        
        super().__init__(parent, caption, directory, filterStr)
        self.setFileMode(QFileDialog.FileMode.ExistingFiles)
    
    @pyqtSlot()
    def exec(self):
        """
        Public slot to finalize initialization and start the event loop.
        
        @return accepted or rejected
        @rtype QDialog.DialogCode
        """
        self.__openBtn = self.findChildren(QPushButton)[0]
        self.__fileNameEdit = self.findChild(QLineEdit)
        self.directoryEntered.connect(self.on_directoryEntered)
        self.__tree = self.findChild(QTreeView)
        self.__tree.selectionModel().selectionChanged.connect(
            self.on_selectionChanged)
        
        return QFileDialog.exec(self)
    
    @pyqtSlot()
    def accept(self):
        """
        Public slot to update the list with the selected files and folders.
        """
        # Avoid to close the dialog if only return is pressed
        if not self.__openBtn.isEnabled():
            return
        
        self.__selectedFilesFolders = [
            x.data(QFileSystemModel.Roles.FilePathRole)
            for x in self.__tree.selectionModel().selectedIndexes()
            if x.column() == 0]
        
        self.hide()
    
    @pyqtSlot(str)
    def on_directoryEntered(self, directory):
        """
        Private slot to reset selections if another directory was entered.
        
        @param directory name of the directory entered
        @type str
        """
        self.__tree.selectionModel().clear()
        self.__fileNameEdit.clear()
        self.__openBtn.setEnabled(False)
    
    @pyqtSlot(QItemSelection, QItemSelection)
    def on_selectionChanged(self, selected, deselected):
        """
        Private method to determine the selected files and folders and update
        the line edit.
        
        @param selected newly selected entries
        @type QItemSelection
        @param deselected deselected entries
        @type QItemSelection
        """
        selectedItems = self.__tree.selectionModel().selectedIndexes()
        if self.__tree.rootIndex() in selectedItems or selectedItems == []:
            return
        
        selectedFiles = [x.data(QFileSystemModel.Roles.FileNameRole)
                         for x in selectedItems if x.column() == 0]
        enteredFiles = self.__fileNameEdit.text().split('"')
        enteredFiles = [x.strip() for x in enteredFiles if x.strip()]
        
        # Check if there is a directory in the selection. Then update the
        # lineEdit.
        for selectedFile in selectedFiles:
            if selectedFile not in enteredFiles:
                txt = '" "'.join(selectedFiles)
                if len(selectedFiles) > 1:
                    txt = '"{0}"'.format(txt)
                self.__fileNameEdit.setText(txt)
                break
    
    @staticmethod
    def getOpenFileAndDirNames(parent=None, caption="", directory="",
                               filterStr="", options=None):
        """
        Static method to get the names of files and directories for opening it.
        
        @param parent parent widget of the dialog
        @type QWidget
        @param caption window title of the dialog
        @type str
        @param directory working directory of the dialog
        @type str
        @param filterStr filter string for the dialog
        @type str
        @param options various options for the dialog
        @type QFileDialog.Options
        @return names of the selected files and folders
        @rtype list of str
        """
        if options is None:
            options = QFileDialog.Option(0)
        options |= QFileDialog.Option.DontUseNativeDialog
        dlg = EricDirFileDialog(parent, caption, directory, filterStr)
        dlg.setOptions(options)
        dlg.exec()
        
        return dlg.__selectedFilesFolders

eric ide

mercurial