IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Téléchargez Python Discussion :

Afficher le contenu d'un dossier


Sujet :

Téléchargez Python

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 735
    Points : 31 060
    Points
    31 060
    Billets dans le blog
    1
    Par défaut Afficher le contenu d'un dossier
    Bonjour,

    Je vous propose un nouvel élément à utiliser : Afficher le contenu d'un dossier

    Pour faire suite au reader CSV, ce programme affiche le contenu d'un dossier.

    On lui donne un dossier et il affiche dans une zone de droite tous les fichiers du dossier. Et si on sélectionne un fichier, il affiche son contenu dans une zone de gauche.



    Ce programme est disponible en version Python3/Qt5 et en version Python3/Qt6.



    Qu'en pensez-vous ?

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Hello,

    Merci pour le partage,

    Tout fonctionne jusqu'au moment où je souhaite sélectionner un nouveau dossier,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Traceback (most recent call last):  File "/home/fred1599/.../.../test.py", line 296, in __slotLoadFile
        fic=current.data(Qt.ItemDataRole.UserRole)
    AttributeError: 'NoneType' object has no attribute 'data'
    Il faudrait aussi préciser que le module chardet doit être installé avant utilisation.

    EDIT : J'utilise la version PyQt6

  3. #3
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 226
    Points : 4 710
    Points
    4 710
    Par défaut
    bonjour

    Je n'aime pas l'utilisation systématique d'un attribut self.__ihm : code pas classique et énorme dépendance entre chaque objet :

    Par exemple, pour moi, il est beaucoup plus intéressant d'avoir un widget (type myWork) réutilisable tel quel dans tous mes projets. Il suffit juste de supprimer cette dépendance "dure".
    On utilise un code QT plus classique : c'est au "maitre" d'écouter le widget (si il le désire).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    class myMainWindow(QMainWindow):
            def __init__(self, ihm, *args, **kwargs):
                    # La zone qui va afficher le fichier
    		self.__affich=myWork(parent=self.centralWidget())
    		self.__affich.dossierChanged.connect(self.update_status_bar)
    		# self.__affich.fichierChanged.connect(...
     
    	def update_status_bar(self, text):
    		self.statusBar().showMessage(text)
     
    class myWork(QWidget):
    	dossierChanged = pyqtSignal(object)
    	fichierChanged = pyqtSignal(object)
     
            def __init__(self, *args, **kwargs):
                 """" on ne passe plus le dico ihm """
     
            def getDir(self, dossier):
                ...   
                    if not dossier.is_dir():
                            self.dossierChanged.emit(f"{dossier} n'est pas un dossier")
    			#self.__ihm["mainWid"].statusBar().showMessage("{0} n'est pas dossier".format(dossier))
                    ...
                    self.dossierChanged.emit(f"Dossier: {dossier}")
     
            def __work(self, fic):
                    ...
                    self.fichierChanged.emit(f"Fichier: {fic}")
    Pour myWork.__titre, Perso, je ne l'insère pas dans ce widget et émets aussi un signal (intercepté par myMainWindow qui a ça propre zone d'affichage), par conséquent, ce widget est encore plus réutilisable/souple.

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 226
    Points : 4 710
    Points
    4 710
    Par défaut
    Afficher en rouge les fichiers binaires

    Il suffit de passer un paramètre au datas dans le widget : remplacer fichier par (fichier, status).
    Ensuite, on utilise un QStyledItemDelegate que l'on attache à notre widget (valable pour tout type de widget) qui lui va interpréter ce nouveau paramètre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    class myWork(QWidget):
    	# Chargement dossier
    	def getDir(self, dossier):
    		...
    			item=QListWidgetItem(str(p), parent=self.__listFile)
    			item.setData(Qt.ItemDataRole.UserRole, (p, 1))  # on passe un (des) parametre supplémentaire
    			self.__listFile.addItem(item)
     
    # si on ne désire pas attendre le clic utilisateur (plus logique?)
    # on peut déjà passer un paramètre en fonction de ... (type fichier, dossier ou non, erreur, ....)
     
    	# Slot demandant le chargement d'un fichier
            @pyqtSlot(QListWidgetItem, QListWidgetItem)
    	def __slotLoadFile(self, current, prev):
    		fic, status =current.data(Qt.ItemDataRole.UserRole) # changement, ici on récupère un tuple
    		...
    		except (PermissionError, UnicodeDecodeError) as e:
    			current.setData(Qt.ItemDataRole.UserRole, (fic, -1))  # On change l'état : pour démo : -1 == erreur
     
    	# Constructeur
    	def __init__(self, *args, **kwargs):
    		# La zone d'affichage des fichiers du dossier
    		self.__listFile=QListWidget(parent=self)
    		try:
    			self.__listFile.setItemDelegate(FileDelegate(self.__listFile))   # on delège une partie de l'affichage
    		except NameError:
    			pass   # indépendance !!! c'est une option si on réutilise ce widget
    La classe optionnelle qui va gérer une couleur de notre widget
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class FileDelegate(QStyledItemDelegate):
    	ERRORVALUE = QColor(240, 80, 60, 220)    # va être calculée qu'une fois
    	def initStyleOption(self, option, index):
    		if not index.isValid():
    			return None
    		super().initStyleOption(option, index)
    		file, status = index.data(Qt.ItemDataRole.UserRole)
    		if status < 0:
    			option.palette.setBrush(QPalette.ColorRole.Text, self.ERRORVALUE)  # QPalette.ColorRole.Text ce n'est que pour qt6 ?
    		# if file.isdir(): ... ATTENTION appel au "délégé" fait a chaque affichage, donc pas bon
    Note: fichier original avec des tabulations et non espaces, résultat : pas top comme affichage dans ce forum

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 735
    Points : 31 060
    Points
    31 060
    Billets dans le blog
    1
    Par défaut
    Super, merci de votre intérêt

    Citation Envoyé par fred1599 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Traceback (most recent call last):  File "/home/fred1599/.../.../test.py", line 296, in __slotLoadFile
        fic=current.data(Qt.ItemDataRole.UserRole)
    AttributeError: 'NoneType' object has no attribute 'data'
    Ah oui effectivement. J'ai testé et (oserais-je dire que je n'avais pas testé avant ? certes pas, juste que j'avais pas fait gaffe à ce détail)
    Cela vient du fait que quand on change de dossier, cela vide la liste des fichiers (zone de droite) mais cette zone associe un signal "itemChanged" à un slot (nommé "slotLoadFile").
    Donc quand la zone est vidée, c'est comme si l'item changeait => ça appelle le slot
    En plus j'aurais dû y penser car on a les même soucis avec tous les objets Qt => dès qu'on les met à jour manuellement ça appelle le signal "j'ai été mis à jour" !!!
    Il y a plusieurs façons de corriger. On peut tester l'item à l'appel du slot (s'il est à None) mais je pense que la meilleure solution est de rajouter self.__listFile.blockSignals(True) en ligne 281 et self.__listFile.blockSignals(False) en ligne 283 (de chaque côté du clear de la ligne 282 donc). Ce sera corrigé après la pub

    Citation Envoyé par fred1599 Voir le message
    Il faudrait aussi préciser que le module chardet doit être installé avant utilisation.
    Je le croyais installé par défaut ??? PS: je bosse sous Linux Xubuntu...

    Citation Envoyé par papajoker Voir le message
    Je n'aime pas l'utilisation systématique d'un attribut self.__ihm : code pas classique et énorme dépendance entre chaque objet
    Oui je comprends que la dépendance peut gêner. C'est le seul moyen que j'ai trouvé pour que les fenêtres se connaissent les unes les autres. De cette façon chaque objet connait
    • l'application
    • la fenêtre principale
    • son parent
    • et d'autres détails comme ici le dossier traité (dans mes projets il y a aussi la bdd, la configuration etc.)

    J'ai conscience que certains éléments sont récupérables plus ou moins facilement par Qt mais quand j'ai trouvé cette méthode je trouvais que c'était un bon raccourci. Bon désolé que cela gêne je vais étudier attentivement ton chouette exemple

    Citation Envoyé par papajoker Voir le message
    Afficher en rouge les fichiers binaires...
    Super ça aussi ça va me plaire. Mais (désolé) il va me falloir un peu de temps pour assimiler

    Citation Envoyé par papajoker Voir le message
    Note: fichier original avec des tabulations et non espaces, résultat : pas top comme affichage dans ce forum
    Là je pige pas: normalement on le télécharge, il ne s'affiche pas dans le forum ???

    Encore merci à tous, j'ai adoré vos remarques

  6. #6
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Citation Envoyé par Sve@r
    Je le croyais installé par défaut ??? PS: je bosse sous Linux Xubuntu...
    Moi aussi, mais je ne pense pas que le problème soit lié au système d'exploitation

    lien PyPi chardet

    Par contre je ne vois pas où tu l'utilises...

    Citation Envoyé par Sve@r
    Ce sera corrigé après la pub
    C'est l'essentiel, la manière dont tu gères le bug te revient...


    J'ai un peu plus de temps pour visionner ton code, quelques observations (ce qui est dit par @papajoker est raccord avec ce que je pense aussi).

    Citation Envoyé par Sve@r
    from PyQt6.QtCore import *
    from PyQt6.QtGui import *

    from PyQt6.QtWidgets import *
    ça prend du temps, mais c'est essentiel, l'utilisateur s'en fou, moi, beaucoup moins en tant que développeur, j'aime savoir quels sont les widgets utilisés. Comme c'est dédié aux deux types sur ce forum, je trouve dommage de s'en priver...

    C'est inutile, lors de ton instanciation de myMainWindow dans myAppli, tu utilises en paramètre un dictionnaire écrit en brut...


    Dans ton code j'ai trouvé difficile de faire le lien entre le nom de tes méthodes et le nom de chaque classe, il y a de l'anglais et du français, perso, la syntaxe devrait toujours être écrite en anglais et évidemment le texte se décide par le développeur selon le besoin de l'application (français ou international).

    Je pense que tu as voulu raccourcir le code au maximum, je peux me tromper... (n'hésite pas à le dire) mais en ce qui me concerne, il serait bien plus long, car j'aurai préféré plus séparé les responsabilités et leurs actions. C'est un choix technique qui ne regarde que moi . Il n'y aurait pas qu'un seul module et ce nombre de classes.

  7. #7
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    903
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 903
    Points : 1 589
    Points
    1 589
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Par curiosité j'ai voulu voir le code, mais bon lorsque j'essaie de télécharger :
    Vous devez vous connecter pour accéder à cette partie du site
    . Je suis pourtant bien connecté et avec noscript mis en veilleuse
    Comme c'était juste pour voir je ne vais pas contacter un administrateur...
    Ce message juste pour te remercier, car tu m'inspires l'envie de faire de même avec kivy.

  8. #8
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 226
    Points : 4 710
    Points
    4 710
    Par défaut
    Ce sont 2 sites différents developpez.net et developpez.com, il suffit de se re-connecter avec les mêmes identifiants.

    ---------------------

    Note :
    Existe déjà le modèle QT QFileSystemModel qui permet l'affichage d'un répertoire dans un treeview, listview ou tableview.

    Exemple (prévisualise fichiers texte et certaines images):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    #!/usr/bin/env python
     
    from pathlib import Path
    import sys
    try:
        from PySide6 import QtCore, QtGui, QtWidgets
    except ImportError:
        print("ERREUR: installez pyside 6 !")
        exit(13)
     
     
    class WinMain(QtWidgets.QMainWindow):
        """ Application simple """
     
        def __init__(self, directory):
            super(WinMain, self).__init__()
     
            self.model = QtWidgets.QFileSystemModel()
            self.model.setFilter(QtCore.QDir.Files | QtCore.QDir.NoDotAndDotDot)
     
            self.resize(600, 520)
            if layout := QtWidgets.QVBoxLayout():  # décalage juste pour mon visuel
                splitter = QtWidgets.QSplitter()
                tmp = QtWidgets.QHBoxLayout(splitter)
                self.content = QtWidgets.QLabel()
                self.content.setText("Voir image")
                self.content.setGeometry(QtCore.QRect(0, 0, 300, 300))
                tmp.addWidget(self.content)
                self.content.setMaximumWidth(600)
                self.list = QtWidgets.QListView(splitter)
                self.list.setModel(self.model)
                self.list.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
                self.list.customContextMenuRequested.connect(self.onContextMenu)
                self.list.doubleClicked.connect(self.afficher)
     
                layout.addWidget(splitter)
                widget = QtWidgets.QWidget()
                widget.setLayout(layout)
                self.setCentralWidget(widget)
            self.statusBar()
            self.directory = directory
     
        @property
        def directory(self):
            return self._directory
        @directory.setter
        def directory(self, value):
            """on change de répertoire"""
            self._directory = value
            self.content.clear()
            self.content.setText("Voir image/fichier texte")
            self.content.setWordWrap(True)
            self.model.setRootPath(self.directory)
            self.list.setRootIndex(self.model.index(self.directory))
            self.setWindowTitle(self.directory)
            self.statusBar().showMessage(self.directory)
            print("root dir:", self.model.rootDirectory())
     
        def changeDir(self):
            choix=QtWidgets.QFileDialog.getExistingDirectory(
                self,
                "Choisissez votre dossier",
                self.directory,
                QtWidgets.QFileDialog.Option.ShowDirsOnly | QtWidgets.QFileDialog.Option.ReadOnly,
            )
            if choix:
                self.directory = choix
     
        def afficher(self, item):
            #file_ = self.model.filePath(item) # même chose que ligne suivante
            file_ =item.data(QtWidgets.QFileSystemModel.Roles.FilePathRole)
            print(file_)
            pix = QtGui.QPixmap(file_)
            # ("png", "jpeg", "jpg", "svg", "bmp", "gif", 'ico', "pdf")
            if not pix.isNull():
                self.content.setPixmap(pix)
                sizem = min(self.content.width(), self.content.height())
                size = QtCore.QSize(sizem, sizem)
                myScaledPixmap = pix.scaled(size, QtCore.Qt.KeepAspectRatio)
                self.content.setPixmap(myScaledPixmap)
            else:
                try:
                    # que appercu car pas de scrolling
                    self.content.setText(Path(file_).read_text()[0:412])
                except UnicodeDecodeError:
                    self.content.setText("fichier incompatible  •`_´•")
                    self.statusBar().showMessage("")
                    return
            self.statusBar().showMessage(file_)
     
        def onContextMenu(self, point):
            menu = QtWidgets.QMenu()
            notUsed = menu.addAction('-')
            notUsed.setEnabled(False)
            menu.addSeparator()
            aInfo = menu.addAction("Changer de dossier...")
            aRefresh = menu.addAction("Actualiser")
            action = menu.exec(self.list.mapToGlobal(point))
            if action == aInfo:
                self.changeDir()
            if action == aRefresh:
                self.directory = self.directory
     
     
    def run(directory):
        app = QtWidgets.QApplication(sys.argv)
        ico = QtGui.QIcon.fromTheme("folder")
        app.setWindowIcon(ico)
     
        trans = QtCore.QTranslator()
        trans.load('qt_fr', QtCore.QLibraryInfo.path(QtCore.QLibraryInfo.LibraryPath.TranslationsPath))
        QtCore.QCoreApplication.installTranslator(trans)    # pour avoir les dialogues en fr
     
        win = WinMain(directory)
        win.show()
        sys.exit(app.exec())
     
    if __name__ == "__main__":
        run(QtCore.QDir.currentPath())
    Pour changer de répertoire : clic droit

    pySyde/pyQt sont légèrement différents !
    Par exemple, PyQt6.QtGui.QFileSystemModel, PySide6.QtWidgets.QFileSystemModel

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 735
    Points : 31 060
    Points
    31 060
    Billets dans le blog
    1
    Par défaut
    Super extra, j'ai de quoi m'amuser durant quelques jours.
    Maintenant quelques réponses plus précises...
    Citation Envoyé par fred1599 Voir le message
    Moi aussi, mais je ne pense pas que le problème soit lié au système d'exploitation... Par contre je ne vois pas où tu l'utilises... (à propos de chardet)
    Zut je n'arrive pas à retrouver l'idée qui m'a fait penser que c'était installé d'office. Ceci dit effectivement il n'est pas utile. J'avais un moment pensé à afficher l'encoding du fichier traité (comme je fais pour le readerCSV) et là il aurait servi puis ai abandonné l'idée et ai oublié de l'enlever (history code)...

    Citation Envoyé par fred1599 Voir le message
    C'est inutile, lors de ton instanciation de myMainWindow dans myAppli, tu utilises en paramètre un dictionnaire écrit en brut...(à propos self.__ihm=dict(ihm))
    En fait si la copie est nécessaire (enfin dans ma tête) car la fenêtre qui récupère ce dictionnaire modifie certaines clefs ("self" et "parent" notamment). Or il ne faut pas modifier le dico de l'appelant.
    C'était le truc que j'avais trouvé à mes débuts pour que les widgets Qt puissent connaître leur hiérarchie (chaque widget connait ainsi son parent). Mais suite à vos très sympatiques remarques et conseils j'ai revu le concept (et ai corrigé).

    Citation Envoyé par fred1599 Voir le message
    ça prend du temps, mais c'est essentiel, l'utilisateur s'en fou, moi, beaucoup moins en tant que développeur, j'aime savoir quels sont les widgets utilisés. Comme c'est dédié aux deux types sur ce forum, je trouve dommage de s'en priver...
    Là je pense que tu préfèrerais que je remplace from PyQt5.QtWidgets import * par from PyQt5.QtWidgets import QAppli, QMainWindow, QWidget, QMenuBar, QListWidget, QListWidgetItem, etc. c'est ça ?
    Ca doit être énormément de boulot à faire et à maintenir (regarde ce pauvre chardet que j'ai même pas pensé à enlever). Est-ce vraiment nécessaire ? Par exemple pour les autres import tu le fais aussi ???

    Citation Envoyé par fred1599 Voir le message
    Dans ton code j'ai trouvé difficile de faire le lien entre le nom de tes méthodes et le nom de chaque classe, il y a de l'anglais et du français, perso, la syntaxe devrait toujours être écrite en anglais
    Oui je suis d'accord. L'anglais (ex "open") est plus pratique que le français (ex "ouvre", "ouvrir" ???) mais bon il y a les bonnes résolutions et la motivation de s'y tenir...

    Citation Envoyé par fred1599 Voir le message
    je pense que tu as voulu raccourcir le code au maximum, je peux me tromper... (n'hésite pas à le dire) mais en ce qui me concerne, il serait bien plus long, car j'aurai préféré plus séparé les responsabilités et leurs actions. C'est un choix technique qui ne regarde que moi . Il n'y aurait pas qu'un seul module et ce nombre de classes.
    Oui là aussi je suis d'accord. Dans un vrai projet chaque objet a son propre source. Mais là je n'avais pas envie de demander à télécharger un zip donc j'ai tout mis dans un seul code unique un peu long mais qui se télécharge en une fois. A regarder comme un "proof of concept" ou "comment utiliser telle ou telle techno" (à l'image de mes autres exemples plus simples).


  10. #10
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Citation Envoyé par Sve@r
    Zut je n'arrive pas à retrouver l'idée qui m'a fait penser que c'était installé d'office. Ceci dit effectivement il n'est pas utile. J'avais un moment pensé à afficher l'encoding du fichier traité (comme je fais pour le readerCSV) et là il aurait servi puis ai abandonné l'idée et ai oublié de l'enlever (history code)...
    Les oublis ça arrive ! on est pas des machines, par contre, j'utilise un IDE qui me permet de contrôler et de voir cela...

    Citation Envoyé par Sve@r
    En fait si la copie est nécessaire...
    Après tests, je n'ai pas cette impression

    Citation Envoyé par Sve@r
    Ca doit être énormément de boulot à faire et à maintenir
    Pas tant que ça, c'est précis, léger (surtout que PyQt est loin d'être le module le plus léger qui soit) et c'est respecter la PEP8 (qui n'est qu'une convention mais on a pas de norme)

    Citation Envoyé par Sve@r
    A regarder comme un "proof of concept" ou "comment utiliser telle ou telle techno" (à l'image de mes autres exemples plus simples).
    Ok je comprends, c'est déjà bien d'avoir passé du temps sur le sujet

  11. #11
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 483
    Points : 9 282
    Points
    9 282
    Billets dans le blog
    6
    Par défaut
    Bonjour Sve@r

    Curieusement, quand j'ai vu le titre de ton post, j'ai pensé que tu utilisais un QTreeView avec le modèle QFileSystemModel, et j'ai été surpris que ce ne soit pas le cas.

    C'est pourtant ce qu'il y a de plus pratique. Voilà un petit code de principe en PyQt5:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    # -*- coding: utf-8 -*-
     
    import sys
    import os
     
    from PyQt5.QtCore import QLocale, QTranslator, QLibraryInfo
    from PyQt5.QtGui import QFont#, QIcon
    from PyQt5.QtWidgets import (QApplication, QFileSystemModel, QTreeView,
                                 QFrame, QGridLayout, QMainWindow, QStyleFactory)
     
    ##############################################################################
    class NavigFichiers(QMainWindow):
     
        #=========================================================================
        def __init__(self, repertoire, parent=None):
            super().__init__(parent)
     
            self.resize(800, 600)
            self.setWindowTitle("Navigateur de fichiers")
     
            # crée le modèle
            model = QFileSystemModel()
            model.setRootPath(repertoire)
     
            #Crée le QTreeView et intégre le modèle
            self.view = QTreeView()
            self.view.setModel(model)
            self.view.setRootIndex(model.index(repertoire))
     
            # Police de caractères à utiliser
            font = QFont()
            font.setStyleHint(QFont.Monospace)
            self.view.setFont(font)
     
            # largeur de la colonne 0
            self.view.setColumnWidth(0, 350)
     
            # place le QTreeView dans la fenêtre
            self.setCentralWidget(QFrame())
            layout = QGridLayout()
            layout.addWidget(self.view, 0, 0)
            self.centralWidget().setLayout(layout)
     
            # Etablit le lien entre signal et méthode
            self.view.clicked.connect(self.clicligne)
     
            # initialise la ligne de status pour les messages
            self.statusbar = self.statusBar()
            self.statusbar.showMessage("")
     
        #=========================================================================
        def clicligne(self, qindex):
            """affiche en bas de page le chemin cliqué
            """
            chemin =  self.view.model().filePath(qindex)
            if os.path.isdir(chemin):
                message = "Répertoire: " + chemin
            else:
                message = "Fichier: " + chemin
            self.statusbar.showMessage(message)
     
    ##############################################################################
    if __name__ == '__main__':
     
        #========================================================================
        # Répertoire d'exécution avec ou sans pyinstaller (onedir ou onefile)
        if getattr(sys, 'frozen', False):
            REPEXE = sys._MEIPASS # programme traité par pyinstaller
        else:
            REPEXE = os.path.dirname(os.path.abspath(__file__)) # prog. normal py
     
        #========================================================================
        # initialise la bibliothèque graphique
        app = QApplication(sys.argv)
     
        #========================================================================
        #met la même icône pour toutes les fenêtres du programme
        #app.setWindowIcon(QIcon(os.path.join(REPEXE, "navigfichiers.png")))
     
        #========================================================================
        # met les tooltips à fond jaune clair dans toute l'application
        #app.setStyleSheet("QToolTip {background-color: #ffff99; border: 1px solid black}")
     
        #========================================================================
        # style pour toute l'application
        if "Fusion" in [st for st in QStyleFactory.keys()]:
            app.setStyle(QStyleFactory.create("Fusion"))
        elif sys.platform=="win32":
            app.setStyle(QStyleFactory.create("WindowsVista"))
        elif sys.platform=="linux":
            app.setStyle(QStyleFactory.create("gtk"))
        elif sys.platform=="darwin":
            app.setStyle(QStyleFactory.create("macintosh"))
        # pour trouver les styles disponibles:
        # print([st for st in QStyleFactory.keys()])
        # Windows 11: ['WindowsVista', 'Windows', 'Fusion']
     
        app.setPalette(QApplication.style().standardPalette())
     
        #========================================================================
        # assure la traduction automatique du conversationnel à la locale
        locale = QLocale.system().name()
        translator = QTranslator()
        reptrad = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
        translator.load("qtbase_" + locale, reptrad) # qtbase_fr.qm
        app.installTranslator(translator)
     
        #========================================================================
     
        repertoire = "C:\\"
     
        navigfichiers = NavigFichiers(repertoire)
        navigfichiers.show()
        sys.exit(app.exec_())
    La navigation est facile, et chaque clic sur une ligne, lance la méthode "clicligne" (j'ai été très inspiré pour son nom... ), qui se contente d'afficher le nom cliqué en bas de fenêtre avec son chemin. Mais cette méthode peut faire n'importe quoi d'autre, y compris afficher le contenu du fichier cliqué dans une autre fenêtre avec un QTextEdit si c'est un fichier texte, ou même lancer VLC si c'est une vidéo.

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 735
    Points : 31 060
    Points
    31 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    et j'ai été surpris que ce ne soit pas le cas.
    Euh oui parce que voilà en fait je connaissais pas

    Qt est tellement énorme que pour tout connaitre...

    Mais je suis super heureux de ce topic car tout le monde arrive et montre ses propres techniques Qt

  13. #13
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Hello,

    Tant qu'on est à montrer certaines techniques, voici un exemple simple de ce à quoi peut ressembler la clean architecture avec ton projet.

    Repo GitHub

    L'objectif est que quelque soit le module que vous souhaitez utiliser pour votre interface graphique, vous ayez un minimum de changement ou ajout à faire. L'autre objectif est de ne rien supprimer et de rendre modulable graphiquement le projet.

    Chaque interface graphique nouvellement créée est dépendante des méthodes obligatoires de la classe Abstraite UIPort.
    On sépare la partie métier de l'interface, même si quelque fois cela peut paraître inutile, sa modification sera simple et sa recherche aussi (évite d'aller dans les méandres d'un code mélangé avec Qt par ex.)

    L'ajout d'une interface tkinter peut se faire dans infrastructure/tkadapter.py avec stricto les mêmes méthodes d'affichage

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 426
    Points : 37 008
    Points
    37 008
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Tant qu'on est à montrer certaines techniques, voici un exemple simple de ce à quoi peut ressembler la clean architecture avec ton projet.
    Wouah, la prose d'Uncle Bob, ça faisait longtemps que je ne l'avais pas croisée!
    Ça peut aider à présenter l'architecture et les composants d'un projet à des managers ou au kickoff d'une équipe de développeurs.
    Les mains dans le cambouis, on réalisera que c'est tellement stratosphérique que ça n'aide qu'un tout petit peu.

    Il y a des lustres entre le turluware du lancement du projet et le pot de la mise en production.

    - W

  15. #15
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Citation Envoyé par wiztricks
    Les mains dans le cambouis, on réalisera que c'est tellement stratosphérique que ça n'aide qu'un tout petit peu.
    Il y a des lustres entre le turluware du lancement du projet et le pot de la mise en production.
    Difficile d'annoncer ça me concernant, j'ai très peu vue de projets où ce genre d'architecture a été utilisée.
    Un seul projet avec cette architecture en production, et c'était assez naturel de travailler dessus et s'y retrouver facilement.
    Très peu de développeurs connaissent cette architecture, quand j'en parle, c'est inconnu au bataillon... donc quand tu dis "on réalisera", c'est qui on ?

    Citation Envoyé par wiztricks
    Ça peut aider à présenter l'architecture et les composants d'un projet à des managers
    Ce que j'appelle manager, sont des personnes qui se foutent du moyen dont l'équipe va développer l'application.
    À la rigueur, un lead dev peut-être un manager, mais comme très souvent c'est lui qui s'occupe de l'architecture de l'application...

    Citation Envoyé par wiztricks
    c'est tellement stratosphérique que ça n'aide qu'un tout petit peu
    Tu dois avoir vu beaucoup de projets avec cette architecture pour conclure cela, car en ce qui me concerne, le seul projet ayant expérimenté cette architecture a été concluant.

  16. #16
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 735
    Points : 31 060
    Points
    31 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Tant qu'on est à montrer certaines techniques, voici un exemple simple de ce à quoi peut ressembler la clean architecture avec ton projet.

    Repo GitHub
    Suis désolé suis pas chez-moi en ce moment donc c'est un peu difficile de suivre (surtout que mon portable est bien mais pas non plus super pratique). Mais dès que je rentre je prends le temps de tester (j'ai essayé ici mais comme je le dis, avec mon portable... et puis il semble qu'il y ait conflit entre Qt5 (qui est toujours là) et Qt6 (que j'ai installé pour l'occasion) car aussi bien avec ton code que celui de papajoker j'ai eu un message bizarre
    qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.).

    Après cette architecture semble effectivement bien posée mais peut-être qu'elle est trop démesurée. Oui pour une compagnie aérienne ou la SNCF elle sera utile mais pour les petits projets auxquels je suis habitué (c'est ça chez-nous, plein de petits projets mais qui restent petits).

    Mais (donc tout ce qui a dit précédemment est annulé) merci encore de vos interventions qui m'apprennent plein de trucs.

  17. #17
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Citation Envoyé par Sve@r
    Après cette architecture semble effectivement bien posée mais peut-être qu'elle est trop démesurée.
    Biensûr qu'elle est démesurée, elle est surtout présente pour montrer le principe. Quoi de mieux pour cela que de le faire sur un exemple simple ?

    Citation Envoyé par Sve@r
    qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found
    Je pense que cette page est liée à ton problème.

    Citation Envoyé par Sve@r
    Oui pour une compagnie aérienne ou la SNCF elle sera utile mais pour les petits projets auxquels je suis habitué (c'est ça chez-nous, plein de petits projets mais qui restent petits).
    Après petit, moyen ou grand projet, toi en tant que développeur, peut décider selon beaucoup de critères de démarrer avec cette architecture et même si ça ne tend pas à évoluer dans le futur, ça a au moins le mérite d'être structurer et d'avoir les avantages sur de la TMA par exemple.

  18. #18
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 226
    Points : 4 710
    Points
    4 710
    Par défaut
    trop démesurée
    Perso, je ne trouve pas

    Simplement pour moi, comme expliqué dans un autre sujet, cet exemple est beaucoup trop simple par rapport à mes attentes. Et j'ai peur que cette architecture ne soit bonne que pour des projets très simples (pour être exact : une GUI relativement simple en fait).
    Ici, je parle uniquement du code python et non de l'arborescence des fichiers

    ----------------
    Pour moi, pyside est installé en tant que paquet linux et pas par pip, donc aucun risque de problème de dépendance !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    pactree -l pyside6 | grep xcb | sort -u
    # paquets archlinux !
    libxcb
    libxcb>=1.7
    xcb-proto
    xcb-util
    xcb-util-cursor
    xcb-util-image
    xcb-util-keysyms
    xcb-util-renderutil
    xcb-util-wm
    note : exactement même sortie avec pactree -l python-pyqt6 | grep xcb | sort -u

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 426
    Points : 37 008
    Points
    37 008
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Très peu de développeurs connaissent cette architecture, quand j'en parle, c'est inconnu au bataillon... donc quand tu dis "on réalisera", c'est qui on ?
    Heureusement car c'est plutôt l'architecture d'un système d'information et non l'architecture d'une application logicielle.
    "On" = ceux qui vont produire les livrables.
    Ici le livrable est l'architecture elle même au sens une organisation du monde suivant nombre de principes.
    Le boulot va être de reformuler le réel dans cette organisation abstraite.

    Citation Envoyé par fred1599 Voir le message
    Ce que j'appelle manager, sont des personnes qui se foutent du moyen dont l'équipe va développer l'application.
    À la rigueur, un lead dev peut-être un manager, mais comme très souvent c'est lui qui s'occupe de l'architecture de l'application...
    Si le projet est assez critique (pour la boite) ou couteux, il y aura des tas d'interlocuteurs/intervenants qui auront leur mot à dire et qui devront avoir une idée de l'état d'avancement des livrables. De fait on a un truc multidimensionnels (ce qui intéresse X n’intéresse pas forcément Y) et à créer des "référentiels" pour avoir différente mises en perspectives (en gardant la cohérence).
    Et cela ne fait du sens que pour des projets un peu lourd...


    Citation Envoyé par fred1599 Voir le message
    Tu dois avoir vu beaucoup de projets avec cette architecture pour conclure cela, car en ce qui me concerne, le seul projet ayant expérimenté cette architecture a été concluant.
    Non je connais "uncle bob". On peut prendre plaisir à l'écouter car ce qu'il raconte est bien construit/pensé.... mais quand on revient dans le monde réel, on ne sait pas trop quoi faire de tout çà.

    - W

  20. #20
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 938
    Points : 7 347
    Points
    7 347
    Par défaut
    Citation Envoyé par wiztricks
    Heureusement car c'est plutôt l'architecture d'un système d'information et non l'architecture d'une application logicielle.
    Pour avoir lu le bouquin, je dirais les deux... dans le sujet actuel la Clean Architecture offre un cadre permettant de séparer clairement les fonctionnalités métier des détails d'implémentation tels que les bases de données et les interfaces utilisateur, mais aussi, aide à structurer le projet de façon à isoler le cœur logique de l'application des éléments périphériques. Cela signifie que les modifications apportées à l'interface utilisateur, aux méthodes de stockage des données ou aux services web externes ont un impact minimal sur la logique métier de l'application.

    Citation Envoyé par wiztricks
    Si le projet est assez critique (pour la boite) ou couteux, il y aura des tas d'interlocuteurs/intervenants qui auront leur mot à dire et qui devront avoir une idée de l'état d'avancement des livrables.
    Biensûr, mais ils ne peuvent éviter les conseils techniques, et s'ils ne les écoute pas, eh bien tant pis pour eux !

    Citation Envoyé par wiztricks
    Non je connais "uncle bob". On peut prendre plaisir à l'écouter car ce qu'il raconte est bien construit/pensé.... mais quand on revient dans le monde réel, on ne sait pas trop quoi faire de tout çà.
    J'avoue qu'après avoir lu le bouquin, j'ai eu un peu de mal à visualiser comment mettre en pratique, mais au final il faut suivre les grands principes (séparation des préoccupations (Separation of Concerns - SoC), le principe de l'inversion des dépendances et le principe de substitution de Liskov) et l'idée principale, c'est d'organiser le code de manière à ce que les dépendances circulent vers l'extérieur, depuis les couches les plus internes (comme le domaine et les cas d'utilisation) vers les couches externes (comme l'interface utilisateur et les infrastructures), ce qui facilite les tests et la maintenance. Selon le projet (plus ou moins gros), on adapte pour éviter trop de découpages inutiles.

Discussions similaires

  1. Afficher le contenu d'un dossier IMG
    Par actarus4444 dans le forum Langage
    Réponses: 6
    Dernier message: 28/08/2009, 17h33
  2. Afficher le contenu d'un dossier dans une page HTML
    Par mauriceuh dans le forum Balisage (X)HTML et validation W3C
    Réponses: 23
    Dernier message: 20/02/2007, 17h57
  3. afficher le contenu d'1 dossier ds ListBox
    Par meera dans le forum MFC
    Réponses: 16
    Dernier message: 16/10/2006, 18h38
  4. Afficher le contenu d'un dossier
    Par mpascolo dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 12/10/2006, 15h59
  5. afficher le contenu d'un dossier distant
    Par roots_man dans le forum ASP
    Réponses: 3
    Dernier message: 04/02/2005, 18h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo