[gitg] Merge CommitModel in a single class



commit 7c160ffa7b40f9ca716c31f1f5579818b9a2a657
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Jun 23 16:49:40 2013 +0200

    Merge CommitModel in a single class
    
    Simplifies hierarchy in preparation for merging libgitg and libgitg-gtk

 libgitg-gtk/gitg-gtk-commit-model.vala |  326 ++++++++++++++++++++++++++++-
 libgitg/Makefile.am                    |    3 +-
 libgitg/gitg-commit-model.vala         |  356 --------------------------------
 plugins/history/gitg-history.vala      |    4 +-
 4 files changed, 320 insertions(+), 369 deletions(-)
---
diff --git a/libgitg-gtk/gitg-gtk-commit-model.vala b/libgitg-gtk/gitg-gtk-commit-model.vala
index 6616398..acb0c97 100644
--- a/libgitg-gtk/gitg-gtk-commit-model.vala
+++ b/libgitg-gtk/gitg-gtk-commit-model.vala
@@ -61,20 +61,328 @@ namespace GitgGtk
                }
        }
 
-       public class CommitModel : Gitg.CommitModel, Gtk.TreeModel
+       public class CommitModel : Object, Gtk.TreeModel
        {
+               private Gitg.Repository d_repository;
+               private Cancellable? d_cancellable;
+               private Gitg.Commit[] d_ids;
+               private Thread<void*>? d_thread;
+               private Ggit.RevisionWalker? d_walker;
+               private uint d_advertized_size;
+               private uint d_idleid;
+               private Gitg.Lanes d_lanes;
+               private Ggit.SortMode d_sortmode;
+
+               private Ggit.OId[] d_include;
+               private Ggit.OId[] d_exclude;
+
                private uint d_size;
                private int d_stamp;
 
+               public uint limit { get; set; }
+
+               public Ggit.SortMode sort_mode
+               {
+                       get { return d_sortmode; }
+                       set
+                       {
+                               if (d_sortmode != value)
+                               {
+                                       d_sortmode = value;
+                                       reload();
+                               }
+                       }
+               }
+
+               [Notify]
+               public Gitg.Repository repository
+               {
+                       get { return d_repository; }
+                       set
+                       {
+                               cancel();
+
+                               d_walker = null;
+                               d_repository = value;
+                       }
+               }
+
+               public signal void started();
+               public signal void update(uint added);
+               public signal void finished();
+
                public CommitModel(Gitg.Repository? repository)
                {
                        Object(repository: repository);
                }
 
-               protected override void emit_started()
+               construct
+               {
+                       d_lanes = new Gitg.Lanes();
+                       d_cancellable = new Cancellable();
+                       d_cancellable.cancel();
+
+                       d_sortmode = Ggit.SortMode.TIME | Ggit.SortMode.TOPOLOGICAL;
+               }
+
+               ~CommitModel()
+               {
+                       cancel();
+               }
+
+               private void cancel()
+               {
+                       if (!d_cancellable.is_cancelled())
+                       {
+                               d_cancellable.cancel();
+
+                               d_thread.join();
+                               d_thread = null;
+                       }
+
+                       if (d_idleid != 0)
+                       {
+                               Source.remove(d_idleid);
+                               d_idleid = 0;
+                       }
+
+                       d_ids = new Gitg.Commit[0];
+                       d_advertized_size = 0;
+
+                       emit_started();
+                       finished();
+               }
+
+               public void reload()
+               {
+                       cancel();
+
+                       if (d_include.length == 0)
+                       {
+                               return;
+                       }
+
+                       walk.begin((obj, res) => {
+                               walk.end(res);
+
+                               d_cancellable.cancel();
+                               if (d_thread != null)
+                               {
+                                       d_thread.join();
+                                       d_thread = null;
+                               }
+                       });
+               }
+
+               public uint size()
+               {
+                       return d_advertized_size;
+               }
+
+               public new Gitg.Commit? @get(uint idx)
+               {
+                       Gitg.Commit? ret;
+
+                       if (idx >= d_advertized_size)
+                       {
+                               return null;
+                       }
+
+                       lock(d_ids)
+                       {
+                               ret = d_ids[idx];
+                       }
+
+                       return ret;
+               }
+
+               public void set_include(Ggit.OId[] ids)
+               {
+                       d_include = ids;
+               }
+
+               public void set_exclude(Ggit.OId[] ids)
+               {
+                       d_exclude = ids;
+               }
+
+               private void notify_batch(bool isend)
+               {
+                       lock(d_idleid)
+                       {
+                               if (d_idleid != 0)
+                               {
+                                       Source.remove(d_idleid);
+                                       d_idleid = 0;
+                               }
+                       }
+
+                       uint newsize = d_ids.length;
+
+                       d_idleid = Idle.add(() => {
+                               lock(d_idleid)
+                               {
+                                       if (d_idleid == 0)
+                                       {
+                                               return false;
+                                       }
+
+                                       d_idleid = 0;
+
+                                       uint added = newsize - d_advertized_size;
+                                       d_advertized_size = newsize;
+
+                                       emit_update(added);
+
+                                       if (isend)
+                                       {
+                                               finished();
+                                       }
+                               }
+
+                               return false;
+                       });
+               }
+
+               private async void walk()
+               {
+                       Ggit.OId[] included = d_include;
+                       Ggit.OId[] excluded = d_exclude;
+
+                       uint limit = this.limit;
+
+                       SourceFunc cb = walk.callback;
+
+                       ThreadFunc<void*> run = () => {
+                               if (d_walker == null)
+                               {
+                                       try
+                                       {
+                                               d_walker = new Ggit.RevisionWalker(d_repository);
+                                       }
+                                       catch
+                                       {
+                                               notify_batch(true);
+                                               return null;
+                                       }
+                               }
+
+                               d_walker.reset();
+                               d_walker.set_sort_mode(d_sortmode);
+
+                               foreach (Ggit.OId oid in included)
+                               {
+                                       try
+                                       {
+                                               d_walker.push(oid);
+                                       } catch {};
+                               }
+
+                               foreach (Ggit.OId oid in excluded)
+                               {
+                                       try
+                                       {
+                                               d_walker.hide(oid);
+                                       } catch {};
+                               }
+
+                               uint size;
+
+                               // Pre-allocate array to store commits
+                               lock(d_ids)
+                               {
+                                       d_ids = new Gitg.Commit[1000];
+
+                                       size = d_ids.length;
+
+                                       d_ids.length = 0;
+                                       d_advertized_size = 0;
+                               }
+
+                               Timer timer = new Timer();
+
+                               while (true)
+                               {
+                                       Ggit.OId? id;
+                                       Gitg.Commit? commit;
+
+                                       if (d_cancellable.is_cancelled())
+                                       {
+                                               break;
+                                       }
+
+                                       try
+                                       {
+                                               id = d_walker.next();
+
+                                               if (id == null)
+                                               {
+                                                       break;
+                                               }
+
+                                               commit = d_repository.lookup(id, typeof(Gitg.Commit)) as 
Gitg.Commit;
+                                       } catch { break; }
+
+                                       // Add the id
+                                       if (d_ids.length == size)
+                                       {
+                                               lock(d_ids)
+                                               {
+                                                       var oldlen = d_ids.length;
+
+                                                       size *= 2;
+
+                                                       d_ids.resize((int)size);
+                                                       d_ids.length = oldlen;
+                                               }
+                                       }
+
+                                       d_ids += commit;
+
+                                       int mylane;
+                                       var lanes = d_lanes.next(commit, out mylane);
+
+                                       commit.update_lanes((owned)lanes, mylane);
+
+                                       if (timer.elapsed() >= 200)
+                                       {
+                                               notify_batch(false);
+                                               timer.start();
+                                       }
+
+                                       if (limit > 0 && d_ids.length == limit)
+                                       {
+                                               break;
+                                       }
+                               }
+
+                               notify_batch(true);
+
+                               Idle.add((owned)cb);
+                               return null;
+                       };
+
+                       try
+                       {
+                               d_cancellable.reset();
+                               emit_started();
+                               d_thread = new Thread<void*>.try("gitg-history-walk", (owned)run);
+                               yield;
+                       }
+                       catch
+                       {
+                               finished();
+
+                               d_cancellable.cancel();
+                               d_thread = null;
+                       }
+               }
+
+               private void emit_started()
                {
                        clear();
-                       base.emit_started();
+                       d_lanes.reset();
+                       started();
                }
 
                private void clear()
@@ -93,7 +401,7 @@ namespace GitgGtk
                        ++d_stamp;
                }
 
