After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 709609 - [PATCH] Change way of sorting before writing XML output.
[PATCH] Change way of sorting before writing XML output.
Status: RESOLVED FIXED
Product: glade
Classification: Applications
Component: general
3.16.x
Other Linux
: Normal normal
: ---
Assigned To: Glade 3 Maintainers
Glade 3 Maintainers
Depends on:
Blocks:
 
 
Reported: 2013-10-08 06:54 UTC by Thomas Martitz
Modified: 2014-06-20 17:46 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Equivalent patch for 3.8 (2.57 KB, patch)
2013-10-08 07:00 UTC, Thomas Martitz
none Details | Review
Patch for 3.16 (2.50 KB, patch)
2013-10-08 07:01 UTC, Thomas Martitz
none Details | Review
Geany's glade file, upstream version (625.54 KB, text/plain)
2013-10-10 10:36 UTC, Thomas Martitz
  Details
git diff for git+.git; patched glade (14.20 KB, patch)
2013-10-11 18:46 UTC, Thomas Martitz
none Details | Review
git diff for git+.git; unpatched glade (13.69 KB, patch)
2013-10-11 18:47 UTC, Thomas Martitz
none Details | Review
Toplevel sorting using topology algorithm (6.86 KB, patch)
2013-10-11 22:27 UTC, Juan Pablo Ugarte
none Details | Review
Compile with: gcc $(pkg-config glib-2.0 --cflags) test.c -o test $(pkg-config glib-2.0 --libs) (829 bytes, text/x-csrc)
2013-10-18 18:53 UTC, Thomas Martitz
  Details
Same patch, added two pass implementation (1.78 KB, patch)
2013-10-18 22:31 UTC, Juan Pablo Ugarte
none Details | Review
Same patch, added two pass implementation (1.30 KB, patch)
2013-10-20 04:28 UTC, Juan Pablo Ugarte
none Details | Review
_glade_tsort() implementation (7.93 KB, patch)
2013-10-23 22:37 UTC, Juan Pablo Ugarte
none Details | Review
_glade_tsort() implementation (38.53 KB, patch)
2013-11-01 15:24 UTC, Juan Pablo Ugarte
none Details | Review
_glade_tsort() implementation (45.77 KB, patch)
2013-11-01 15:27 UTC, Juan Pablo Ugarte
none Details | Review

Description Thomas Martitz 2013-10-08 06:54:30 UTC
Split the current sort into two passes, first by name/id, then by
widget dependency.

Sorting by two keys at the same time is bogus. It leads to dependencies not
being considered because lexical sorting is already done.

Consider three widgets A, B and C.

A sorts before B, and B sorts before C. When C is compared to B it won't
compared to A again because if (B < C) then (A < C). Any dependency of A on C
might be missed.

So sort by one key at time. Sorting must be done afterwards because it's more
significant.

Pre-sorting by name has two nice side effects: the XML output is more stable,
thus more VCS friendly/suitable for diff'ing'. A more stable XML output also
leads to a more consistent XML tree in the Glade UI.

PS: I hope using BugZilla for patches is correct. Do you also accept patches on the -devel mailing list?
Comment 1 Thomas Martitz 2013-10-08 07:00:14 UTC
Created attachment 256685 [details] [review]
Equivalent patch for 3.8

This patch adds the same change to the 3.8 branch
Comment 2 Thomas Martitz 2013-10-08 07:01:33 UTC
Created attachment 256686 [details] [review]
Patch for 3.16

Patch for 3.16. Seems to have gone lost when creating this task
Comment 3 Juan Pablo Ugarte 2013-10-08 19:43:20 UTC
With out going into much detail, it does seems better to sort it alphabetically first.

Implementation wise I think it is probably a good idea to keep the toplevel list sorted but this will make adding a new toplevel appear in the right order instead of the end which is what the user is used to.
I tried it and it does not look bad, besides once you save and reopen the file again the initial order is going to be lost
Comment 4 Thomas Martitz 2013-10-09 07:04:08 UTC
Nice to here you generally like. I did not fully understand your second paragraph. Do you like my implementation better or one that sorts on insertion?

