[11:04:01] Hello [11:04:18] I've written my own treemodel to connect to my own data model [11:04:52] But my data model run in another thread than the gtk.mainloop [11:04:59] *** foser has joined the room as a participant and a member [11:05:49] to not have any problem with threads, I decided that my model will send modification signals to the treemodel using gobject.idle_add [11:05:59] have fun marshalling :) [11:06:26] problem is that, sometimes, the treemodel explore the tree by itself thus, when receiving the signals, duplicating some actions [11:06:34] (rows are added or removed twice) [11:07:03] what's the good way of implementing such a system ? [11:08:41] ploum, I can't think of anything other than keeping track of which signals you already have queued idle handlers for and then making sure you only ever queue one per change [11:08:55] it wont be particularly easy to get right though :-) [11:10:42] *** gnumdk has joined the room as a participant and a member [11:10:47] Hello [11:10:59] kamstrup: could you please explain a bit ? [11:11:01] Is there a way to get real rounded menu in gtk ? [11:11:41] I've tried something similar but it didn't work. Hopefully your idea is different [11:12:19] ploum, ok... so it's basically some hashmap of operation-id -> idle_handler_id [11:12:27] g_idle_add returns a source id [11:12:44] so you need to construct some id for a given change as well [11:13:25] like if you change a row you could have something like "CHANGED"+row_id [11:13:38] then put that in a map [11:13:41] I think it is what I did. The problem is that *sometimes*, treeview discover by itself, sometimes not, but there's no way to know what treeview has discovered. [11:13:54] uhm [11:14:04] hmmm - ok, there might very well be some details I haven't grokked [11:14:26] by design, you cannot have a half-updated treeview [11:14:41] your treeview must always be correct wrt the signals you emitted [11:14:56] *** bpeel_away is now known as bpeel [11:14:57] so adding two rows, then emitting two "row-added" doesn't work [11:15:00] *** Milosz has left the room (Ping timeout: 600 seconds (~AKKG@91-64-178-209-dynip.superkabel.de)) [11:15:15] you need to add a row, emit row-added, add next row, emit row-added [11:15:27] ploum, you say that "model will send modification signals to the treemodel using gobject.idle_add"... where is the difference between the model and treemodel ? [11:16:13] eh, /me still unsure how you can do it safely without caching the actual changes somewhere [11:16:36] tristan: the model is not gtk related at all. It's something that runs in its own thread and offer a tree API. My treemodel only connect to it. [11:17:26] ploum, your GtkTreeModelIface implementation offers a model viewable by a treeview... and accesses your unrelated datamodel as a thin layer correct ? [11:17:42] tristan: indeed [11:18:34] ploum, so when the treeview invokes methods of the GtkTreeModel implementation directly, that implementation needs to report out-of-sync data sometimes [11:18:56] even if it knows the data has changed under the hood, but is pending an idle handler to find out [11:18:59] according to Company advice, maybe I could have a huge cache, take the values from there but reset this cache each time I receive a signal ? [11:19:28] ploum, if you cache the whole data, it defeats the purpose of a custom model though correct ? [11:19:30] heh [11:19:40] tristan: yes, indeed [11:20:13] but I don't see how to report out-of-sync data otherwise [11:20:47] so, when publishing a change from the thread, you need to lock the treemodel / save the old treemodel state for that row in some queue / unlock the treemodel [11:21:15] then when emitting signals... you need to unqueue those changes one by one while taking care of the lock [11:21:23] *** hansfbaier has left the room (hansfbaier!~jack@61.5.86.211 PART #gtk+ (~jack@61.5.86.211)) [11:21:29] and when the GtkTreeModel is invoked by the TreeView directly [11:21:56] *** andre_ has joined the room as a participant and a member [11:22:00] it has to be sure to use the queued "inconsistent data" instead where available (i.e. the idle hasnt passed through yet) [11:22:14] could be something accumulative like that [11:22:22] *** lx has joined the room as a participant and a member [11:22:54] I never thought it would be so painful :-( [11:22:59] heh [11:23:36] ploum, you even have to consider that the same data may change multiple times before the treeview has time to get the change for that data [11:24:13] ploum, however just the thought of a cross-threaded model implementation makes my brain hurt ;-) [11:25:01] ploum, it can be much simplified if the nature of your data is specific, for instance a threaded log view is easy... it only has to append rows asynchronously [11:25:59] *** mcrha|afk is now known as mcrha [11:27:17] tristant: I fail to see how it is easy ? [11:27:24] the problem is the same, isn't it ? [11:30:15] ploum, not really - if you are just accumulating incoming server logs or such, then the only cross-threaded operation is "add-row" [11:30:43] in that case you queue the data in an idle handler and append it to a model that's safely accessible from the gui thread [11:31:10] here, I've a complex tree and I use add, remove and update [11:31:17] ploum, i.e. you are not taking into accound row-changes interleaved with inserted rows, mangled row indexes and all [11:32:06] well, in my model, I pay a lot of attention to that [11:32:07] ploum, well then your case is more complex than an ever growing server log that needs to be viewed ;-) [11:32:08] heh [11:32:44] thanks a lot for all the information [11:32:56] It makes me a bit depressive but, at least, it's informative [11:33:21] cannot we imagine making the treeview a bit more intelligent ? [11:33:43] ploum, I've been imagining that recently [11:33:58] ploum: theading in general is hard [11:34:05] ploum, but my imaginings havent included accessing models in other threads [11:34:21] ploum: if you have to synchronize state between 2 threads, you're always in a world of pain [11:34:22] *** kamstrup has left the room (Ex-Chat (~kamstrup@188.114.151.76)) [11:34:46] it's what intel figured out when they had to sync CPU caches of multiple CPUs to the same data ;) [11:35:25] Company: indeed, but you cannot decently imagine doing all the work in the same thread as the GUI ! [11:35:41] *** Milosz has joined the room as a participant and a member [11:35:52] ploum: no, but you need an intelligent way to store the data that is accessed by the GUI [11:36:13] i.e. in MVC, decide where you keep the M if V and C are in different threads [11:36:14] ploum, right, we usually encourage people to at least keep all the GTK+ related calls in the same thread though [11:36:15] *** kamstrup has joined the room as a participant and a member [11:37:31] *** xan has joined the room as a participant and a member [11:37:48] I choosed to put the M and C in the same thread. But it doesn't work… [11:38:27] tristan: all the gtk calls are in the same thread, that's why I'm using idle_add. If you don't do that, you have very very naughty crashes ;-) [11:39:21] ploum, are they ? what if the GtkTreeView accesses your model implementation and requires it to consult data that may have been asynchronously updated ? [11:39:30] its hard to say [11:40:12] ploum, on the other hand, you might try "the other approach", which is typically more dangerous [11:40:19] but in your case possibly suitable [11:40:29] ploum, scratch the g_idle_add calls alltogether [11:40:42] and aquire the gdk_threads_mutex() when updating the model internally ? [11:41:00] *** andreasn has joined the room as a participant and a member [11:41:15] tristan: that's an option, indeed [11:41:19] it worths trying [11:41:20] ploum, this may have problems that I'm not considering at the moment [11:41:27] I would try it yeah [11:41:32] thanks a lot