Vous êtes à peu près ici : Accueil  »   tutoriel PyGTK  »   PyGTK : sommaire

21.3. Alimenter la sélection

Alimenter la sélection est un peu plus compliqué. Il faut enregistrer des gestionnaires que l'on appelera lorsque la sélection sera réclamée. Pour chaque paire de sélection/cible à gérer, on fait un appel à :

  widget.selection_add_target(selection, target, info)

... où les paramètres widget, selection et target identifient les requêtes dont doit s'occuper ce gestionnaire. Quand une demande pour une sélection est reçue, on appellera le signal "selection_get". Le paramètre info est un nombre entier qui peut être utilisé comme un identifiant pour la cible spécifique dans le rappel.

La fonction de rappel a la forme :

  def selection_get(widget, selection_data, info, time):

Le gtk.SelectionData est le même que précédemment, mais cette fois-ci, on est chargé de remplir les champs type, format et data. Le paramètre format est important ici - le serveur X l'utilise pour savoir si data nécessite un changement de l'ordre de ses bytes ou non. Habituellement la valeur est 8, c'est à dire un caractère, ou 32 pour un entier). Ceci est réalisé en appelant la méthode :

  selection_data.set(type, format, data)

Cette méthode PyGTK peut seulement manipuler des chaînes de caractères donc le paramètre data doit être inclus dans une chaîne Python, mais le format sera de la dimension appropriée (par ex. 32 pour les atomes et les nombres entiers, 8 pour les chaînes). Les modules Python struct ou StringIO peuvent être utilisés pour convertir des données non-chaîne en chaîne de caractères. Par exemple, vous pouvez convertir une liste de nombres entiers vers une chaîne et renseigner le selection_data par :

  ilist = [1, 2, 3, 4, 5]

  data = apply(struct.pack, ['%di'%len(ilist)] + ilist)

  selection_data.set("INTEGER", 32, data)

La méthode suivante établit les données de la sélection à partir de la chaîne indiquée :

  selection_data.set_text(str, len)

À la demande de l'utilisateur, on réclame la propriété de la sélection en appelant :

  result = widget.selection_owner_set(selection, time=0L)

... où result vaut TRUE si le programme a réclamé la sélection selection avec succès. Si une autre application réclame la possession de la sélection, on obtiendra une réponse "selection_clear_event".

Comme exemple de fourniture de sélection, le programme setselection.py ajoute une fonction de sélection à un bouton interrupteur compris dans une boîte gtk.EventBox. Le gtk.Eventbox est nécessaire car la sélection doit être associée à une gtk.gdk.Window alors que le gtk.Button est un widget "sans fenêtre" dans GTK+ 2.0. Quand le bouton interrupteur est enfoncé, le programme réclame la propriété de la sélection primaire. La seule cible reconnue (à part certaines cibles comme "TARGETS" fournies par GTK+ lui-même) est la cible "STRING". Lorsque cette cible est demandée, une représentation en chaîne de caractères du temps actuel est renvoyée. La Figure 21.2, « Exemple de création de sélection » montre le programme au moment où il prend possession de la sélection primaire.

Figure 21.2. Exemple de création de sélection

Exemple de création de sélection

Voici le code du programme setselection.py :

     1   #!/usr/bin/env python
     2   # -*- coding:utf-8 -*-
     3   # exemple setselection.py
     4   
     5   import pygtk
     6   pygtk.require('2.0')
     7   import gtk
     8   import time
     9   
    10   class SetSelectionExample:
    11       # Fonction de rappel quand l'utilisateur modifie la sélection.
    12       def selection_toggled(self, widget, window):
    13           if widget.get_active():
    14               self.have_selection = window.selection_owner_set("PRIMARY")
    15               # si réclamer la sélection échoue, on remet le bouton
    16               # dans l'état inactif.
    17               if not self.have_selection:
    18                   widget.set_active(False)
    19           else:
    20               if self.have_selection:
    21                   # Impossible de libérer la sélection en PyGTK,
    22                   # on indique juste que l'on ne la possède pas.
    23                   self.have_selection = False
    24           return
    25   
    26       # Appelé lorsqu'une autre application réclame la sélection.
    27       def selection_clear(self, widget, event):
    28           self.have_selection = False
    29           widget.set_active(False)
    30           return True
    31   
    32       # Fournit le temps actuel comme sélection.
    33       def selection_handle(self, widget, selection_data, info, time_stamp):
    34           current_time = time.time()
    35           timestr = time.asctime(time.localtime(current_time))
    36   
    37           # Quand on renvoie une chaîne unique, elle ne doit se terminer 
    38           # par une valeur nulle. Ceci le fait pour nous.
    39           selection_data.set_text(timestr, len(timestr))
    40           return
    41   
    42       def __init__(self):
    43           self.have_selection = False
    44           # Création de la fenêtre de niveau supérieur
    45           window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    46           window.set_title("Set Selection")
    47           window.set_border_width(10)
    48           window.connect("destroy", lambda w: gtk.main_quit())
    49           self.window = window
    50           # Création d'une boîte évènement pour contenir le bouton 
    51           # car il n'a pas sa propre GdkWindow.
    52           eventbox = gtk.EventBox()
    53           eventbox.show()
    54           window.add(eventbox)
    55           
    56           # Création d'un bouton interrupteur pour agir avec la sélection
    57           selection_button = gtk.ToggleButton("Réclamer sélection")
    58           eventbox.add(selection_button)
    59   
    60           selection_button.connect("toggled", self.selection_toggled, eventbox)
    61           eventbox.connect_object("selection_clear_event", self.selection_clear,
    62                                   selection_button)
    63   
    64           eventbox.selection_add_target("PRIMARY", "STRING", 1)
    65           eventbox.selection_add_target("PRIMARY", "COMPOUND_TEXT", 1)
    66           eventbox.connect("selection_get", self.selection_handle)
    67           selection_button.show()
    68           window.show()
    69   
    70   def main():
    71       gtk.main()
    72       return 0
    73   
    74   if __name__ == "__main__":
    75       SetSelectionExample()
    76       main()