Newsgroup: it.comp.os.linux.development
Titolo: ancora il togglebutton nel treview...

Mi succesde una cosa spassosissima, se non fosse che non capisco perché.
Ogni volta che sposto la riga della selezione clickando su un togglebutton,
il togglebutton che perde la selezione commuta. Con il risultato che 
devo diventare idiota per selezionare le voci giuste.
Riporto qua sotto la callback di commutazione, però ho messo i sorgenti on
line, se per caso volete darci un'occhiata all'indirizzo
http://www.campana.vi.it/ottavio/quantizzatore-0.1.tar.gz
void
on_treeview_clicked (GtkCellRendererToggle * cellrenderertoggle,
                     gchar * arg1, gpointer user_data)
{
  extern GtkWidget *window1;
  GtkTreeIter iter;
  GtkWidget *model;
  GtkWidget *tree;
  GtkWidget *selection;
  char *nome;
  gboolean stato;
 
  tree = (GtkWidget *) lookup_widget (window1, "treeview1");
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
 
  if (gtk_tree_selection_get_selected
      (selection, &model, (GtkTreeIter *) & iter))
    {
      gtk_tree_model_get (model, &iter, NOME, &nome, USARE, &stato, -1);
 
      stato = !stato;
 
      gtk_tree_store_set (GTK_TREE_STORE (model), &iter, USARE, stato, -1);
    }
 
}
 
Non dovrebbe beccare la nuova riga selezionata e cambiarne lo stato? E
allora perché il precedente commuta?

 allora perché il precedente commuta?
Non ho ancora capito perché ti ostini a volere usare la selezione,
quando il path ti viene passato nel callback. ;-)
Il problema è che hai un widget che prende il focus, e tu tenti di
lavorare partendo dalla selection, che è una shortcut per il focus
di una riga. Semplicemente, fa casino.
Come ho già detto, recupera l'iteratore dal path che ti viene dato
dal callback.
Ciao,
 Emmanuele.
-- 
Emmanuele Bassi (Zefram)           [ 
http://digilander.libero.it/ebassi/
 ]
GnuPG Key fingerprint = 4DD0 C90D 4070 F071 5738  08BD 8ECC DB8F A432 0FF4

 }
Tra parentesi, il codice sopra mi va addirittura in segmentation fault,
una volta riscritto in maniera corretta (si, perché è sbagliato, e si, è
comunque sbagliato una volta corretto ;-)).
+++
È sbagliato perché i puntatori sono tutti sbagliati: la corretta
dichiarazione è:
	 GtkTreeIter iter;
	 GtkTreeModel *model;
	 GtkTreeSelection *selection;
E, più in generale, il callback *dovrebbe* essere questo:
void
on_cellrenderer_toggled (GtkCellRendererToggle *toggle,
                         gchar *path_string,
			 gpointer data)
{
	GtkWidget *tree;
 
	GtkTreeIter iter;
	GtkTreeModel *model;
	GtkTreeSelection *selection;
 
	tree = data; /* lo passo con il callback, dato che non ho
	              * lookup_widget, non avendo usato glade.
		      */
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
		gboolean stato;
 
		gtk_tree_model_get (model, &iter, COLUMN_CHECK, &stato, -1);
		stato = !stato;
		gtk_list_store_set (GTK_LIST_STORE (model), &iter, stato, -1);
	}
}
Questo *se* funzionasse (mi va in sigsegv su una strdup... dovrò
controllare meglio).
+++
Ad ogni modo, lo ripeto (e con questo fanno tre, Ottavio: fosse in te,
comincerei a leggere la documentazione delle API ;-))): questo modo
*non* è quello giusto.
Come c'è scritto negli esempi della documentazione delle API, il sistema
funziona in maniera corretta se recuperi l'iteratore dal path che ti
viene sempre passato via callback. La selection va utilizzata in altri
ambiti, e, comunque, non è garantita la sua accuratezza (per via dei
giochi di focusing).


 quando il path ti viene passato nel callback. ;-)
