Newsgroup: it.comp.os.linux.development
Titolo: Selezionare prossima riga in un TreeView

Mi chiedevo se esiste un modo semplice per trovare la riga successiva a 
quella selezionata in un treeview.
Il metodo iter_next restituisce il prossimo iter dello stesso livello, 
ma l'iter corrente potrebbe avere un figlio.
Il metodo iter_children restituisce il prossimo figlio, ma l'iter 
potrebbe non avere figli. Inoltre la prossima riga potrebbe avere un 
iter di livello inferiore, in tal caso io come faccio a risalire?
Insomma non esiste un modo semplice per fare una sorta di 
select_next_row indipendentemente dalla profondita' dell'iter attuale?
-- 
 |\ |       |HomePage   : 
http://nem01.altervista.org
 | \|emesis |XPN (my nr): 
http://xpn.altervista.org

 select_next_row indipendentemente dalla profondita' dell'iter attuale?
Figlio mio, tu pretendi troppo. ;-)
BTW: le operazioni di recupero degli iteratori mi sembra siano in tempo
costante; quindi, male che ti vada, una ricerca ti prenderà un O(n) e
non un O(n*n).
Ciao,
 Emmanuele.
-- 
Emmanuele Bassi (Zefram)                 [ 
http://www.emmanuelebassi.net
 ]
GnuPG Key fingerprint = 4DD0 C90D 4070 F071 5738  08BD 8ECC DB8F A432 0FF4

non un O(n*n).
Beh tralasciando il fatto che l'albero puo' contenre anche centinaia di 
elementi ... ma cosa ricerco visto che io non conosco quale e' il 
prossimo iter, anzi io proprio quello voglio conoscere. Insomma non ho 
capito :-D


 capito :-D
Dicevo: dato che la ricerca dell'iteratore dovrebbe essere in tempo
costante, puoi reimplementare una ricerca con un po' di if senza perdere
poi molto nelle performance:
 
def find_next_row (current_iter):
	# sanity check
	assert (current_iter is not None)
 
	next_iter = None
 
	if tree_store.iter_has_child(current_iter):
		next_iter = tree_store.iter_children(current_iter)
	# il nodo non ha figli; restituiamo il prossimo nodo di livello
	# omologo
	if not next_iter:
		next_iter = tree_store.iter_next(current_iter)
	# a questo punto, il nodo non ha né figli, né nodi omologhi.
	# potremmo essere a fine albero, nel caso migliore; tuttavia,
	# potremmo essere anche nella situazione in cui il nodo corrente
	# è in fondo ad un lungo ramo, e non so se iter_next restituisce
	# il nodo successivo che *non* sia un figlio del nodo corrente.
	# 
	# se così non fosse:
	if not next_iter:
		prev_iter = tree_store.iter_parent(current_iter)
		next_iter = select_next_row(prev_iter)
		# ovviamente, potrebbe capitare il caso sfigato in cui
		# capitiamo sul nodo di partenza: un check sul path, per
		# verificare che sia differente (il path non cambia,
		# l'iteratore si), sarebbe utile.
 
	# il caso in cui l'iteratore corrente non avesse figli né
	# parenti, e non esistesse alcun nodo di livello omologo, è il
	# caso in cui esiste un solo elemento nel tree.
	return next_iter
Questo fatto in cinque minuti, non testato, e andando a memoria.
Potrebbe essere interessante aprire i sorgenti del GtkCTree e vedere
cosa usassero ai tempi, riadattandolo ai tempi. Ad ogni modo, è per
questo che esistono gli iteratori... ;-)


 		next_iter = select_next_row(prev_iter)
Questa sarebbe:
		next_iter = find_next_row(prev_iter)
Abbastanza ovviamente.


questo che esistono gli iteratori... ;-)
... per far perdere tempo ai poveri programmatori che usano i Treview? :-D


Stavo giocando col mio nuovo newsreader quando Emmanuele Bassi ha cercato di 
mandarlo in crash scrivendo: 
[mega cut]
OK, ho risolto con questo semplice algoritmo con un while che risale 
l'albero. Probabilmente esiste una soluzione piu' elegante, ma per il 
momento questa funziona:
def find_next_row(model,current_iter):
    if model.iter_has_child(current_iter):
        next_iter=model.iter_children(current_iter)
    else:
        next_iter=model.iter_next(current_iter)
        while not next_iter:
            prev_iter=model.iter_parent(current_iter)
            current_iter=prev_iter
            if not prev_iter:
                break
            next_iter=model.iter_next(current_iter)
    return next_iter
Ora devo realizzare l'algoritmo che fa la cosa inversa :-D
Speriamo che basti invertire i children con parent (e viceversa) e i 
next con previous :-D


 ... per far perdere tempo ai poveri programmatori che usano i Treview? :-D
No, semplicemente per farli impazzire e rinchiudere nell'Arkham Asylum
di Gotham City. :-)


di Gotham City. :-)
Ah ecco! mi sa che tra un po' passano a prendermi allora ;-D


 Sintatticamente era corretto, ma algoritmicamente no ;-)
Non ricordavo il comportamento di iter_next. ;-)


Non ricordavo il comportamento di iter_next. ;-)
Ci sei andato vicino in fondo :-D


 ^__^;;;
Per questo servirebbe una struttura dati secondaria, in cui (i
riferimenti a)gli articoli sono collegati nel modo che più ti interessa.
In questo modo, basta numerarli secondo quell'ordine, e selezionare la
riga corrispondente nel TreeStore.
Non credo che, nel CTree, le cose siano tanto differenti (internamente).


