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

Python Discussion :

Présentation d'une app (qui existe peut-être déja)


Sujet :

Python

  1. #1
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut Présentation d'une app (qui existe peut-être déja)
    Salut,

    Travaillant sur différents OS, Un iMac en poste fixe et un portable (en dual boot Windows/Linux), j’ai pris la fâcheuse manie de faire depuis mon Mac Cmd/c (équivalent de Ctrl/c) et Ctrl/v sur mon portable en espérant que par magie le presse-papier du Mac allait se transférer sur le portable….
    Ayant un compte Dropbox, je me suis dit pourquoi ne pas automatiser le copier/coller en passant par le cloud.

    Il y a des pré-requis :
    Avoir un compte Dropbox (mais je pense qu’avec un autre cloud ça fonctionne aussi, suffit de modifier le script)
    Avoir installé PyQt5

    Son fonctionnement :
    Copier le contenu du presse-papier dans Dropbox qui sera automatiquement récupérer dans le presse-papier d’un autre ordinateur .
    Alors bien-sur vos remarques et commentaires sont les bienvenus.

    Ci-joint le zip contenant le script et les png.

    https://www.dropbox.com/s/p6suav3l5r...Cloud.zip?dl=0

    Le script :
    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
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
     
    # -*- Coding: utf-8 -*-
    # Created by Diablo76 on 14/02/2023 -- 07:41:27.
     
    import os
    import sys
    from pathlib import Path
     
    from PyQt5.QtCore import Qt, QTimer
    from PyQt5.QtGui import QIcon, QImage, QPixmap
    from PyQt5.QtWidgets import (
        QAction,
        QApplication,
        QDesktopWidget,
        QLabel,
        QMainWindow,
        QMenu,
        QMessageBox,
        QSystemTrayIcon
    )
     
    # Constantes globales
    _VERSION = "1.06"
    CLOUD = "Dropbox"
    PATH_CLOUD = f"{Path.home()}{os.sep}{CLOUD}{os.sep}.ClipboardToCloud{os.sep}"
    PATH_FILE = PATH_CLOUD + "clipboard.data"
    TITLE = f"Clipboard To {CLOUD} {_VERSION}"
     
     
    class ToolTip(QLabel):
        """Affichage d'un QLabel d'apparence QToolTip"""
        def __init__(self):
            super().__init__()
            self.setWindowFlags(Qt.ToolTip)  # type: ignore
            self.setStyleSheet(
                "border: 1px solid black; background-color: rgb(200,200,180)"
            )
            self.setWindowOpacity(0.8)
            self.center = QDesktopWidget().availableGeometry().center()
     
        def show(self):
            """Affichage du tooltip au centre de l'écran
            avec une durée de 2.5 secondes"""
            super().show()
            self.move(
                int(self.center.x() - self.width() / 2),
                int(self.center.y() - self.height() / 2)
            )
            QTimer.singleShot(2500, self.hide)
     
     
    class MainWindow(QMainWindow):
        """MainWindow"""
        def __init__(self):
            super().__init__()
            self.directory_exist()
            self.tray = QSystemTrayIcon()
            self.tool_tip = ToolTip()
            self.icons = {
                "Dropbox": QIcon(QPixmap("dropbox.png")),
                "Clipboard": QIcon(QPixmap("clipboard.png")),
                "Loupe": QIcon(QPixmap("loupe.png"))
            }
            self.clipboard = QApplication.clipboard()
            self.create_trayicon()
            self.old_data = os.path.getsize(PATH_FILE)
            self.new_data = None
            self.timer = QTimer()
            self.timer.setInterval(1000)
            self.timer.timeout.connect(self.data_changed)
            self.timer.start()
     
        def directory_exist(self):
            """Controle et création du répertoire sur le Cloud"""
            if not os.path.isdir(PATH_CLOUD):
                try:
                    os.mkdir(PATH_CLOUD)
                    with open(PATH_FILE, "wb") as file:
                        file.write(TITLE.encode("utf-8"))
                except (FileNotFoundError, PermissionError):
                    QMessageBox.warning(
                        self,
                        TITLE,
                        f"Impossible de créer le répertoire {PATH_CLOUD}"
                    )
                    sys.exit()
     
        def data_changed(self):
            """Contrôle de l'état du fichier"""
            self.new_data = os.path.getsize(PATH_FILE)
            if self.new_data != self.old_data:
                self.paste_to_clipboard()
                self.old_data = self.new_data
     
        def copy_to_cloud(self):
            """Copie du fichier binaire sur le Cloud"""
            if self.clipboard.mimeData().formats():
                if self.clipboard.mimeData().hasImage():
                    pixmap = self.clipboard.pixmap()
                    pixmap.save(PATH_FILE, "PNG")
                    self.show_message(f"Image copiée dans {CLOUD}.", QIcon(pixmap))
                elif self.clipboard.mimeData().hasText():
                    text = self.clipboard.text()
                    with open(PATH_FILE, "wb") as file:
                        file.write(text.encode("utf-8"))
                    self.show_message(f"Texte copié dans {CLOUD}.", self.icons["Dropbox"])
                self.old_data = os.path.getsize(PATH_FILE)
            else:
                self.show_message(
                    "Le Presse-papier est vide !!!.",
                    QSystemTrayIcon.Warning,  # type: ignore
                )
     
        def paste_to_clipboard(self):
            """Copie du fichier binaire du cloud vers le presse-papier"""
            with open(PATH_FILE, "rb") as file:
                data = file.read()
            header = data[0:4]
            if header == b"\x89PNG":
                image = QImage.fromData(data)
                self.clipboard.setImage(image)
                self.show_message(
                    "Image collée dans le Presse-papier.",
                    QIcon(QPixmap(image))
                )
            else:
                self.clipboard.setText(data.decode("utf-8"))
                self.show_message(
                    "Texte collé dans le Presse-papier.", self.icons["Clipboard"]
                )
     
        def create_trayicon(self):
            """Création du QSystemTrayIcon"""
            self.tray.setIcon(self.icons["Clipboard"])
            self.tray.setVisible(True)
            self.tray.setToolTip(TITLE)
            menu = QMenu(self)
            opt_copy = QAction(
                parent=self, text=f"Copier dans {CLOUD}", icon=self.icons["Dropbox"]
            )
            opt_copy.triggered.connect(self.copy_to_cloud)
            menu.addAction(opt_copy)
            opt_paste = QAction(
                parent=self,
                text="Coller dans le Presse-papier",
                icon=self.icons["Clipboard"]
            )
            opt_paste.triggered.connect(self.paste_to_clipboard)
            menu.addAction(opt_paste)
            show_clipboard = QAction(
                parent=self, text="Apperçu du presse-papier", 
                icon=self.icons["Loupe"]
            )
            show_clipboard.triggered.connect(self.show_clipboard)
            menu.addAction(show_clipboard)
            menu.addSeparator()
            quit_app = QAction(parent=self, text="Quitter")
            quit_app.triggered.connect(app.quit)
            menu.addAction(quit_app)
            self.tray.setContextMenu(menu)
     
        def show_clipboard(self):
            """Affichage du presse-papier"""
            if self.clipboard.mimeData().formats():
                if self.clipboard.mimeData().hasImage():
                    pixmap = self.clipboard.pixmap().scaledToWidth(
                        500, Qt.SmoothTransformation  # type: ignore
                    )
                    self.tool_tip.setPixmap(pixmap)
                else:
                    self.tool_tip.setText(self.clipboard.text())
                self.tool_tip.show()
            else:
                self.show_message(
                    "Le Presse-papier est vide !!!.",
                    QSystemTrayIcon.Warning  # type: ignore
                )
     
        def show_message(self, message: str, icon: QIcon):
            """Affichage de la notification avec une durée de 3 secondes"""
            self.tray.showMessage(TITLE, message, icon, 3000)
     
     
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        main_win = MainWindow()
        sys.exit(app.exec_())
    Edit: Il n'y a pas d'UI c'est un TrayIcon

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Marrant ce truc. Moi chaque fois que je vois du Qt je suis content car j'apprends des trucs. Mais pourquoi tu ne le proposes pas en tant que code source Python ???

    Citation Envoyé par Diablo76 Voir le message
    Alors bien-sur vos remarques et commentaires sont les bienvenus.
    PATH_CLOUD = f"{Path.home()}{os.sep}{CLOUD}{os.sep}.ClipboardToCloud{os.sep}"
    Hum... C'est quand-même dommage d'utiliser pathlib et de créer ce chemin de façon si pénible (alors que justement pathlib est fait pour ça !!!)
    PATH_CLOUD = Path(Path.home(), CLOUD, ".ClipboardToCloud") !!!
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut
    Merci de ta réponse.
    Alors os.sep me réconforte, mais tu as raison, je vais modifier ça.
    Pour ce qui est de code source Python, est-elle suffisamment aboutie??, Il y a surement des améliorations à faire.

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 101
    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 101
    Points : 4 446
    Points
    4 446
    Par défaut
    bonjour
    Citation Envoyé par Diablo76;
    pré-requis : Avoir un compte Dropbox (mais
    Tout à fait, même un nas fait l'affaire, en fait il faut juste un répertoire partagé.

    Puisque nous sommes développeurs, il est aussi possible de faire la même chose (pour du texte) avec gist (gitlab,gitub,...). Mais créer des gists privés demande une api et le code devient bien différent (providers, Repertoire(Provider), Gist(Provider), Gitlab(Provider), pasteBin(Provider)...).

    Citation Envoyé par Sve@r Voir le message
    alors que justement pathlib est fait pour ça !!!
    Et de plus, existe une autre façon de l'écrire (qui retourne le même type)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PATH_CLOUD = Path.home() / CLOUD / ".ClipboardToCloud"
    note : mettre le séparateur à la fin du répertoire, je ne suis pas fan.

    EDIT:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    os.path.isdir(PATH_CLOUD)
    os.mkdir(PATH_CLOUD)
    Si on utilise pathlib, autant ne plus utiliser os puisque cette variable n'est plus une chaine
    $moi= ( !== ) ? : ;

  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 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    Il y a surement des améliorations à faire.
    Certainement mais l'avantage c'est que le truc restera présent. Parce que ce topic, dans 15 jours il aura disparu dans les profondeurs du forum. Et en plus il sera définitivement associé à ton pseudo (le petit tableau noir au dessus de mon avatar).

    Et quand tu fais des améliorations il te suffit ensuite d'éditer ton topic posté dans "codes sources" et repositionner le nouveau script, il est alors modifié et ceux qui le téléchargent à partir de ce moment téléchargent alors le nouveau.

    Citation Envoyé par papajoker Voir le message
    Citation Envoyé par Sve@r Voir le message
    alors que justement pathlib est fait pour ça !!!
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut
    C'est pas un truc, c'est juste un script, de ta part je attendais à plus de critiques, maintenant pourquoi pas ??

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    de ta part je attendais à plus de critiques
    Ok. Alors
    1. quand on fait de l'héritage d'objet Qt, il faut proposer un objet ayant les mêmes propriétés que l'objet hérité. Par exemple un QLabel peut être instancié avec un texte, un parent, des flags, il faut donc que le ToolTip soit instanciable à minima de la même façon.
      Code python : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      class ToolTip(QLabel):
      	"""Affichage d'un QLabel d'apparence QToolTip"""
      	def __init__(self, *args, **kwargs):
      		super().__init__(*args, **kwargs)
      Et pareil pour tous les autres objets. Et en ce qui concerne le ToolTip, pour plus de souplesse, il pourrait recevoir la tempo en paramètre au lieu de la mettre d'office à 2500 millisecondes
      Code python : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      class ToolTip(QLabel):
      	"""Affichage d'un QLabel d'apparence QToolTip"""
      	def __init__(self, tempo=2.5, *args, **kwargs):
      		super().__init__(*args, **kwargs)
      		self.__tempo=tempo*1000
    2. le QMainWindow pourrait recevoir ses éléments de travail en paramètre. Plus généralement, pour rendre ton script totalement indépendant/intégrable dans une autre appli, il ne devrait contenir aucune variable globale et placer le code "spécifique script" dans un bloc if __name__ == "__main__"
    3. les attributs et méthodes internes doivent commencer par des double underscores (afin que ton objet soit protégé de l'extérieur)
    4. si on vire le fichier "clipboard_data" il n'est pas recréé au lancement du script qui tombe en erreur (c'est quand tu récupères sa taille via os.path.getsize(PATH_FILE), opération qui me laisse dubitatif quant à son but car il y a d'autres façons plus robustes de détecter un changement de fichier que comparer sa taille avant/après => pathlib.Path(...).stat().st_mtime)
    5. pas besoin d'encoder et décoder ton texte en utf-8. Tu bennes le texte en vrac dans le fichier binaire, tu le récupèreras à l'identique.

    Et pour les évolutions, le script pourrait historiser n presse-papiers et offrir de récupérer l'un ou l'autre (comme le fait l'éditeur de texte Unix "vi").
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut
    Sincèrement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class ToolTip(QLabel):
    	"""Affichage d'un QLabel d'apparence QToolTip"""
    	def __init__(self, *args, **kwargs):
    		super().__init__(*args, **kwargs)
    c'est pour les dinosaures

    mais bon , je n'ai pas ton niveau

  9. #9
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 101
    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 101
    Points : 4 446
    Points
    4 446
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    c'est pour les dinosaures
    Rien compris à ta remarque…
    C'est la bonne façon de coder par les gens qui ont de l'expérience. Tous les frameworks que tu utilises vont appliquer ce principe
    Peut-être que tu n'as jamais entendu parler de SOLID et open/close ? un truc inventé à l'age des dinosaures informatiques... c'est pourtant un truc qui lui aussi fait fureur (et pas que sur le forum)
    Pourquoi avoir demandé un avis sur le code pour faire ensuite ce genre de remarque ?

    note: même chose que le timeur, pour bg-color, forcer le fond (sans la couleur) dans la classe est un truc de "jeune" codeur. Mais puisque tu sembles assumer, ok
    $moi= ( !== ) ? : ;

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    Sincèrement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class ToolTip(QLabel):
    	"""Affichage d'un QLabel d'apparence QToolTip"""
    	def __init__(self, *args, **kwargs):
    		super().__init__(*args, **kwargs)
    c'est pour les dinosaures
    Citation Envoyé par papajoker Voir le message
    Rien compris à ta remarque…
    Moi non plus. Mais si tu connais une syntaxe plus récente qui offre la même possibilité...

    Citation Envoyé par Diablo76 Voir le message
    mais bon , je n'ai pas ton niveau
    Il y a des gens qui ont ce qu'on peut appeler "des graces divines". Par exemple l'oreille absolue, c'est un truc qui ne peut pas s'apprendre. On l'a ou on ne l'a pas.
    Tout le reste, y compris un niveau en prog, ça, ça peut s'apprendre. Suffit juste de bosser. Exemple: John Travolta s'est payé une qualif boeing. Il n'est pas pilote, il ne le sera jamais, mais cela ne l'a pas empêché de la bosser et la passer (et bon dans ce cas particulier aussi la payer car 150000€ quoi !!!)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 101
    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 101
    Points : 4 446
    Points
    4 446
    Par défaut
    Comme "animateur", tu fais peur (EDIT: ton message effacé)
    Tu demandes des critiques, et lorsque l'on te propose une bonne liste d'améliorations…, je ne comprends pas, te voilà en PLS

    Tant pis, je risque ma peau…

    Comme dit dans le premier message, je préfère une couche d'abstraction. Cela te permet de complètement séparer l'interface du métier.
    Le gui ne connait qu'une interface (au métier), les 2 sont donc bien séparées, et cela comme écrit dans mon premier message permet en plus d'avoir plusieurs services (si désiré plus tard) sans réécrire dans la partie interface graphique.

    Un truc très simple du genre :

    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
    class Provider(abc.ABC):
        # interface pour tous
     
        @abc.abstractmethod
        def updated(self) -> bool:
            return False
     
        @abc.abstractmethod
        def send(self, datas) -> bool:
            return False
     
        @abc.abstractmethod
        def get_content(self):
            return 'txt', ''
     
        @abc.abstractmethod
        def get_name(self) -> str:
            pass
    la partie graphique ne connait que cette interface/service donc c'est la partie à surement le plus réfléchir.

    Ensuite, tu écris ton code métier, la partie facile
    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
    class ProviderDrop(Provider):
     
        def __init__(self, *args, **kwargs):
            super().__init__()
            self._status = 0
            self.file_name: Path = kwargs.get("file_name", PATH_FILE)
            if not self.file_name.exists():
                self.file_name.parent.mkdir(parents=True, exist_ok=True)
                self.file_name.write_text('')
            self.updated()
     
        def updated(self) -> bool:
            status = self.file_name.stat().st_mtime
            if status != self._status:  # et file size > 0
                self._status = status
                return True
            return False
     
        def get_name(self) -> str:
            return 'dropbox'   # utile pour charger icone.png et entrée menu
     
        def send(self, datas, bin=False) -> bool:
            if bin:
                return self.file_name.write_bytes(datas) > 0
            return self.file_name.write_text(datas) > 0
     
        def get_content(self):
            data = self.file_name.read_bytes()
            # if entete ....
            return 'bin', data
            # else convertir en texte
    Désolé, utiliser des couches d'abstractions, c'est un truc de dino et pas une pratique "jeune qui désire s'affirmer"
    $moi= ( !== ) ? : ;

  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 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par papajoker Voir le message
    return self.file_name.write_bytes(datas) > 0
    Ca j'aime bien. Moi qui me casse le luc à ouvrir mes fichiers pour y lire et écrire dedans alors qu'on pouvait le faire directos!!! J'ai appris un truc sur pathlib.Path

    [edit] Je viens de modifier une dizaine de sources. Des blocs de with open(..., "r") as fp: ... fp ceci ... fp cela remplacés par un simple pathlib.Path(...).read_text()
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Alors ne doute pas de ma compétence pour ce métier, et je fais tout pour venir en aide aux personnes en difficulté.
    Maintenant, oui surement j'ai poussé le bouchon un peu trop loin.
    J'ai juste proposé un script, je ne dis pas qu'il est parfait, mais ça peut donner des idées à d'autres.

  14. #14
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 101
    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 101
    Points : 4 446
    Points
    4 446
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    ne doute pas de ma compétence
    Mais il n'y a aucun doute ! ton script est bon. C'est toi qui as demandé des critiques. Puisque c'est bon, on ne peut que te donner des axes pour qu'il soit encore meilleur ou chercher des broutilles.
    Et si on te fait 50 remarques, c'est pour t'aider et certainement pas pour t'enfoncer la tête sous l'eau (comme tu as l'air de la penser). Et si une personne désire t'aider, c'est qu'elle pense que tu en vaux la peine !

    Citation Envoyé par Diablo76;
    je fais tout pour venir en aide aux personnes en difficulté.
    Donc, comme nous tous. Cela m'exaspère que tu puisses douter des motivations d'une personne sur ce forum. Simplement, nous avons tous notre personnalité, certains vont préférer mentir pour rassurer/motiver le débutant et d'autres vont souligner les problèmes pour qu'il enregistre son "erreur" et ne la refasse jamais. Certains ont besoins d'une carotte et d'autres surtout pas, pas possible de savoir sur un forum.
    $moi= ( !== ) ? : ;

  15. #15
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut
    Je ne doute de rien, c'est un constat, peut importe le niveau de compétence, ici c'est celui qui aura la plus grosse queue

  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 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    mais ça peut donner des idées à d'autres.
    C'est ce que je pensais quand j'ai écrit "Moi chaque fois que je vois du Qt je suis content car j'apprends des trucs" et que je t'ai dit d'aller le mettre dans la section des codes sources!!!

    Citation Envoyé par Diablo76 Voir le message
    Je ne doute de rien, c'est un constat, peut importe le niveau de compétence, ici c'est celui qui aura la plus grosse queue
    Oui hé bien va constater un peu mieux !!! Ok entre pros on se challenge un peu ou on s'envoie des piques amicales mais on se le fait entre nous, pas envers des débutants.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  17. #17
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 572
    Points : 2 014
    Points
    2 014
    Par défaut
    Citation Envoyé par Diablo76 Voir le message
    Alors bien-sur vos remarques et commentaires sont les bienvenus.
    A priori, je dirais non.

    Ou bien ce sont nos remarques et commentaires qui seraient les bienvenus, mais pas nous.


  18. #18
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    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 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Arioch Voir le message
    A priori, je dirais non.
    En fait c'est un exemple concret d'un dicton provençal "fais du bien à Bertrand, te le rend en caguant". Et si ce dicton (repris par Marcel Pagnol dans "Manon des sources") a été créé, c'est bien parce les ingrats de ce genre sont légion.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  19. #19
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    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 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Bonjour,

    Ce que je trouve dommage c'est de ne pas présenter ce code via un lien vers une plateforme web de gestion de codes sources telle que GitLab, GitHub, ... (pour les plus connus) et de demander simplement une revue de code collaborative.

    J'ai l'impression qu'on pourrait encore découper, je vois deux responsabilités :
    1. Les fichiers et les répertoires
    2. Le clipboard (gestion des interactions avec le presse papier)


    On pourrait aussi étendre les fonctionnalités, par exemple indiquer le type de contenu du presse papier, déterminer si c'est une image ou un texte, dans pourquoi pas un ClipBoardManager ?

    Un FileManager, permettrait aussi d'éviter comme pour ClipBoardManager des dépendances qui seraient difficilement maintenables...

    Nommer MainWindow pour se rapprocher d'une problématique concrète avec un nom plus concret comme ClipBoardCloudManager.

    C'est pas grand chose, le code fonctionne et à mon sens, si pas ou peu d'évolutions, la partie ISP (Interface Segregation Principle) comme proposé précédemment me semble overkill.

    C'est pas parce-qu'un principe très connu est une bonne pratique, qu'il ne faut pas adapter à son projet... savoir faire le tri sur les principes et ne pas les appliquer sans réfléchir à l'objectif final !
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  20. #20
    Membre habitué
    Homme Profil pro
    Animateur Numérique
    Inscrit en
    Février 2013
    Messages
    131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Animateur Numérique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Février 2013
    Messages : 131
    Points : 186
    Points
    186
    Par défaut
    Salut et désolé de répondre aussi tardivement,

    @fred1599:
    En ce qui concerne le découpage pourquoi pas mais le but de ce script c'est de transférer le contenu du presse-papier d'un ordi à un autre sans tenir compte de l'os et du réseau.

    @pour_les_autres:
    J'ai pris en compte plusieurs de vos remarques et critiques.

    Le dépôt :

    https://github.com/diablo76600/ClipboardToCloud

Discussions similaires

  1. [AC-2010] Champ d'une requête sélection qui ne peut être mis à jour
    Par Daejung dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 22/10/2015, 14h58
  2. Réponses: 1
    Dernier message: 16/11/2007, 10h28
  3. Une DLL qui existe mais VB ne la trouve pas...
    Par Lawari dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 09/12/2005, 23h16
  4. Réponses: 2
    Dernier message: 10/03/2004, 18h52
  5. Une table qui existe mais qui est inconnu! ?
    Par Nino dans le forum InterBase
    Réponses: 6
    Dernier message: 13/06/2003, 11h47

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