I also thought about it but didn't want t change too much. With git head the XML output is very unstable so the order is always different on save&reopen.

If you merge a sort on insertion solutions I'm fine with that.
Comment 5 Juan Pablo Ugarte 2013-10-09 13:22:37 UTC
(In reply to comment #4)
> Nice to here you generally like. I did not fully understand your second
> paragraph. Do you like my implementation better or one that sorts on insertion?

If we have to sort by name/dep I prefer (as a user) to do it at insertion and keep view and save order consistent.
It will obviously make the order change when the name is changed but IMO that would be a fair trade off.

> I also thought about it but didn't want t change too much. With git head the
> XML output is very unstable so the order is always different on save&reopen.

Could you attach the offending file?

> If you merge a sort on insertion solutions I'm fine with that.

Well it will take more time since we would have to sort the list on name changes
Comment 6 Thomas Martitz 2013-10-10 10:35:43 UTC
(In reply to comment #5)> 
> If we have to sort by name/dep I prefer (as a user) to do it at insertion and
> keep view and save order consistent.
> It will obviously make the order change when the name is changed but IMO that
> would be a fair trade off.


Makes sense.

> 
> Could you attach the offending file?
> 

Sure.

> > If you merge a sort on insertion solutions I'm fine with that.
> 
> Well it will take more time since we would have to sort the list on name
> changes

If you say it requires more time could you consider merging my patch in the meantime as a bug fix? It does fix bugs because the widget dependencies are not properly considered by the final sorting routine (as I tried to explain in the commit message).

It's gonna be hard for me to make the changes you propose since I'm still mostly lost in the glade code base.
Comment 7 Thomas Martitz 2013-10-10 10:36:32 UTC
Created attachment 256887 [details]
Geany's glade file, upstream version
Comment 8 Tristan Van Berkom 2013-10-10 21:20:05 UTC
FWIW: I did improve this particular feature a lot in Glade master while
doing the composite templates feature for GTK+, it was one of my own 
priorities to be damn sure that all of GTK+'s .ui files dont get
unrelated changes at save time.

So, I only ask that while fixing this bug, we do our best to not regress
what we already have.

It would be nice, before committing, to use the patched Glade to open
every single .ui file (there are around 25 of them) in GTK+ and save
them, and see if our patches cause any difference.

This can be done easily like so:
   o git checkout gtk+
   o cd gtk+
   o glade ./gtk/*.ui
   o Glade will load all of the files, save each one of them one by one
     and close the tab in Glade until there are no tabs open again
   o git diff -a

Ideally, 'git diff -a' in this case produces no output.

If there are some small changes resulting from these patches, and
they cannot be easily avoided, then so be it, just please try to
keep it the same as it currently is.

Thanks.
Comment 9 Juan Pablo Ugarte 2013-10-10 23:01:36 UTC
(In reply to comment #6)
> If you say it requires more time could you consider merging my patch in the
> meantime as a bug fix? It does fix bugs because the widget dependencies are not
> properly considered by the final sorting routine (as I tried to explain in the
> commit message).

Yeah, I will probably commit your patch first and then work from there.
I found another related bug with this file and glade 3.16, for some reason it gets stuck in an infinite loop while trying to save geany.glade

Does it work for you?
Comment 10 Thomas Martitz 2013-10-10 23:14:59 UTC
Actually I only tried saving this very file in Glade 3.8.4, as Geany still supports GTK2 I didn't try to use it with a GTK3-only glade.

Is it caused by my patch?
Comment 11 Thomas Martitz 2013-10-11 18:46:14 UTC
(In reply to comment #8)
> 
> This can be done easily like so:
>    o git checkout gtk+
>    o cd gtk+
>    o glade ./gtk/*.ui
>    o Glade will load all of the files, save each one of them one by one
>      and close the tab in Glade until there are no tabs open again
>    o git diff -a
> 
> Ideally, 'git diff -a' in this case produces no output.
> 
> If there are some small changes resulting from these patches, and
> they cannot be easily avoided, then so be it, just please try to
> keep it the same as it currently is.
> 
> Thanks.

I've done that. I attached the files.

These files reported errors in glade, so i did not save them:
gtkscalebutton.ui
gtkprintunixdialog.ui
gtkfilechooserdefault.ui
gtkcoloreditor.ui
gtkaboutdialog.ui

The only difference between the diffs is gtkpagesetupunixdialog.ui where there was a single object reordered after saving it with patched glade. It was stable after the initial save, i.e. it didn't fluctuate further. I guess this is the only file where the split-sort makes a difference because there are dependencies between the top level widgets.

But these files show no regressions as such. I would be very surprised if there are regression because the change only affects sorting, it doesn't affect the contents of the toplevel widget list.
Comment 12 Thomas Martitz 2013-10-11 18:46:48 UTC
Created attachment 257045 [details] [review]
git diff for git+.git; patched glade
Comment 13 Thomas Martitz 2013-10-11 18:47:22 UTC
Created attachment 257046 [details] [review]
git diff for git+.git; unpatched glade
Comment 14 Juan Pablo Ugarte 2013-10-11 19:18:20 UTC
(In reply to comment #10)
> Actually I only tried saving this very file in Glade 3.8.4, as Geany still
> supports GTK2 I didn't try to use it with a GTK3-only glade.
> 
> Is it caused by my patch?

No, its not your patch, and its seems its not stuck in a infinite loop, it just takes too long to be usable (several minutes)

So before rushing this in I want to explore the possibility of using some graph theory to see if we can solve this problem.

My guess is that what we really need to resolve dependencies is tsort

http://en.wikipedia.org/wiki/Topological_sorting 

Then we need a clever implementation that updates the list of "edges" when we add or remove an object from the project and obviously when a dependency changes (widget prop referencing another object)
Comment 15 Tristan Van Berkom 2013-10-11 21:24:58 UTC
(In reply to comment #11)
> (In reply to comment #8)
> > 
> > This can be done easily like so:
> >    o git checkout gtk+
> >    o cd gtk+
> >    o glade ./gtk/*.ui
> >    o Glade will load all of the files, save each one of them one by one
> >      and close the tab in Glade until there are no tabs open again
> >    o git diff -a
> > 
> > Ideally, 'git diff -a' in this case produces no output.
> > 
> > If there are some small changes resulting from these patches, and
> > they cannot be easily avoided, then so be it, just please try to
> > keep it the same as it currently is.
> > 
> > Thanks.
> 
> I've done that. I attached the files.
> 
> These files reported errors in glade, so i did not save them:

What kind of errors ? The .UI files wont load ?

> gtkscalebutton.ui
> gtkprintunixdialog.ui
> gtkfilechooserdefault.ui
> gtkcoloreditor.ui
> gtkaboutdialog.ui

To edit GTK+'s own .ui files, you need to use GTK+'s private
widget catalog (to load internal thingamajigies like GtkColorEditor
and the like).

This should help loading files in GTK+:
   https://git.gnome.org/browse/gtk+/tree/gtk/glade/README.glade

If Glade cannot load the basic files in GTK+, then we will put all
patches and enhancements on hold until we fix that first.

> The only difference between the diffs is gtkpagesetupunixdialog.ui where there
> was a single object reordered after saving it with patched glade. It was stable
> after the initial save, i.e. it didn't fluctuate further.

That sounds about reasonable, please try again using GTK+'s private
widget catalog and see if that single change is indeed the only one.

> I guess this is the
> only file where the split-sort makes a difference because there are
> dependencies between the top level widgets.
> 
> But these files show no regressions as such. I would be very surprised if there
> are regression because the change only affects sorting, it doesn't affect the
> contents of the toplevel widget list.

If it effects the *order* of the toplevel widget list then your patch is
definitely dangerous ;-)

Even if you are playing with the order in which child nodes are saved
by parents, that's really dangerous, as the order a GtkBox or GtkNotebook
saves it's children is part of the semantic used to load that widget
by GtkBuilder, and the order of children has significance.

Also, one more thing.

Reading through this bug description and initial comments diagonally,
it's hard to see what problem exactly this patch tries to address, it reads
a lot like:
 "Lets sort in a new way, because I dunno... wouldnt that be cool"

While I think the real issue here is that for some particular data/widget
type that Geany uses, Glade saves things in an alternating order (meaning
somewhere there may be a g_list_append() needs to be replaced by
g_list_prepend(), or similar).

Can somebody please update the bug title to reflect what the bug
actually is ?
Comment 16 Thomas Martitz 2013-10-11 21:59:11 UTC
(In reply to comment #15)
> (In reply to comment #11)
> > (In reply to comment #8)
> > > 
> > > This can be done easily like so:
> > >    o git checkout gtk+
> > >    o cd gtk+
> > >    o glade ./gtk/*.ui
> > >    o Glade will load all of the files, save each one of them one by one
> > >      and close the tab in Glade until there are no tabs open again
> > >    o git diff -a
> > > 
> > > Ideally, 'git diff -a' in this case produces no output.
> > > 
> > > If there are some small changes resulting from these patches, and
> > > they cannot be easily avoided, then so be it, just please try to
> > > keep it the same as it currently is.
> > > 
> > > Thanks.
> > 
> > I've done that. I attached the files.
> > 
> > These files reported errors in glade, so i did not save them:
> 
> What kind of errors ? The .UI files wont load ?
> 
> > gtkscalebutton.ui
> > gtkprintunixdialog.ui
> > gtkfilechooserdefault.ui
> > gtkcoloreditor.ui
> > gtkaboutdialog.ui
> 
> To edit GTK+'s own .ui files, you need to use GTK+'s private
> widget catalog (to load internal thingamajigies like GtkColorEditor
> and the like).
> 
> This should help loading files in GTK+:
>    https://git.gnome.org/browse/gtk+/tree/gtk/glade/README.glade
> 
> If Glade cannot load the basic files in GTK+, then we will put all
> patches and enhancements on hold until we fix that first.
> 
> > The only difference between the diffs is gtkpagesetupunixdialog.ui where there
> > was a single object reordered after saving it with patched glade. It was stable
> > after the initial save, i.e. it didn't fluctuate further.
> 
> That sounds about reasonable, please try again using GTK+'s private
> widget catalog and see if that single change is indeed the only one.
> 
> > I guess this is the
> > only file where the split-sort makes a difference because there are
> > dependencies between the top level widgets.
> > 
> > But these files show no regressions as such. I would be very surprised if there
> > are regression because the change only affects sorting, it doesn't affect the
> > contents of the toplevel widget list.
> 
> If it effects the *order* of the toplevel widget list then your patch is
> definitely dangerous ;-)
> 

Yes, the top level order is important, because there may be interdependencies. These dependencies are not currently handled by git master and this patch addresses this (see commit message and text below).

I worded my sentence badly. I meant "I would be surprised if there are regressions because only the toplevel order is affected while toplevel dependency is enforced".

> Even if you are playing with the order in which child nodes are saved
> by parents, that's really dangerous, as the order a GtkBox or GtkNotebook
> saves it's children is part of the semantic used to load that widget
> by GtkBuilder, and the order of children has significance.
> 

No, this change doesn't affect children. I'm aware of the implications. This change only affects the toplevel list, nothing else.

> Also, one more thing.
> 
> Reading through this bug description and initial comments diagonally,
> it's hard to see what problem exactly this patch tries to address, it reads
> a lot like:
>  "Lets sort in a new way, because I dunno... wouldnt that be cool"
> 
> While I think the real issue here is that for some particular data/widget
> type that Geany uses, Glade saves things in an alternating order (meaning
> somewhere there may be a g_list_append() needs to be replaced by
> g_list_prepend(), or similar).
> 
> Can somebody please update the bug title to reflect what the bug
> actually is ?

The bug is that current Glade uses a compare function that sorts by two different keys at the same time. This doesn't work correctly. The dependencies of two toplevel widgets are potentially not considered because alphabetic sorting took already place.

Using my ABC example from the first message: The compare function will not be called for A and C because C is already sorted after B (and A sorted before B). But if A depends on C, then C must come first. As the compare function is not called this is missed.

To resolve this you must sort separately, by each key at a time. As sort-by-dependency is more important (for correct XML output) it must be done last.

This is not about alternating order of saved geany.glade. But this change makes it more stable as a _side effect_. I didn't mean to report bugs with or about geany.glade.
Comment 17 Juan Pablo Ugarte 2013-10-11 22:27:58 UTC
Created attachment 257061 [details] [review]
Toplevel sorting using topology algorithm

Hi, so I did a quick implementation of the topology sorting (actually a literal implementation)

the algorithm I used to create the edges is

for every object P in project
    for every object S in project
        if P == parent of S
            add edge (P,S)
        else if glade_widget_adaptor_depends (S, P)
            add edge (P,S)
Comment 18 Tristan Van Berkom 2013-10-18 01:36:25 UTC
(In reply to comment #17)
> Created an attachment (id=257061) [details] [review]
> Toplevel sorting using topology algorithm
> 
> Hi, so I did a quick implementation of the topology sorting (actually a literal
> implementation)
> 
> the algorithm I used to create the edges is
> 
> for every object P in project
>     for every object S in project
>         if P == parent of S
>             add edge (P,S)
>         else if glade_widget_adaptor_depends (S, P)
>             add edge (P,S)

Juan, looking at your patch, this is not done
exactly correctly, unless I'm missing something
sneaky...

The toplevels need to be sorted... not the full object
list of the project, I can see that you are building the
dependency list, or edges, by comparing each object
individually, and then trying to sort the toplevel list
using those 'edges'.

Will 'tsort' work like this ?

Or will tsort expect that all of your edges can be found
in the list you want to sort ?

This is likely the wrong approach, otherwise it's quite
unclear reading the code why it is the correct approach.
Comment 19 Juan Pablo Ugarte 2013-10-18 16:47:03 UTC
(In reply to comment #18)
[...] 
> The toplevels need to be sorted... not the full object
> list of the project, I can see that you are building the
> dependency list, or edges, by comparing each object
> individually, and then trying to sort the toplevel list
> using those 'edges'.

True, but we need the full dependency tree because of children objects depend on their parents.

> Will 'tsort' work like this ?
> 
> Or will tsort expect that all of your edges can be found
> in the list you want to sort ?

that is a really good question!
I did not had time to actually understand the whole algorithm.
I want to make some test cases first to make sure the implementation is correct.

If it happens that tsort needs all the nodes in the list, then it wont be a problem, we can filter it later.

> This is likely the wrong approach, otherwise it's quite
> unclear reading the code why it is the correct approach.

yeah I know, I just implemented the algorithm I need to do more testing.
Comment 20 Thomas Martitz 2013-10-18 17:39:01 UTC
The children are subtrees of their parent and already ordered according to their appearance within the parent. They must not be considered in the overall sorting. Only toplevel widgets must be considered, i.e. children should not be shuffled around in their parent.

However, sorting of toplevel widgets must consider that children (and subchildren) depend on other toplevel widgets (such as GtkImage) but the current sorting does that already if I understood this correctly.

Or am I understanding this wrong?

If not I would think my patch should be optimal for sort-on-save. Only sort-on-insert would be even better.
Comment 21 Thomas Martitz 2013-10-18 17:45:06 UTC
(In reply to comment #20)
> However, sorting of toplevel widgets must consider that children (and
> subchildren) depend on other toplevel widgets (such as GtkImage) but the
> current sorting does that already if I understood this correctly.

Correction: The current sorting after applying my patch does this. As I have mentioned the upstream sorting is slightly broken because of sorting by two separate keys in a single compare function.
Comment 22 Juan Pablo Ugarte 2013-10-18 18:04:50 UTC
(In reply to comment #20)
[...]
> However, sorting of toplevel widgets must consider that children (and
> subchildren) depend on other toplevel widgets (such as GtkImage) but the
> current sorting does that already if I understood this correctly.
> 
> Or am I understanding this wrong?

We where talking about my tsort patch and which are the correct parameters to pass.

(In reply to comment #21)
[...]
> Correction: The current sorting after applying my patch does this. As I have
> mentioned the upstream sorting is slightly broken because of sorting by two
> separate keys in a single compare function.

Yes I know, I am still not convinced using two keys in qsort is wrong.
irrc as long as the comparison if constant qsort should work.

in any case I found that glade_widget_depends() is too slow to be used for sorting the list of widgets at save time. (geany.glade gtk2 version) takes several minutes on glade 3.16 while tsort takes a few ms

BTW, do you have a glade file that triggers the two key problemi qsort?
Comment 23 Thomas Martitz 2013-10-18 18:52:29 UTC
I am surprised that glade_widget_depends() is so slow on glade 3.16, in 3.8 saving (and thus, sorting) is instant with geany.glade. Can this be a regression? In gdb I see it's called recursively, perhaps there is something fishy?

I'm also confused why you question my patch now. You have already mentioned that you would merge it.

As two why sorting with two keys is wrong (btw, glib does not use qsort as it's not stable; instead it uses mergesort. anyway, this is an implementation detail of glib). As I don't have a glade file that exposes the problem but I'll show the problem with a sample program. You can find it in the attachment. It implements is written in analogy to the current glade git master and uses my above example. The items A, B and C which are to be sorted lexically, except that A depends on C (realized via the second order key), so the correct order would be "C, B, A"

The output of the program is

> Compare B to C
> Compare A to B
> A
> B
> C

I.e. post-sort order is (still) "A, B, C". The output also shows that the dependency of A to C is not even considered (=> the compare function is not called for these two) because it already found that A sorts before B and B sorts before C. As a proper sorting algorithm it concludes that A must also sort before C and doesn't call the compare function: the dependency is missed.

Interdependencies in the toplevel widget are missed in the same way. Therefore you need to sort by separate keys separately.
Comment 24 Thomas Martitz 2013-10-18 18:53:15 UTC
Created attachment 257658 [details]
Compile with: gcc $(pkg-config glib-2.0 --cflags) test.c -o test $(pkg-config glib-2.0 --libs)
Comment 25 Juan Pablo Ugarte 2013-10-18 19:10:54 UTC
(In reply to comment #23)
> I am surprised that glade_widget_depends() is so slow on glade 3.16, in 3.8
> saving (and thus, sorting) is instant with geany.glade. Can this be a
> regression? In gdb I see it's called recursively, perhaps there is something
> fishy?
> 
> I'm also confused why you question my patch now. You have already mentioned
> that you would merge it.

Because I do not want to apply a patch that might change the current sorting order if I will have to fix it again anyways (because of how slow glade_widget_depends() is on 3.16)
Comment 26 Thomas Martitz 2013-10-18 19:28:34 UTC
Well, this contradicts your earlier statement "Yeah, I will probably commit your patch first and then work from there."

But anyway, I'm happy if you find a solution. But I hope it doesn't mean that glade git master and 3.8.x remains buggy for much longer. The current sorting solution *is bugged* and may result in incorrect .xml. I would prefer to merge a solution now if the better fix takes longer, especially since the it also has the nice side effect of making the generated xml more stable.
Comment 27 Juan Pablo Ugarte 2013-10-18 22:31:33 UTC
Created attachment 257672 [details] [review]
Same patch, added two pass implementation

As you can see, trying to sort it in two passes does not help either.
The problem is even more fundamental!

Dependency is not a transitive property so we can not use a comparison sort algorithm.
Comment 28 Thomas Martitz 2013-10-19 06:52:08 UTC
Are you sure you added the right file?

Aynway, yes you are right. When I apply my patch to my test program then it still sorts wrong. Something more sophisticated is needed to make the sort right.

So what's left from my patch is that it makes XML output more stable (less diff noise between two saved files) but I guess you won't consider it for merging anymore?
Comment 29 Juan Pablo Ugarte 2013-10-20 04:28:23 UTC
Created attachment 257737 [details] [review]
Same patch, added two pass implementation

Yeah I attached a different test.c file :)
I am afraid applying your patch is pointless since we will have to fix it properly anyways changing once again the output.

yeah what we need is topological sort, I am working on it, its almost finished it just need some testing.

btw if you have time to create test cases, including circular dependencies and such I will appreciate :)
Comment 30 Juan Pablo Ugarte 2013-10-23 22:37:07 UTC
Created attachment 257980 [details] [review]
_glade_tsort() implementation

This is my latest patch, I added a test application but we need to add more cases!
And eventually make runtime insert new object ordered
Comment 31 Juan Pablo Ugarte 2013-11-01 15:24:33 UTC
Created attachment 258741 [details] [review]
_glade_tsort() implementation

Ok I think now I am getting closer...

I fixed the way I generate the dependencies graph, the new algorithm is

for every object P in project
    for every object S in project
        if glade_widget_depends (S, P)
            add edge (P toplevel, S toplevel)

This way dependencies on children reflect on the toplevels properly.

I also removed all widget adaptor depends() implementation except
glade_gtk_widget_depends() which I left it just because of GtkIconFactory.

GtkIconFactory seems to be the only case where an object depends on another without a reference.
This could be handled differently if we choose to serialize non widgets first or if we add a weight property on the class we can use when doing the initial sort.

Anyways this patch order toplevels alphabetically first, then by dependencies, then if there is any circular dependency it repeats the process by sorting them alphabetically and by hard dependency (by hard dependency I mean a dependency on a construct-only property)
And in the case it finds a hard circular dependency, it simply break it by resetting one of the properties.

If it find a hard circular dependency it will popup a warning and will let you see the dependency if you have installed xdot.
This is just for debug see comment in glade_project_cycles_nodes_message()

So the only thing left for me to do about dependency ordering is make sure I do not add soft circular dependencies in the graph so those toplevel can keep the original alphabetical order
Comment 32 Juan Pablo Ugarte 2013-11-01 15:27:59 UTC
Created attachment 258742 [details] [review]
_glade_tsort() implementation

Ops, I forgot to include new files glade-tsort.[ch]
Comment 33 Juan Pablo Ugarte 2013-11-16 03:08:34 UTC
Ok so after lot of work on this I pushed this fix to master and glade-3-16 branch
I will have to backport it to 3.8

I made a few optimizations to the functions most used while creating the dependency graph

glade_widget_get_toplevel() now caches its value so its fast to call it in the nested for statements.
I also added _glade_widget_peek_prop_refs() to avoid creating a new list of properties each time we want to know if a widget depends on another.

With all these changes I was able to reduce executing time of sorting geany.glade from 250ms to 135ms on average, btw 99% of the time is spent building the dependency graph

Anyways toplevel order from now on should be alphabetical except when there is a dependency on other object.

Object with circular dependencies will be appended at the end in alphabetical order unless there is a hard dependency (a dependency on a construct only prop)
and at last if there are objects with hard circular dependencies they are simply appended to the end in alphabetical order.
Comment 34 Thomas Martitz 2013-11-16 10:14:32 UTC
Sounds awesome! I'm sorry that I didn't get to test it yet but I would have done so with geany.glade too, anyway.
Comment 35 Thomas Martitz 2014-01-21 22:35:46 UTC
Will this be backported to 3.8
Comment 36 Thomas Martitz 2014-02-03 13:57:11 UTC
I request to re-open as the fix hasn't been backported to 3.8 yet (as promised).
Comment 37 Juan Pablo Ugarte 2014-02-05 21:26:30 UTC
Hi Thomas, I never got time to back port it, if you are blocked on this I recommend you to dig into it, it should not be hard.

In any case I opened a new bug to track this issue #723714