-               protected override void emit_update(uint added)
+               private void emit_update(uint added)
                {
                        var path = new Gtk.TreePath.from_indices(d_size);
 
@@ -110,7 +418,7 @@ namespace GitgGtk
                                path.next();
                        }
 
-                       base.emit_update(added);
+                       update(added);
                }
 
                public Type get_column_type(int index)
@@ -169,7 +477,7 @@ namespace GitgGtk
                        return_if_fail(iter.stamp == d_stamp);
 
                        uint idx = (uint)(ulong)iter.user_data;
-                       Gitg.Commit? commit = base[idx];
+                       Gitg.Commit? commit = this[idx];
 
                        val.init(get_column_type(column));
 
@@ -227,7 +535,7 @@ namespace GitgGtk
 
                        uint idx = (uint)(ulong)iter.user_data;
 
-                       return base[idx];
+                       return this[idx];
                }
 
                public Gitg.Commit? commit_from_path(Gtk.TreePath path)
@@ -239,7 +547,7 @@ namespace GitgGtk
                                return null;
                        }
 
-                       return base[(uint)indices[0]];
+                       return this[(uint)indices[0]];
                }
 
                public bool iter_children(out Gtk.TreeIter iter, Gtk.TreeIter? parent)
@@ -322,4 +630,4 @@ namespace GitgGtk
        }
 }
 
-// vi:ts=4
+// ex:set ts=4 noet
diff --git a/libgitg/Makefile.am b/libgitg/Makefile.am
index 237861e..b7e337d 100644
--- a/libgitg/Makefile.am
+++ b/libgitg/Makefile.am
@@ -40,8 +40,7 @@ VALA_FILES =                          \
        gitg-lanes.vala                 \
        gitg-color.vala                 \
        gitg-init.vala                  \
-       gitg-commit.vala                \
-       gitg-commit-model.vala
+       gitg-commit.vala
 
 # Ignore all warnings for vala code...
 libgitg_1_0_la_CFLAGS =                \
diff --git a/plugins/history/gitg-history.vala b/plugins/history/gitg-history.vala
index d335fff..a45256b 100644
--- a/plugins/history/gitg-history.vala
+++ b/plugins/history/gitg-history.vala
@@ -116,7 +116,7 @@ namespace GitgHistory
                        }
                }
 
-               private void on_commit_model_started(Gitg.CommitModel model)
+               private void on_commit_model_started(GitgGtk.CommitModel model)
                {
                        if (d_insertsig == 0)
                        {
@@ -140,7 +140,7 @@ namespace GitgHistory
                        }
                }
 
-               private void on_commit_model_finished(Gitg.CommitModel model)
+               private void on_commit_model_finished(GitgGtk.CommitModel model)
                {
                        if (d_insertsig != 0)
                        {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]