2010-01-23 5 views
2

Je crée un éditeur de texte trivial (en tant qu'exercice) dans GTK en utilisant Glade, GtkBuilder et C. J'ai un menu d'édition avec Couper, Copier et Coller ainsi qu'un GtkTextView pour le texte. GtkTextView lie automatiquement les séquences couper/copier/coller pour lui-même (et fournit même des éléments de menu si vous faites un clic droit). Je souhaite connecter les éléments de menu Couper, Copier et Coller dans ma barre de menus à mon affichage de texte afin qu'ils agissent comme prévu.Comment se connecter GtkTextView à GtkMenuItem

Notez qu'il s'agit d'une connexion bidirectionnelle. (1) Lorsque l'un des objets GtkMenuItem Couper, Copier ou Coller est activé, il indique à GtkTextView de faire quelque chose. (2) Lorsqu'une sélection est faite ou effacée dans GtkTextView, Couper et Copier sont respectivement activés ou désactivés (voir gedit comme exemple). De plus, (3) que Paste soit activé dépend de l'état du presse-papiers.

Comment connecter mes éléments de menu Couper, Copier et Coller à la vue de texte? Y a-t-il un moyen de le faire dans Glade, ou mon programme C aura-t-il besoin de code supplémentaire pour cela? Existe-t-il un moyen simplifié de le faire, ou dois-je mettre en œuvre les trois comportements mentionnés dans le paragraphe ci-dessus manuellement?

Répondre

2

Vous aurez besoin d'un code C supplémentaire, mais pas beaucoup. Pour cet exemple, je suppose que vous utilisez GtkAction s pour vos éléments de menu, mais si vous n'êtes pas la solution devrait être similaire.

Effectuez d'abord les rappels pour les actions couper, copier et coller dans Glade. Lorsque vous connectez les signaux, transmettez une structure de données contenant au moins des pointeurs sur les actions de coupe, de copie et de collage, et la vue de texte, en tant que données utilisateur.

void 
on_cut(GtkAction *action, SomeStruct *data) 
{ 
    g_signal_emit_by_name(data->view, "cut-clipboard", NULL); 
    gtk_action_set_sensitive(data->paste_action, TRUE); 
} 

void 
on_copy(GtkAction *action, SomeStruct *data) 
{ 
    g_signal_emit_by_name(data->view, "copy-clipboard", NULL); 
    gtk_action_set_sensitive(data->paste_action, TRUE); 
} 

void 
on_paste(GtkAction *action, SomeStruct *data) 
{ 
    g_signal_emit_by_name(data->view, "paste-clipboard", NULL); 
} 

Ensuite, connecter au signal notify::has-selection de votre GtkTextBuffer:

void 
on_has_selection_notify(GtkTextBuffer *buffer, GParamSpec *pspec, SomeStruct *data) 
{ 
    gboolean has_selection = gtk_text_buffer_get_has_selection(buffer); 
    gtk_action_set_sensitive(data->cut_action, has_selection); 
    gtk_action_set_sensitive(data->copy_action, has_selection); 
} 

Pour déterminer l'état initial de l'action de la pâte (dans le cas où il y a du texte sur le presse-papiers lorsque vous démarrez l'application) run le code suivant pendant que vous construisez votre interface:

gtk_action_set_sensitive(data->paste_action, 
    gtk_clipboard_wait_is_text_available(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))); 

Cela suppose qu'il n'y a aucun moyen pour l'utilisateur d'effacer manuellement le presse-papiers (La plupart des programmes ne vous permettent pas de faire cela.)

Lecteur d'avertissement: le code saisi ici n'a pas été testé.

+0

Merci, cela a fonctionné (je ne savais pas au début que vous pouviez vous connecter à une propriété via "notify :: property-name"). Cependant, je pense avoir trouvé une meilleure façon de gérer le presse-papiers: connectez-vous au signal "owner-change" du presse-papiers. Ce signal semble être émis chaque fois que le presse-papiers est mis à jour. Sur mon système, cela a fonctionné pour tous les cas marginaux auxquels je pouvais penser. –