ma dove diavolo è scritta 'sta roba? Lo eviterei, se lo sapessi, no?
Anche perché non ho trovato molto codice a riguardo da cui scopiazzare...

 *non* è quello giusto.
ma io la documentazione delle api l'ho letta. Ma i treeview sono descritti
un po' male.
Comunque con la tua patch alla callback, non crasha, ma si incazza:
(quantizzatore:21736): GLib-GObject-WARNING **: invalid cast from 
`GtkTreeStore' to `GtkListStore'
 
(quantizzatore:21736): Gtk-CRITICAL **: file gtkliststore.c: line 
919 (gtk_list_store_set): assertion `GTK_IS_LIST_STORE (list_store)'
failed
Il discorso sui puntatori è relativo, tutti sono derivati da GtkWidget,
quindi anche se li si dichiara così e li si casta non succede nulla.
Adesso vado a vedere questo iteratore del path, che non so cosa sia, ma
studierò.

 Anche perché non ho trovato molto codice a riguardo da cui scopiazzare...
http://developer.gnome.org/doc/API/2.0/gtk/
http://developer.gnome.org/doc/API/2.0/gtk/TreeWidgetObjects.html
Ci sono vari esempi... Poi, l'onnipresente gtk-demo (che alcune distro
non pacchettizzano, e non so perché) nell'esempio per il GtkListStore.


 studierò.
L'iteratore di una riga lo recuperi dal GtkTreePath. Il GtkTreePath lo
recuperi dalla stringa che ti viene passata nel callback (tu la chiami
`arg1', se non ricordo male).
Il passaggio è:
	GtkTreeIter iter;
	GtkTreePath *path;
	GtkListStore *model;
	model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree));
	path = gtk_tree_path_new_from_string (arg1);
	g_assert (path != NULL);
 
	iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (model),
					&iter,
					path);
 
 
	gtk_tree_path_free (path);
arg1 è una stringa nel formato "1:2:3", nel caso di un albero (nodo 2,
figlio 3, nipote 4), oppure "1" (nodo 2) nel caso di una lista.
Un GtkTreePath è una rappresentazione della stringa su cui operare, in
modo da non doversi scrivere un parser appropriato, e da cui ricavare,
senza difficoltà, l'iteratore alla posizione corretta.
Una volta recuperato l'iteratore, libera la memoria occupata dal Path,
e sei a posto.
+++
Questo è il modo *corretto* per avere un iteratore, partendo dal path.
Il path (in formato di stringa) ti viene passato dal callback del cell
renderer apposta per questo.
Fidati: l'ho fatto in C, l'ho fatto in Perl, l'ho fatto in Python e lo
sto per fare pure un C#. :-)
Ciao,
 Emmanuele (articolo sernificato per l'occasione).


 
http://developer.gnome.org/doc/API/2.0/gtk/TreeWidgetObjects.html
allora mi sa che devo andare dall'oculista... L'ho letta un casino di
volte e non ci ho trovato mai un esempio che mi servisse. Fai tu...

 sto per fare pure un C#. :-)
stavo pensando una cosa....
Di dove sei? Dopo tutti questi consigli dovrei offrirti da bere una sera
:-)
Grazie, adesso collaudo subito.



visto che mi sono impegnato a sbronzarti ti chiedo un'altra cosa. Come
faccio a sapere che riga è stata selezionata al di fuori di una callback?
posso farlo avendo solo un puntatore al treeview?

 posso farlo avendo solo un puntatore al treeview?
No, puoi usare un TreePath globale, oppure puoi usare una RowReference.
Quest'ultima ha la pregevole caratteristica di rimanere sempre valida a
prescindere da quello che fai con il modello (a parte cancellare la row
a cui si riferisce, abbastanza ovviamente ;-)).
Ciao,
 Emmanuele.


 a cui si riferisce, abbastanza ovviamente ;-)).
ok ok, adesso studio