Non credo che, nel CTree, le cose siano tanto differenti (internamente).
Sigh, caro vecchio CTree, cosi' semplice, cosi' veloce, cosi' completo 


 :-D
"Più veloce" non più: nell'HEAD del CVS delle GTK 2.4 è appenba entrata
la patch che permette di impostare l'altezza delle righe come fissa,
facendo saltare il controllo sulla dimensione dei cellrenderer, ovvero
il maggiore collo di bottiglia nel GtkTreeView. Adesso si comportano
bene anche con modelli di 10k righe.
http://lists.gnome.org/archives/gtk-devel-list/2003-December/msg00127.html


 bene anche con modelli di 10k righe.
Ok, tra 5 o 6 anni quando la debian stable iniziera` ad avere come 
standard le GTK 2.4 (e con 5 o 6 anni son ottimista :) ) iniziero` a 
utilizzare le GTK2 per le mie applicazioni :)
Bye,
  Gabry
PS: Apparte le facili battute, la mutevolezza delle API e delle librerie 
"standard" di sviluppo di linux e` uno dei motivi che tiene lontani gli 
sviluppatori commerciali da linux, il supporto di applicazioni binary 
only diventa un macello...


http://lists.gnome.org/archives/gtk-devel-list/2003-December/msg00127.html
Eh, si, pero' perdo la compatibilita' con quelli che usano GTK<2.4, e
sono ancora parecchi immagino. :-/
-- 
Give me the luxuries, and to hell with the necessities.


 only diventa un macello...
Le API non sono propriamente "cambiate": è stato aggiunto un simbolo. Le
applicazioni che non lo usano, potranno tranquillamente funzionare sulle
varie 2.0/2.2/2.4/...
Quanto al resto: tra 2.2 e 2.4 c'è una minor release. L'API breakage
accade in molte librerie commerciali, solo che si nota di meno, perché
esistono installer che contengono *tutte* le dipendenze. La filosofia
"pacchetti piccoli + dipendenze a carico dell'utente" è tipica di *nix.


 sono ancora parecchi immagino. :-/
Se decidi di usare questa feature, devi, ovviamente, avere una release
aggiornata delle GTK. Ma - lo and behold! - puoi sempre fare un check a
runtime sulla release delle GTK e abilitare il fixed height se $version
 >= 2.4.0. ;-)


 >= 2.4.0. ;-)
OK, inizia a prepararmi il codice che io non ho la minima idea di come
fare :-D
-- 
Bits make bytes, but nibbles turn me on.


 fare :-D
Si spera che PyGTK ci metta poco tempo per adeguarsi alle GTK2.4. Dato
il tempo che c'hanno messo per arrivare alle 2.0, e dato il fatto che
sono restii ad entrare nel progetto "GNOME Bindings"[1][2], ci credo
poco.
Ad ogni modo, basterà fare:
 
	# ...
	if gtk.gtk-version >= (2,4,0):
		for i in range(0, N_COLUMNS):
			col = treeview.get_column(i)
			col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
 
		treeview.set_property('fixed_height_mode', gtk.TRUE)
	# ...
Non appena il binding sarà effettuato. Comunque, il fixed_height_mode è
consigliabile per treeview con un numero di righe > 10k, quindi ti
converrebbe attivarlo (nel tuo caso) solo quando l'utente seleziona la
visualizzazione di tutti gli articoli in un gruppo.
+++
[1] Per banali motivi di pacchettizzazione: gnome-python usa la
compilazione condizionale in funzione delle librerie installate, mentre
Murray Cumming vorrebbe (non a torto) singoli pacchetti per singoli
binding.
[2] Al contrario di gtk2-perl. Piccola parentesi di orgoglio personale:
il mio binding per GConf sarà incluso.


il mio binding per GConf sarà incluso.
Eh beh, complimenti. Perchè non scrivi anche un wrapper di alto livello
per i treeview? ... magari in python ... ;-)
-- 
Love thy neighbor ... just never get caught.


 ... magari in python ... ;-)
Con il ritmo con cui includono le patch, anche se lo scrivessi adesso,
non verrebbe incluso prima del 2005. ;-)))


full-immersion nelle viscere del Perl. È quasi dolore fisico. :-)
Uh, dovrebbe essere esattamente il contrario :-D
[cut]
Thanks ... e speriamo che tra 6 mesi non mi tocchi fare un nuovo porting
:-D
-- 
FATAL SYSTEM ERROR: Press F13 to continue...


 Uh, dovrebbe essere esattamente il contrario :-D
È dolore perché so che devo tornare al Perl. ;-)


È dolore perché so che devo tornare al Perl. ;-)
Perchè chi/cosa ti costringe a non usare python?
-- 
Somewhere, over the rainbow...that's where the airline will find my luggage.


 Perchè chi/cosa ti costringe a non usare python?
Il fatto di dover finire i binding per libpanel-applet-2.0, di fare il
maintainer di Gnome2::GConf e di Gnome2::Print, e di dare una mano con
gtk2-perl in generale (specie in vista dei GNOME Language Binding).
L'unico "momento-python" l'ho quando riesco a mettere le mani su
gnome-schedule, ma anche quello langue, dato il poco tempo libero che mi
ritrovo ad avere.
+++
Non che io rinneghi il Perl: lo adoro. Penso, anzi, che quando si
programma con le GTK, il Perl sia uno dei (se non il) binding più
"pulito" tra tutti, e non lo dico solo per sporca auto-pubblicità, ma
perché conosco il lavoro fatto per renderlo tale.
