Partial Fix #5782 - messing around with libgit2-glib
authorAlan Knowles <alan@roojs.com>
Wed, 27 Mar 2019 06:26:05 +0000 (14:26 +0800)
committerAlan Knowles <alan@roojs.com>
Wed, 27 Mar 2019 06:26:05 +0000 (14:26 +0800)
21 files changed:
Clones.bjs
Clones.vala
Git.vala [new file with mode: 0644]
Git2.vala [new file with mode: 0644]
GitBranch.vala
GitCallbacks.vala [new file with mode: 0644]
GitMonitor.vala
GitMonitorQueue.vala
GitRepo.vala
Gitlive.vala
Makefile.am
MergeBranch.bjs
NewBranch.bjs
NewBranch.vala
RepoStatusPopover.bjs
StatusIcon.vala
Ticket.bjs
Ticket.vala
c/push.c.vala [new file with mode: 0644]
config1.builder
configure.ac

index d1c1402..555a6b7 100644 (file)
@@ -13,7 +13,7 @@
     "response" : "(self, response_id) =>  { \n \n        this.el.hide();\n  \n}"
    },
    "boolean deletable" : true,
-   "| void loadAndShow" : "() {\n\tthis.el.set_deletable(true);\n    this.el.set_gravity(Gdk.Gravity.NORTH);\n    this.el.move((Gdk.Screen.width() / 2 ) - (int.min(1280,Gdk.Screen.width()) / 2) ,0);\n     this.el.set_keep_above(true);\n    this.el.set_default_size(\n\t\t\tint.min(1280,Gdk.Screen.width()),\n\t\t\tint.max(500,Gdk.Screen.height() - 200)\n\t);\n\tthis.el.show_all();\n\t\n\tthis.toolbar.el.hide();\n\tthis.scrolled.el.hide();\n\tthis.spinner.el.show();\n\tthis.spinner.el.start();\t\n\t\n\tGitRepo.updateAll(\"show_clones\");\n\t\n     \n \n\t\n\t\n}\n\n",
+   "| void loadAndShow" : "() {\n\tthis.el.set_deletable(true);\n    this.el.set_gravity(Gdk.Gravity.NORTH);\n    this.el.move((Gdk.Screen.width() / 2 ) - (int.min(1280,Gdk.Screen.width()) / 2) ,0);\n     this.el.set_keep_above(true);\n    this.el.set_default_size(\n\t\t\tint.min(1280,Gdk.Screen.width()),\n\t\t\tint.max(500,Gdk.Screen.height() - 200)\n\t);\n\tthis.el.show_all();\n\t\n\tthis.toolbar.el.hide();\n\tthis.scrolled.el.hide();\n\tthis.spinner.el.show();\n\tthis.spinner.el.start();\t\n\t\n\tGitRepo.updateAllAsync(\"show_clones\");\n\t\n     \n \n\t\n\t\n}\n\n",
    "default_width" : 1024,
    "| void show" : "()    {\nthis.el.set_deletable(true);\n    this.el.set_gravity(Gdk.Gravity.NORTH);\n    this.el.move((Gdk.Screen.width() / 2 ) - (int.max(1280,Gdk.Screen.width()) / 2) ,0);\n     this.el.set_keep_above(true);\n   this.el.set_default_size(\n\t\t\tint.max(1280,Gdk.Screen.width()),\n\t\t\tint.max(500,Gdk.Screen.height() - 100)\n\t);\n    this.el.show_all();\n\tthis.spinner.el.stop();\n\tthis.spinner.el.hide();\t\n\tthis.toolbar.el.show();\n\tthis.scrolled.el.show();\t\n \n    \n     \n\n    this.reposStore.load();\n   \n    GLib.debug(\"show clones = run?\");\n    this.el.run();\n    // load clones..\n//     this.get('/reposStore').load();\n    \n    //this.get('/ok_button').el.set_sensitive(false);\n    \n    // block until we return.\n//    var run_ret = this.el.run();\n//    if (run_ret < 1 ) {\n//        return  \"DONE\";\n//    }\n//    print(\"RUN RETURN : \" + run_ret);\n//    return \"DONE\";\n    //print(JSON.stringify(this.get('bug').getValue()));\n   // return this.get('bug').getValue();\n    //this.success = c.success;\n}\n",
    "title" : "Manage Clones",
        "items" : [
         {
          "listeners" : {
-          "row_activated" : "(path, col)  =>  {\n\n\tif (col.title == \"Auto Commit\" || col.title == \"Auto Push\" || col.title == \"Auto Branch\") {\n\t\treturn;\n\t}\n\t\n\t//\n\t\n\tGtk.TreeIter iter;\n\t_this.reposStore.el.get_iter(out iter, path);\n\tGLib.Value val;\n    _this.reposStore.el.get_value(iter, 6, out val);\n    var git_working_dir = (string)val;\n    \n    var repo = GitRepo.singleton().get(git_working_dir);\n    \n    Gdk.Rectangle rect;\n    _this.reposView.el.get_cell_area(path, col, out rect);\n    RepoStatusPopover.singleton().show(this.el, rect, repo);\n    \n     \n    \n}",
+          "row_activated" : "(path, col)  =>  {\n\n\tif (col.title == \"Auto Commit\" || col.title == \"Auto Push\" || col.title == \"Auto Branch\") {\n\t\treturn;\n\t}\n\t\n\t//\n\t\n\tGtk.TreeIter iter;\n\t_this.reposStore.el.get_iter(out iter, path);\n\tGLib.Value val;\n    _this.reposStore.el.get_value(iter, 6, out val);\n    var git_working_dir = (string)val;\n    \n    var repo = GitRepo.singleton().get_sync(git_working_dir);\n    \n    Gdk.Rectangle rect;\n    _this.reposView.el.get_cell_area(path, col, out rect);\n    RepoStatusPopover.singleton().show(this.el, rect, repo);\n    \n     \n    \n}",
           "cursor_changed" : "()  => {\n  // SEE SELECTION.CHANGED\n  /*\n  \n  return;\n  \n    if (this.el.get_selection().count_selected_rows() < 1) {\n        //nothing? - clea it?\n        return;\n    }\n        var ret = {};         \n    var model = this.get('/changedFilesStore');\n\n     var s = this.el.get_selection();\n     var files = [];\n    s.selected_foreach(function(model,p,iter) {\n    \n       files.push( model.get_value(iter, 0).value.get_string());\n     \n    });\n    this.get('/patchview').showDiff(files); \n    //var value = ''+ ret.model.get_value(ret.iter, 1).value.get_string();\n     //print(\"OUT?\" + value);// id..\n    // load the list in the right grid..\n     \n    return true;\n*/\n}"
          },
          "id" : "reposView",
-         "bool activate_on_single_click" : true,
          "* init" : " \n{\n    var selection = this.el.get_selection();\n    selection.set_mode( Gtk.SelectionMode.SINGLE);\n\n\n    var description = new Pango.FontDescription();\n    description.set_size(10000);\n    this.el.override_font(description);\n \n}\n",
+         "bool activate_on_single_click" : true,
          "xtype" : "TreeView",
          "* pack" : "add",
          "int search_column" : 0,
@@ -88,7 +88,7 @@
            "$ pathToRepo" : "function(path) {\n\n    var tr= this.repos;\n\n    \n    for(var i =0 ; i < tr.length; i++) {\n        if (tr[i].repopath == path) {\n            return tr[i];\n        }\n    } \n    return false; \n}\n",
            "xtype" : "ListStore",
            "* pack" : "set_model",
-           "| void load" : "()\n{\n    //this.insert(citer,iter,0);\n    print(\"getting list\");\n    var tr = GitRepo.list();\n    \n    this.el.clear();\n    \n    // fixme .. sort by last updated ...\n    \n    \n    for(var i =0 ; i < tr.length; i++) {\n\t    var repo = tr.index(i);\n\t    // this is done before we display stuff...\n\t    //repo.loadBranches();\n\t    //repo.loadStatus();\n\t    \n\t    Gtk.TreeIter iter;\n\t    this.el.append(out iter);\n     \n        //print(JSON.stringify(ret,null,4));\n         //tr[i].getBranches();\n         //tr[i].getStatus();\n         //var hi;\n         //try {\n             //tr[i].debug=1;\n         //     hi = tr[i].history('/', 1, 'branch', tr[i].currentBranch.name );\n//             print(JSON.stringify(hi,null,4));\n        // } catch(e) { print(e);}\n          \n        this.el.set_value(iter, 0,   repo.name );\n        this.el.set_value( iter, 1, repo.currentBranch.name   );\n        this.el.set_value( iter, 2,  repo.branchesToString()   );\n//        this.el.set_value(ret.iter, 2, '' + repo.branches.map(\n//                        function(e) { return e.name; \n//                    }).join(', ') \n //        );\n//        this.el.set_value(iter, 3, '' +  (!hi  ? '??' : hi[0].changed_raw));        \n        this.el.set_value(iter, 4, repo.is_autocommit() );                \n        this.el.set_value(iter, 5, repo.is_autopush() );                        \n        this.el.set_value(iter, 6,  repo.git_working_dir );  \n        // highlight color.\n        var cb = repo.currentBranch;\n        //print(JSON.stringify(cb,null,4));\n        var col = \"#ffffff\";\n        \n        if (cb.lastrev != cb.remoterev) {\n            col =  \"#f2dede\";\n            this.el.set_value( iter, 1, repo.currentBranch.name +\"\\n\" +\n            \t(repo.ahead_or_behind == \"B\" ? \"Local is BEHIND remote\" : \"Local is AHEAD of remote\")\n            \n               );\n        }\n        if (repo.has_local_changes) {\n            col =  \"#d9edf7\";\n            this.el.set_value( iter, 1, repo.currentBranch.name +\"\\nHas uncommitted changes\"   );\n        }\n        if  ((cb.lastrev != cb.remoterev) && (repo.has_local_changes)) {\n            col =  \"#fcf8e3\";\n            this.el.set_value( iter, 1, repo.currentBranch.name +\"\\n\" + \n            (repo.ahead_or_behind == \"B\" ? \"Local is BEHIND remote\" : \"Local is AHEAD of remote\") +\n            \"\\nHas uncommitted changes\"   );            \n        }\n        \n        this.el.set_value(iter, 7, col  );      \n        var ticket = repo.activeTicket;\n        \n        this.el.set_value(iter, 8, repo.is_auto_branch()  );      \n        this.el.set_value(iter, 9, ticket == null ? \"\" : ticket.id  );      \n        \n        \n    }     \n    this.el.set_sort_column_id (0, Gtk.SortType.ASCENDING);\n} ",
+           "| void load" : "()\n{\n    //this.insert(citer,iter,0);\n    print(\"getting list\");\n    var tr = GitRepo.list();\n    \n    this.el.clear();\n    \n    // fixme .. sort by last updated ...\n    \n    \n    for(var i =0 ; i < tr.length; i++) {\n\t    var repo = tr.index(i);\n\t    // this is done before we display stuff...\n\t    //repo.loadBranches();\n\t    //repo.loadStatus();\n\t    \n\t    Gtk.TreeIter iter;\n\t    this.el.append(out iter);\n     \n        //print(JSON.stringify(ret,null,4));\n         //tr[i].getBranches();\n         //tr[i].getStatus();\n         //var hi;\n         //try {\n             //tr[i].debug=1;\n         //     hi = tr[i].history('/', 1, 'branch', tr[i].currentBranch.name );\n//             print(JSON.stringify(hi,null,4));\n        // } catch(e) { print(e);}\n          \n        this.el.set_value(iter, 0,   repo.name );\n        this.el.set_value( iter, 1, repo.getCurrentBranch().name   );\n        this.el.set_value( iter, 2,  repo.branchesToString()   );\n//        this.el.set_value(ret.iter, 2, '' + repo.branches.map(\n//                        function(e) { return e.name; \n//                    }).join(', ') \n //        );\n//        this.el.set_value(iter, 3, '' +  (!hi  ? '??' : hi[0].changed_raw));        \n        this.el.set_value(iter, 4, repo.is_autocommit() );                \n        this.el.set_value(iter, 5, repo.is_autopush() );                        \n        this.el.set_value(iter, 6,  repo.git_working_dir );  \n        // highlight color.\n        var cb = repo.getCurrentBranch();\n        //print(JSON.stringify(cb,null,4));\n        var col = \"#ffffff\";\n        \n        if (cb.lastrev != cb.remoterev) {\n            col =  \"#f2dede\";\n            this.el.set_value( iter, 1, repo.getCurrentBranch().name +\"\\n\" +\n            \t(repo.ahead_or_behind == \"B\" ? \"Local is BEHIND remote\" : \"Local is AHEAD of remote\")\n            \n               );\n        }\n        if (repo.has_local_changes) {\n            col =  \"#d9edf7\";\n            this.el.set_value( iter, 1, repo.getCurrentBranch().name +\"\\nHas uncommitted changes\"   );\n        }\n        if  ((cb.lastrev != cb.remoterev) && (repo.has_local_changes)) {\n            col =  \"#fcf8e3\";\n            this.el.set_value( iter, 1, repo.getCurrentBranch().name +\"\\n\" + \n            (repo.ahead_or_behind == \"B\" ? \"Local is BEHIND remote\" : \"Local is AHEAD of remote\") +\n            \"\\nHas uncommitted changes\"   );            \n        }\n        \n        this.el.set_value(iter, 7, col  );      \n        var ticket = repo.activeTicket;\n        \n        this.el.set_value(iter, 8, repo.is_auto_branch()  );      \n        this.el.set_value(iter, 9, ticket == null ? \"\" : ticket.id  );      \n        \n        \n    }     \n    this.el.set_sort_column_id (0, Gtk.SortType.ASCENDING);\n} ",
            "$ xns" : "Gtk"
           },
           {
            "items" : [
             {
              "listeners" : {
-              "toggled" : "  (self, path)  => {\n  \n  \tGtk.TreeIter iter;\n  \t_this.reposStore.el.get_iter_from_string(out iter, path);\n  \t\n  \tGLib.Value val;\n  \tGLib.Value rval;\n  \t_this.reposStore.el.get_value(iter, 4, out val);\n  \t_this.reposStore.el.get_value(iter, 6, out rval);\n  \t\n  \tvar repopath = (string)rval;\n  \tvar bval = (bool)val;\n  \t_this.reposStore.el.set_value(iter, 4, !bval);\n  \tGLib.debug(\"got repopath? %s\", repopath);\n  \t\n  \tvar repo = GitRepo.get(repopath);\n  \trepo.set_autocommit(!bval);\n  \t\n  \t\n  \t\n  \n}"
+              "toggled" : "  (self, path)  => {\n  \n  \tGtk.TreeIter iter;\n  \t_this.reposStore.el.get_iter_from_string(out iter, path);\n  \t\n  \tGLib.Value val;\n  \tGLib.Value rval;\n  \t_this.reposStore.el.get_value(iter, 4, out val);\n  \t_this.reposStore.el.get_value(iter, 6, out rval);\n  \t\n  \tvar repopath = (string)rval;\n  \tvar bval = (bool)val;\n  \t_this.reposStore.el.set_value(iter, 4, !bval);\n  \tGLib.debug(\"got repopath? %s\", repopath);\n  \t\n  \tvar repo = GitRepo.get_sync(repopath);\n  \trepo.set_autocommit(!bval);\n  \t \n  \n}"
              },
              "id" : "cr_autocommit",
-             "* pack" : "pack_start,false",
              "xtype" : "CellRendererToggle",
+             "* pack" : "pack_start,false",
              "$ xns" : "Gtk",
              "$ mode" : "Gtk.CellRendererMode.ACTIVATABLE"
             }
            "items" : [
             {
              "listeners" : {
-              "toggled" : "  (self, path)  => {\n  \n  \tGtk.TreeIter iter;\n  \t_this.reposStore.el.get_iter_from_string(out iter, path);\n  \t\n  \tGLib.Value val;\n  \tGLib.Value rval;\n  \t_this.reposStore.el.get_value(iter, 5, out val);\n  \t_this.reposStore.el.get_value(iter, 6, out rval);\n  \t\n  \tvar repopath = (string)rval;\n  \tvar bval = (bool)val;\n  \t_this.reposStore.el.set_value(iter, 5, !bval);\n  \tvar repo = GitRepo.get(repopath);\n  \trepo.set_autopush(!bval);\n  \t\n  \t\n  \t\n  \n}"
+              "toggled" : "  (self, path)  => {\n  \n  \tGtk.TreeIter iter;\n  \t_this.reposStore.el.get_iter_from_string(out iter, path);\n  \t\n  \tGLib.Value val;\n  \tGLib.Value rval;\n  \t_this.reposStore.el.get_value(iter, 5, out val);\n  \t_this.reposStore.el.get_value(iter, 6, out rval);\n  \t\n  \tvar repopath = (string)rval;\n  \tvar bval = (bool)val;\n  \t_this.reposStore.el.set_value(iter, 5, !bval);\n  \tvar repo = GitRepo.get_sync(repopath);\n  \trepo.set_autopush(!bval);\n  \t\n  \t\n  \t\n  \n}"
              },
              "id" : "cr_autopush",
-             "* pack" : "pack_start,false",
              "xtype" : "CellRendererToggle",
+             "* pack" : "pack_start,false",
              "$ xns" : "Gtk",
              "$ mode" : "Gtk.CellRendererMode.ACTIVATABLE"
             }
            "items" : [
             {
              "listeners" : {
-              "toggled" : "  (self, path)  => {\n  \n  \tGtk.TreeIter iter;\n  \t_this.reposStore.el.get_iter_from_string(out iter, path);\n  \t\n  \tGLib.Value val;\n  \tGLib.Value rval;\n  \t_this.reposStore.el.get_value(iter, 8, out val);\n  \t_this.reposStore.el.get_value(iter, 6, out rval);\n  \t\n  \tvar repopath = (string)rval;\n  \tvar bval = (bool)val;\n  \t_this.reposStore.el.set_value(iter, 8, !bval);\n  \tvar repo = GitRepo.get(repopath);\n  \trepo.set_auto_branch(!bval);\n  \t\n  \t\n  \t\n  \n}"
+              "toggled" : "  (self, path)  => {\n  \n  \tGtk.TreeIter iter;\n  \t_this.reposStore.el.get_iter_from_string(out iter, path);\n  \t\n  \tGLib.Value val;\n  \tGLib.Value rval;\n  \t_this.reposStore.el.get_value(iter, 8, out val);\n  \t_this.reposStore.el.get_value(iter, 6, out rval);\n  \t\n  \tvar repopath = (string)rval;\n  \tvar bval = (bool)val;\n  \t_this.reposStore.el.set_value(iter, 8, !bval);\n  \tvar repo = GitRepo.get_sync(repopath);\n  \trepo.set_auto_branch(!bval);\n  \t\n  \t\n  \t\n  \n}"
              },
              "id" : "cr_autobranch",
-             "xtype" : "CellRendererToggle",
              "* pack" : "pack_start,false",
+             "xtype" : "CellRendererToggle",
              "$ xns" : "Gtk",
              "$ mode" : "Gtk.CellRendererMode.ACTIVATABLE"
             }
           },
           {
            "id" : "tv_repo",
-           "* init" : "\n    this.el.add_attribute(_this.cr_repo.el , \"markup\", 0 );\n",
            "Gtk.SortType sort_order" : "Gtk.SortType.ASCENDING",
+           "* init" : "\n    this.el.add_attribute(_this.cr_repo.el , \"markup\", 0 );\n",
            "title" : "Repo",
            "* pack" : "append_column",
            "xtype" : "TreeViewColumn",
            "items" : [
             {
              "id" : "cr_repo",
-             "* pack" : "pack_start,false",
              "xtype" : "CellRendererText",
+             "* pack" : "pack_start,false",
              "$ xns" : "Gtk"
             }
            ]
            "items" : [
             {
              "id" : "cr_active_ticket",
-             "xtype" : "CellRendererText",
              "* pack" : "pack_start,false",
+             "xtype" : "CellRendererText",
              "$ xns" : "Gtk"
             }
            ]
            "items" : [
             {
              "id" : "cr_current_branch",
-             "* pack" : "pack_start,false",
              "xtype" : "CellRendererText",
+             "* pack" : "pack_start,false",
              "$ xns" : "Gtk"
             }
            ]
            "items" : [
             {
              "id" : "cr_last_updated",
-             "* pack" : "pack_start,false",
              "xtype" : "CellRendererText",
+             "* pack" : "pack_start,false",
              "$ xns" : "Gtk"
             }
            ]
            "items" : [
             {
              "id" : "cr_all_branches",
-             "* pack" : "pack_start,false",
              "xtype" : "CellRendererText",
+             "* pack" : "pack_start,false",
              "$ xns" : "Gtk"
             }
            ]
index 123d5ae..d4c267b 100644 (file)
@@ -85,7 +85,7 @@ public class Clones : Object
        this.spinner.el.show();
        this.spinner.el.start();        
        
-       GitRepo.updateAll("show_clones");
+       GitRepo.updateAllAsync("show_clones");
        
          
      
@@ -361,7 +361,7 @@ public class Clones : Object
                 _this.reposStore.el.get_value(iter, 6, out val);
                 var git_working_dir = (string)val;
                 
-                var repo = GitRepo.singleton().get(git_working_dir);
+                var repo = GitRepo.singleton().get_sync(git_working_dir);
                 
                 Gdk.Rectangle rect;
                 _this.reposView.el.get_cell_area(path, col, out rect);
@@ -464,7 +464,7 @@ public class Clones : Object
                 // } catch(e) { print(e);}
                   
                 this.el.set_value(iter, 0,   repo.name );
-                this.el.set_value( iter, 1, repo.currentBranch.name   );
+                this.el.set_value( iter, 1, repo.getCurrentBranch().name   );
                 this.el.set_value( iter, 2,  repo.branchesToString()   );
         //        this.el.set_value(ret.iter, 2, '' + repo.branches.map(
         //                        function(e) { return e.name; 
@@ -475,24 +475,24 @@ public class Clones : Object
                 this.el.set_value(iter, 5, repo.is_autopush() );                        
                 this.el.set_value(iter, 6,  repo.git_working_dir );  
                 // highlight color.
-                var cb = repo.currentBranch;
+                var cb = repo.getCurrentBranch();
                 //print(JSON.stringify(cb,null,4));
                 var col = "#ffffff";
                 
                 if (cb.lastrev != cb.remoterev) {
                     col =  "#f2dede";
-                    this.el.set_value( iter, 1, repo.currentBranch.name +"\n" +
+                    this.el.set_value( iter, 1, repo.getCurrentBranch().name +"\n" +
                        (repo.ahead_or_behind == "B" ? "Local is BEHIND remote" : "Local is AHEAD of remote")
                     
                        );
                 }
                 if (repo.has_local_changes) {
                     col =  "#d9edf7";
-                    this.el.set_value( iter, 1, repo.currentBranch.name +"\nHas uncommitted changes"   );
+                    this.el.set_value( iter, 1, repo.getCurrentBranch().name +"\nHas uncommitted changes"   );
                 }
                 if  ((cb.lastrev != cb.remoterev) && (repo.has_local_changes)) {
                     col =  "#fcf8e3";
-                    this.el.set_value( iter, 1, repo.currentBranch.name +"\n" + 
+                    this.el.set_value( iter, 1, repo.getCurrentBranch().name +"\n" + 
                     (repo.ahead_or_behind == "B" ? "Local is BEHIND remote" : "Local is AHEAD of remote") +
                     "\nHas uncommitted changes"   );            
                 }
@@ -577,11 +577,9 @@ public class Clones : Object
                _this.reposStore.el.set_value(iter, 4, !bval);
                GLib.debug("got repopath? %s", repopath);
                
-               var repo = GitRepo.get(repopath);
+               var repo = GitRepo.get_sync(repopath);
                repo.set_autocommit(!bval);
-               
-               
-               
+                
               
             });
         }
@@ -656,7 +654,7 @@ public class Clones : Object
                var repopath = (string)rval;
                var bval = (bool)val;
                _this.reposStore.el.set_value(iter, 5, !bval);
-               var repo = GitRepo.get(repopath);
+               var repo = GitRepo.get_sync(repopath);
                repo.set_autopush(!bval);
                
                
@@ -735,7 +733,7 @@ public class Clones : Object
                var repopath = (string)rval;
                var bval = (bool)val;
                _this.reposStore.el.set_value(iter, 8, !bval);
-               var repo = GitRepo.get(repopath);
+               var repo = GitRepo.get_sync(repopath);
                repo.set_auto_branch(!bval);
                
                
diff --git a/Git.vala b/Git.vala
new file mode 100644 (file)
index 0000000..795eabb
--- /dev/null
+++ b/Git.vala
@@ -0,0 +1,712 @@
+
+// valac -o /tmp/ggit Git.vala --pkg libgit2-glib-1.0 --pkg libsoup-2.4 --pkg gee-0.8 -g
+
+void main()
+{
+        GLib.Log.set_handler(null, 
+            GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_INFO, 
+            (dom, lvl, msg) => {
+                                       
+                                       
+               // should we debug..
+                                       
+                       
+               print("%s\n", msg);
+            }
+         ); 
+
+       
+       Ggit.init();
+       var a = new GitLive.Repo("/home/alan/gitlive/gitlive");
+       a.diffhead();
+       //a.fetchAll();
+       return;
+       /*
+       GLib.Timeout.add (1, () => {
+      GLib.debug("Meanwhile");
+      return true;
+    }, GLib.Priority.HIGH);
+       
+       var loop = new MainLoop();
+        
+       var a = new GitLive.Repo("/home/alan/gitlive/web.coba");
+      GLib.debug("Starting");  
+       a.loadRemoteHeads.begin(true, (obj,res) => {
+               a.loadRemoteHeads.end(res);
+                GLib.debug("got results");
+               a.loadLocalBranches();
+               loop.quit();
+       });
+       loop.run();
+       //a.mergeMasterIntoHead();
+       //a.walkDiff();
+       //return;
+       //a.is_managed();
+       //a.is_autocommit();
+       
+
+       //a.fetchAll();
+       //
+       /*
+       var a = new GitLive.Repo("/home/alan/git/test1-clone");
+       //a.fetchAll();
+       var str = (new GLib.DateTime.now_utc()).format("%Y-%m-%d %H:%M:%S");
+       GLib.FileUtils.set_contents("/home/alan/git/test1-clone/test1",  str); 
+       
+       var ix = a.repo.get_index();
+       ix.add_path("test1");
+       ix.write();
+       var treeoid = ix.write_tree();
+
+       var head = a.repo.get_head();
+       var parent = head.lookup() as Ggit.Commit;
+       Ggit.Commit[] parents = (parent == null) ? 
+               new Ggit.Commit[] {} :
+               new Ggit.Commit[] { parent };
+
+       var tree = a.repo.lookup(treeoid,typeof (Ggit.Tree))  as   Ggit.Tree;// odd format.. 
+       
+       var sig = new Ggit.Signature.now("Alan Knowles", "alan@roojs.com");
+       a.repo.create_commit("HEAD", sig, sig, null, "test commit " + str, tree, parents);
+       */
+       // mmh.. no git add/commit in library...
+//     string[] spawn_args = {"git", "commit", "-m", "test", "-a"};
+       //string[] spawn_env = Environ.get ();
+//     Process.spawn_sync ("/home/alan/git/test1-clone", spawn_args, spawn_env, SpawnFlags.SEARCH_PATH, null);
+       //a.pushAll();
+}
+
+namespace  GitLive {
+
+       public class Repo : Object {
+
+               string name = "";
+               public Ggit.Repository  repo;
+               Callbacks callbacks;
+
+               public Repo(string path)
+               {
+                       this.name = GLib.Path.get_basename(path);
+                       this.repo = Ggit.Repository.open(GLib.File.new_for_path(path));
+                       this.callbacks = new Callbacks(this);
+               
+               }
+               Ggit.Branch                                             head = null;
+           Gee.ArrayList<Ggit.Branch>          branches = null;
+           Ggit.RemoteHead[]                           remote_heads = null;
+               public void loadLocalBranches(bool force = false)
+               {
+                       if (!force && this.branches != null) {
+                               return;
+                       }
+                       
+                       this.branches =  new Gee.ArrayList<Ggit.Branch>();
+                       var r = this.repo.enumerate_branches(Ggit.BranchType.LOCAL);
+                       while (r.next()) {
+                               var br = r.get() as Ggit.Branch;
+                               if (br == null) {
+                                       continue;
+                               }
+                               if (br.is_tag()) {
+                                       continue;
+                               }
+                               
+                               //var head = this.repo.revparse("refs/heads/" + br.get_name() ).get_id();
+                               //var rhead = this.repo.revparse(br.get_upstream().get_name() ).get_id();
+                               try {
+                                       GLib.debug("got branch: N=%s", br.get_name() );
+                                       GLib.debug("is_head %s", br.is_head() ? "Y" : "n");
+
+                                       GLib.debug("upstream = %s", br.get_upstream() == null ? "??" : br.get_upstream().get_name().substring(20));
+                                       GLib.debug("oid = %s",br.get_target().to_string());
+                                       this.branches.add(br);
+                                       if (br.is_head()) {
+                                               GLib.debug("HEAD= %s", br.get_name());
+                                               this.head = br;
+                                       }
+                               } catch (Error e) {
+                                       GLib.debug("Skip branch");
+                               }
+                       }
+                       
+                       
+               }
+                
+               public bool is_managed()
+               {
+                       GLib.debug("is_managed: %d", this.repo.get_config().get_int32("gitlive.managed"));
+                       return this.repo.get_config().get_int32("gitlive.managed") == 1;
+               }
+               
+               
+               public bool is_autocommit ()
+               {       
+                       GLib.debug("is_autocommit: %d", this.repo.get_config().get_int32("gitlive.autocommit"));
+                       return this.repo.get_config().get_int32("gitlive.autocommit") == 1;
+               }
+               public void set_autocommit(bool val)
+               {
+                       this.repo.get_config().set_int32("gitlive.autocommit", val ? 1 : 0);
+               
+               }
+                
+               public void walkDiff()
+               {
+                       this.loadLocalBranches();
+                       
+                       
+                       
+                       var oid =  this.repo.revparse(this.head.get_name() ).get_id()  ;
+                       var moid =  this.repo.revparse("refs/heads/master" ).get_id()  ;
+                       
+                       var a = new Ggit.RevisionWalker(this.repo);
+                       a.set_sort_mode(Ggit.SortMode.TOPOLOGICAL);
+                       a.push(oid);
+                       a.hide(moid);
+                       var last = oid;
+                       for (var noid = a.next(); noid != null; noid= a.next()) {
+                               //var commit = this.repo.lookup(noid, typeof(Ggit.Commit)) as Ggit.Commit;
+                               GLib.debug("rev: %s",
+                                       noid.to_string()
+                               );
+                               last = noid;
+                       }
+                       var commit = this.repo.lookup(last, typeof(Ggit.Commit)) as Ggit.Commit;
+                       var parent = commit.get_parents();
+                       GLib.debug("parent = %s", parent.get_id(0).to_string());
+                       var master_rev =  parent.get_id(0);
+                       var master_commit  = this.repo.lookup_commit(master_rev);;
+                       
+                       var head_commit = this.repo.lookup_commit(oid);
+                       
+                       var master_tree = master_commit.get_tree();
+                       var head_tree = head_commit.get_tree();
+                       
+                       var diff = new Ggit.Diff.tree_to_tree(this.repo, master_tree, head_tree, new Ggit.DiffOptions());
+                       
+                       diff.print(Ggit.DiffFormatType.PATCH, ( delta,  hunk,  line) => {
+                               GLib.debug("%d: %s, %s", line.get_new_lineno(), line.get_origin().to_string(), line.get_text());
+                               return 0;
+                       });
+                       // let's try a merge..
+                       var mo = new Ggit.MergeOptions();
+                       mo.set_file_favor(Ggit.MergeFileFavor.THEIRS);
+                       var ix = this.repo.merge_trees(master_tree, master_tree, head_tree, mo);
+                       
+                       if (ix.has_conflicts()) {
+                               GLib.debug("merge has conflicts");
+                               return;
+                       }
+                        var treeoid = ix.write_tree();
+                        
+                        
+                         
+                       var parents =   new Ggit.Commit[] { master_commit };
+
+
+                       var new_tree = this.repo.lookup(treeoid,typeof (Ggit.Tree))  as   Ggit.Tree;
+                       
+                       var sig = new Ggit.Signature.now(
+                                       this.repo.get_config().get_string("user.name"),
+                                       this.repo.get_config().get_string("user.email")
+                       );
+                       
+                       
+                       
+                       this.repo.create_commit("HEAD", sig, sig, null, "Test Merge", new_tree, parents);
+        
+                       
+                       
+               }
+               
+               public void diffhead()
+               {
+                       var r = this.repo.enumerate_branches(Ggit.BranchType.LOCAL);
+                       Ggit.Branch? head = null;
+                       while (r.next()) {
+                               var gbr = r.get() as Ggit.Branch;
+                               if (gbr.is_head()) {
+                                       head = gbr;
+                               }
+                       }
+                       GLib.debug("checking head=%s",head == null ? "EMPTY" :  head.get_name());
+                       var br = this.repo.lookup_branch(head.get_name(),Ggit.BranchType.LOCAL);
+                       var commit  = this.repo.lookup_commit(br.get_target());
+
+                       
+                       var diff = new Ggit.Diff.tree_to_workdir(this.repo, commit.get_tree(), new Ggit.DiffOptions());
+                       var ret = "";
+                       diff.print(Ggit.DiffFormatType.PATCH, (delta, hunk, line) => {
+                               switch(line.get_origin()) {
+                                       case Ggit.DiffLineType.ADDITION: ret+="+"; break;
+                                       case Ggit.DiffLineType.DELETION: ret+="-";break;
+                                       case Ggit.DiffLineType.CONTEXT:  ret+=" ";break;
+                                       case Ggit.DiffLineType.HUNK_HDR: break;                                 
+                                       case Ggit.DiffLineType.FILE_HDR: break;
+                                       default: ret+=" ";break;
+                               }
+                               ret += " " + line.get_text();
+                               return 0;
+                       });
+                       GLib.debug("%s", ret);
+               }
+               
+               
+               public void mergeMasterIntoHead()
+               {
+                       // assumes head is not master...
+                       this.loadLocalBranches();
+                       GLib.debug("head rev = %s", this.head.get_name());
+                       var head_oid =  this.repo.revparse(this.head.get_name() ).get_id()  ;
+                       //var master_oid =  this.repo.revparse("refs/heads/master" ).get_id()  ;
+                       var master_oid =  this.repo.revparse("HEAD" ).get_id()  ;
+
+                       var master_commit  = this.repo.lookup_commit(master_oid);;
+                       var head_commit = this.repo.lookup_commit(head_oid);
+                        
+               
+                       var anc_oid = this.repo.merge_base(master_commit.get_id(), head_commit.get_id());
+                       
+                       var anc_commit = this.repo.lookup_commit(anc_oid);
+                       var anc_tree = anc_commit.get_tree();
+                       
+                       var mo = new Ggit.MergeOptions();
+                       var co = new Ggit.CheckoutOptions();
+                       var the_ref = this.repo.lookup_reference_dwim("refs/heads/master");
+
+                   var ac = new Ggit.AnnotatedCommit.from_ref(this.repo, the_ref);
+                       
+                       var commits =   new Ggit.AnnotatedCommit[] { ac };
+                       
+                       this.repo.merge(commits, mo, co);
+                       
+                       var cfg = this.repo.get_config().snapshot();
+                       
+                   var sig = new Ggit.Signature.now(
+                                       cfg.get_string("user.name"),
+                                       cfg.get_string("user.email")
+                       );
+                       var new_head = this.repo.get_head();
+                       var oid = new_head.get_target();
+
+                       var ix = this.repo.get_index();
+                       ix.write();
+                       var treeoid = ix.write_tree();
+
+                       var new_tree = this.repo.lookup(treeoid,typeof (Ggit.Tree))  as   Ggit.Tree;
+                       
+                       var parent = new_head.lookup() as Ggit.Commit;
+                       Ggit.Commit[] parents =  new Ggit.Commit[] { parent };
+                       
+                       this.repo.create_commit("refs/heads/" + this.head.get_name(), sig, sig, null, "Test Merge", new_tree, parents);
+        
+               }
+               
+               
+
+               
+               
+               /*
+               public bool doMergeClose(string commit_message)
+               {
+                       this.loadLocalBranches(true);
+                       var oldbranch = this.head.get_name();
+            // going to asume this is merge trees..
+                          string [] cmd = { "merge",   "--squash",  oldbranch };
+                          this.git( cmd );
+                          cmd = { "commit",   "-a" , "-m",  commit_message };
+                          this.git( cmd );
+                          this.push();
+                          this.loadBranches(); // updates lastrev..
+               
+                      var notification = new Notify.Notification(
+                               "Merged branch %s to %s".printf(oldbranch, master),
+                               "",
+                                "dialog-information"
+                               
+                       );
+
+                       notification.set_timeout(5);
+                       notification.show();   
+               
+               
+               }
+               */
+               
+               
+               public bool is_auto_branch ()
+               {
+                       if (this.name == "gitlog") {
+                               return false;
+                       }
+                       // check remote...
+                       if (this.is_managed()) {
+                               return true;
+                       }
+                       return false;
+                       
+        
+               }
+               
+               public async void loadRemoteHeads(bool force = false)
+               {
+                   SourceFunc callback = loadRemoteHeads.callback;
+                       
+                       ThreadFunc<bool> run = () => {
+                               
+                               if (!force && this.remote_heads != null) {
+                                       return true;;
+                               }
+                               var r = this.repo.lookup_remote("origin");
+                               r.connect(Ggit.Direction.FETCH, this.callbacks, null, null);
+                               yield;
+                               this.remote_heads = r.list();
+                               
+                               foreach(var br in this.remote_heads) {
+                                       if (!br.get_name().has_prefix("refs/heads/")) {
+                                               continue;
+                                       }
+                                       
+                                       GLib.debug("Remote: name=%s  oid=%s local_oid=%s is_local=%s",
+                                               br.get_name(),
+                                               br.get_oid().to_string(),
+                                               br.get_local_oid().to_string(),
+                                               br.is_local() ? "Y" : "n"
+                                               );
+                               }
+                               Idle.add((owned) callback);
+                               return true;;
+                       };
+                       new Thread<bool>("loadRemoteHeads-" , run);
+                       yield;
+                       
+
+               }
+                
+               
+               Ggit.Branch? getBranch(string remote_name, string remote_branch_name)
+               {
+                        //GLib.debug("bn=%s",remote_branch_name);
+                        if (remote_branch_name.has_prefix("refs/remotes/")) {
+                                return null;
+                        }
+
+                        var target = remote_branch_name.replace("refs/heads/", remote_name+"/") .replace("refs/remotes/", "");
+                       if (target == "HEAD") {
+                               target = remote_name +"/master";
+                       }
+                        
+                       foreach(var br in this.branches) {
+                       //      GLib.debug("test:%s=%s", br.get_upstream().get_shorthand() , target);
+                               if ( br.get_upstream().get_shorthand() == target) {
+                                       return br;
+                               }
+                               
+                       }
+                       //GLib.debug("missing %s", remote_branch_name);                 
+                       return null;
+               
+               }
+                
+               
+               public void fetchAll()
+               {
+                       this.loadLocalBranches();
+                       this.loadRemoteHeads();
+                       
+                       // remotes probably will not work with http auth..
+                       //var ar = this.repo.list_remotes();
+                       //foreach(var n in ar) {
+                       var n = "origin"; 
+                       
+                               GLib.debug("got remote '%s'", n);
+                               var r = this.repo.lookup_remote(n);
+                               GLib.debug("connecting '%s'", r.get_url());
+                                
+                               try {
+                                       string[] h = { "a = 1" };
+                                       r.connect(Ggit.Direction.FETCH, this.callbacks, null, null);
+                                       
+                               } catch (Error e) {
+                                       GLib.debug("Got Error Message: %s", e.message);
+                                       return;
+                               }
+                               string[] far = {};
+
+                               foreach(var rh in this.remote_heads) {
+                                       if (rh.get_name().has_prefix("refs/remotes/")) {
+                                                  continue;
+                                        }
+                               
+                                       var br = this.getBranch(n, rh.get_name());
+                                
+                                       /*GLib.debug("got heads: name=%s   rev=%s  localrev=%s",
+                                               rh.get_name(), 
+                                               rh.get_oid().to_string(),
+                                               br == null ? "?": this.repo.revparse(br.get_name() ).get_id().to_string()
+                                       );
+                                       */
+                                       //var loc_oid = this.repo.revparse(br.get_name() ).get_id();
+                                       
+                                       var loc_oid = br.get_target();
+                                       
+                                       size_t ahead, behind;
+                                       this.repo.get_ahead_behind(
+                                               loc_oid,
+                                               rh.get_oid(),
+                                               out ahead,
+                                               out behind
+                                       );
+                                       
+                                       if (rh.get_oid().to_string() == this.repo.revparse(br.get_name() ).get_id().to_string()) {
+                                               continue;
+                                       }
+                                       if (ahead > 0) {
+                                               continue;
+                                       }
+                                       far += ("+refs/heads/" + br.get_name()) + ":refs/remotes/" + n + "/" + rh.get_name().replace("refs/heads/","");
+                               } 
+                               
+                               if (far.length < 1) {
+                                       GLib.debug("no fetch required.. it's uptodate");
+                                       r.disconnect();
+                                       return;
+                               }
+                               
+                               GLib.debug("getting remote specs '%s', %d", n, far.length);
+                               
+/*
+                               var far = r.get_fetch_specs();
+                               */
+                               foreach(var rs in far) {
+                                       GLib.debug("got remote spec: %s", rs);
+                                       
+                               }
+
+                               var options = new Ggit.FetchOptions();
+                               options.set_remote_callbacks(this.callbacks);
+                               //yield Async.thread(() => {
+       
+                                       r.download(far, options);
+                               //});
+                               r.disconnect();
+                               
+                               //r.download(
+                        
+               
+               }
+               
+               
+               
+               public void pushAll()
+               {
+                       
+                       this.loadLocalBranches();
+                       this.loadRemoteHeads();
+                       // remotes probably will not work with http auth..
+                       //var ar = this.repo.list_remotes();
+                       var n = "origin";
+                       
+                               GLib.debug("got remote '%s'", n);
+                               var r = this.repo.lookup_remote(n);
+                               GLib.debug("connecting '%s'", r.get_url());
+                                
+                               r.connect(Ggit.Direction.PUSH, this.callbacks, null, null);
+                               
+                               //GLib.debug("getting specs '%s'", n);
+                               /* 
+                               
+                               this.repo.add_remote_push(
+                                       "origin",
+                                       "+%s:%s".printf(head.get_shorthand(),head.get_name())
+                               );
+ */
+                               string[] far = {};
+                               var heads = r.list();
+                               foreach(var rh in heads) {
+                                       if (rh.get_name().has_prefix("refs/remotes/")) {
+                                                  continue;
+                                        }
+                               
+                                       var br = this.getBranch(n, rh.get_name());
+                                       /*
+                                       GLib.debug("got heads: name=%s   rev=%s  localrev=%s",
+                                               rh.get_name(), 
+                                               rh.get_oid().to_string(),
+                                               br == null ? "?": this.repo.revparse(br.get_name() ).get_id().to_string()
+                                       );*/
+                                       var loc_oid = this.repo.revparse(br.get_name() ).get_id();
+                                       size_t ahead, behind;
+                                       this.repo.get_ahead_behind(
+                                               loc_oid,
+                                               rh.get_oid(),
+                                               out ahead,
+                                               out behind
+                                       );
+                                       
+                                       if (rh.get_oid().to_string() == this.repo.revparse(br.get_name() ).get_id().to_string()) {
+                                               continue;
+                                       }
+                                       if (behind > 0) {
+                                               continue;
+                                       }
+                                       far += ("+refs/heads/" + br.get_name()) + ":"+ rh.get_name();
+                               }  
+                               
+                               if (far.length < 1) {
+                                       GLib.debug("no push required.. it's uptodate");
+                                       r.disconnect();
+                                       return;
+                               }
+                               /*var head = this.repo.get_head();
+                               string[] far = {};
+                               far += "+%s:%s".printf(head.get_name(),head.get_name());
+                               */
+                               foreach(var rs in far) {
+                                       GLib.debug("got remote spec: %s", rs);
+                                       
+                               }
+                                       
+                               var popts = new Ggit.PushOptions();
+                                popts.callbacks = this.callbacks;
+                               GLib.debug("Push?");
+                               r.upload(far,popts);
+                               GLib.debug("Push done?");
+                               r.disconnect();
+                               
+                               
+                               //r.download(
+                        
+               
+               }
+               
+                
+
+       }
+       
+       private class Callbacks : Ggit.RemoteCallbacks
+       {
+               //private Remote d_remote;
+               private Ggit.RemoteCallbacks? d_proxy = null;
+
+               public delegate void TransferProgress(Ggit.TransferProgress stats);
+               //private TransferProgress? d_transfer_progress;
+
+               public Callbacks( Repo repo)  //, Ggit.RemoteCallbacks? proxy) //,Remote remote, owned TransferProgress? transfer_progress)
+               {
+                       //d_remote = remote;
+                       //d_proxy = proxy;
+                       //d_transfer_progress = (owned)transfer_progress;
+               }
+
+               protected override void progress(string message)
+               {
+                       GLib.debug("progress: %s", message);
+                       if (d_proxy != null)
+                       {
+                               d_proxy.progress(message);
+                       }
+               }
+
+               protected override void transfer_progress(Ggit.TransferProgress stats)
+               {
+                       GLib.debug("transfer_progress");
+                       /*
+                       if (d_transfer_progress != null)
+                       {
+                               d_transfer_progress(stats);
+                       }
+
+                       if (d_proxy != null)
+                       {
+                               d_proxy.transfer_progress(stats);
+                       }
+                       */
+               }
+
+               protected override void update_tips(string refname, Ggit.OId a, Ggit.OId b)
+               {
+                       GLib.debug("update_tips");
+                       //d_remote.tip_updated(refname, a, b);
+
+                       if (d_proxy != null)
+                       {
+                               d_proxy.update_tips(refname, a, b);
+                       }
+               }
+
+               protected override void completion(Ggit.RemoteCompletionType type)
+               {
+                       GLib.debug("completion");
+                       if (d_proxy != null)
+                       {
+                               d_proxy.completion(type);
+                       }
+               }
+
+               protected override Ggit.Cred? credentials(string url, string? username_from_url, Ggit.Credtype allowed_types) throws Error
+               {
+                       GLib.debug("get credentials %s  UN=%s", url, username_from_url);
+                       var uri = new Soup.URI(url);
+
+                       if (uri != null) {
+                               var ret = this.netrc(uri.get_host());
+                               if (ret != null) {
+                                       return ret;
+                               }
+                               
+                               //return new Ggit.CredPlaintext(username_from_url, "test");
+                       }
+                       return null;
+                       /*var provider = d_remote.credentials_provider;
+
+                       if (provider != null)
+                       {
+                               ret = provider.credentials(url, username_from_url, allowed_types);
+                       }
+
+                       if (ret == null && d_proxy != null)
+                       {
+                               ret = d_proxy.credentials(url, username_from_url, allowed_types);
+                       }
+                       
+                       return ret;
+                       */
+               }
+               public  Ggit.Cred netrc(string domain) 
+               {
+                       string str;
+                       GLib.FileUtils.get_contents(GLib.Environment.get_home_dir() + "/.netrc", out str);
+                       var lines = str.split("\n");
+                       for(var i=0; i< lines.length; i++) {
+                               // assumes one line per entry.. if not we are buggered...
+                               //GLib.debug("got %s" , lines[i]);
+                       
+                               var bits =  Regex.split_simple ("[ \t]+", lines[i].strip());
+                               if (bits.length < 6 || bits[0] != "machine" || bits[1] != domain) {
+                                       continue;
+                               }
+                               GLib.debug("found password?");
+                               // we are gussing.... 
+                               return new Ggit.CredPlaintext(bits[3], bits[5]);
+
+                       }
+                       return null;
+
+
+               
+               
+               }
+               
+       }
+       
+       
+
+}
\ No newline at end of file
diff --git a/Git2.vala b/Git2.vala
new file mode 100644 (file)
index 0000000..cc14629
--- /dev/null
+++ b/Git2.vala
@@ -0,0 +1,61 @@
+
+
+void main()
+{
+        GLib.Log.set_handler(null, 
+            GLib.LogLevelFlags.LEVEL_DEBUG | GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_INFO, 
+            (dom, lvl, msg) => {
+                                       
+                                       
+               // should we debug..
+                                       
+                       
+               print("%s\n", msg);
+            }
+         ); 
+
+       Git.Threads.init();
+       var a = new GitLive.Repo("/home/alan/gitlive/web.Texon");
+       a.fetchAll();
+}
+namespace  GitLive {
+
+       public class Repo : Object 
+       {
+               Git.Repository repo;
+               
+               public Repo (string path)
+               {
+                       Git.Repository.open(out this.repo , path);
+               }
+               
+               public void push()
+               {
+               string_array remotes;
+               this.repo.get_remote_list(out remotes);
+               
+               foreach(var rem in remotes.strings) {
+                       Git.Remote remote;
+                       this.repo.get_remote(out remote, rem_name);
+               
+               
+        // get the remote.
+     git_remote* remote = NULL;
+     git_remote_lookup( &remote, repository, "origin" );
+
+     // connect to remote
+     git_remote_connect( remote, GIT_DIRECTION_PUSH )
+
+     // add a push refspec
+     git_remote_add_push( remote, "refs/heads/master:refs/heads/master" );
+
+     // configure options
+     git_push_options options;
+     git_push_init_options( &options, GIT_PUSH_OPTIONS_VERSION );
+
+     // do the push
+     git_remote_upload( remote, NULL, &options );
+
+     git_remote_free( remote );
+     return true; 
+ }
\ No newline at end of file
index 18aa32c..6a2dfa1 100644 (file)
@@ -31,11 +31,15 @@ public class GitBranch : Object
        
        public bool active = false;
        public string lastrev = "";
-       public string name = "";
+       public string name = ""; // human friendly name...
        public bool is_remote;
        public string remote = "";
        public string remoterev = "";
        public string age = "";
+    public int ahead = 0;
+    public int behind = 0;    
+       
+     
        
        public string toString()
        {
@@ -54,15 +58,132 @@ public class GitBranch : Object
        {
                this.repo = repo;
        }
+       
+       public Ggit.Tree getTree()
+       {
+               var br = this.repo.repo.lookup_branch(this.name,Ggit.BranchType.LOCAL);
+               return this.repo.repo.lookup_commit(br.get_target()).get_tree();
+       }
+       
 
        public static  void loadBranches(GitRepo repo)
        {
                repo.branches = new Gee.HashMap<string,GitBranch>();
        
-       var branches =  new Gee.HashMap<string,GitBranch>();
-               var local =  new Gee.HashMap<string,GitBranch>();
-               var remotes  =  new Gee.HashMap<string,GitBranch>();
-               
+       //var branches =  new Gee.HashMap<string,GitBranch>();
+               //var local =  new Gee.HashMap<string,GitBranch>();
+               var remotes  =  new Gee.HashMap<string,Ggit.OId>();
+               var remotes_used  =  new Gee.HashMap<string,bool>();
+                
+  
+               
+               var rem = repo.repo.lookup_remote("origin");
+               var cb = new GitCallbacks(repo);
+               rem.connect(Ggit.Direction.FETCH, cb, null, null);
+               var remote_heads = rem.list();
+               foreach(var rh in remote_heads) {
+                       var rn = rh.get_name();
+                       if (!rn.has_prefix("refs/heads/")) {
+                               continue;
+                       }
+                       remotes.set(rn.substring(11), rh.get_oid());
+                       remotes_used.set(rn.substring(11), false);
+
+         } 
+               
+                
+               var r = repo.repo.enumerate_branches(Ggit.BranchType.LOCAL);
+               while (r.next()) {
+               
+
+               
+                       var br = new GitBranch(repo);
+                       var gbr = r.get() as Ggit.Branch;
+                       if (!gbr.is_branch()) {
+                               continue;
+                       }
+                       
+                       br.active = gbr.is_head();
+                       br.name = gbr.get_name();
+                       br.lastrev = gbr.get_target().to_string();
+                       string rname ;
+                       try {
+                               rname = gbr.get_upstream() != null ? gbr.get_upstream().get_name() : "";
+                       } catch(Error e) {
+                               GLib.debug("Skip branch = got error");
+                               continue;
+                       }
+                       repo.branches.set(gbr.get_name(), br);                  
+                       if (rname.has_prefix("refs/remotes/origin/")) {
+                               rname = rname.substring(20);
+                               if (remotes.has_key(rname)) {
+                                       br.remote = rname;
+                                       br.remoterev = remotes.get(rname).to_string();
+                                       remotes_used.set(rname,true);
+                                       size_t ahead, behind;
+                                       br.behind = 1;
+                                       
+                                       try {
+                                               repo.repo.get_ahead_behind(
+                                                       gbr.get_target(),
+                                                       remotes.get(rname),
+                                                       out ahead,
+                                                       out behind
+                                               );
+                                               br.ahead = (int)ahead;
+                                               br.behind = (int) behind;
+
+                                       } catch(Error e) {
+                                               GLib.debug("we probably need to fetch... %s", repo.name);
+                                       }
+                                       
+                               }
+                                
+                               
+                               // age?
+                               // behind or infront..
+                       }
+                       if (br.active) {
+                               GLib.debug("repo: %s currentBranch = %s", repo.name, br.name);
+                               repo._currentBranch = br;
+                       }
+                       
+               }
+               
+               // find unused remotes.. and track them...
+               foreach(var rn in remotes_used.keys) {
+                       if (remotes_used.get(rn)) {
+                               continue;
+                       }
+                       if (repo.branches.has_key(rn)) {
+                               GLib.debug("skip tracking branch - same name exists?");
+                               continue;
+                       }
+                       // not clear how to do this yet...
+                       try {
+                               repo.git(  { "branch" ,"--track" , rn,  "origin/" + rn} ); 
+                       } catch (Error e) {
+                               continue; // allow failure?
+                       }
+                       var br = new GitBranch(repo);
+                       br.name = rn;
+                       br.lastrev = ""; // it's behind
+                       br.remoterev  =  remotes.get(rn).to_string();
+                       br.remote = rn;
+                       br.ahead = 0;
+                       br.behind = 1;
+                       // behind/ahead == 0...
+                       repo.branches.set(rn, br);
+                       
+               }
+
+               if (repo._currentBranch == null) {
+                       GLib.error("could not find active Branch for %s", repo.name);
+               }
+               
+                        
+               
+               /*
       //        repo.git( { "fetch",  "-a" } ); == done async before...
                
        string[] cmd = { "branch",   "--no-color", "--verbose", "--no-abbrev" , "-a"  };
@@ -133,7 +254,7 @@ public class GitBranch : Object
                br.name  = newname;
                local.set(br.name, br);
         }
-        
+        */
         /*
         this bit of the code tries to turn a local branch into a track of a remote one.
         -- that's probably not a good idea.
@@ -148,9 +269,9 @@ public class GitBranch : Object
                name = name.replace("/", ".");
                
         }
-        */
+       
         repo.branches = local;
-        
+         */
     
        
        }
@@ -182,10 +303,7 @@ public class GitBranch : Object
                return this.is_remote ? this.remote : this.name;
        }
        
-       public void create()
-       {
-       
-       }
+//     public void create() { }
        
 }
        
diff --git a/GitCallbacks.vala b/GitCallbacks.vala
new file mode 100644 (file)
index 0000000..55de1b2
--- /dev/null
@@ -0,0 +1,116 @@
+public class GitCallbacks : Ggit.RemoteCallbacks
+{
+       //private Remote d_remote;
+       private Ggit.RemoteCallbacks? d_proxy = null;
+
+       public delegate void TransferProgress(Ggit.TransferProgress stats);
+       //private TransferProgress? d_transfer_progress;
+
+       public GitCallbacks( GitRepo repo)  //, Ggit.RemoteCallbacks? proxy) //,Remote remote, owned TransferProgress? transfer_progress)
+       {
+               //d_remote = remote;
+               //d_proxy = proxy;
+               //d_transfer_progress = (owned)transfer_progress;
+       }
+
+       protected override void progress(string message)
+       {
+               GLib.debug("progress: %s", message);
+               if (d_proxy != null)
+               {
+                       d_proxy.progress(message);
+               }
+       }
+
+       protected override void transfer_progress(Ggit.TransferProgress stats)
+       {
+               GLib.debug("transfer_progress");
+               /*
+               if (d_transfer_progress != null)
+               {
+                       d_transfer_progress(stats);
+               }
+
+               if (d_proxy != null)
+               {
+                       d_proxy.transfer_progress(stats);
+               }
+               */
+       }
+
+       protected override void update_tips(string refname, Ggit.OId a, Ggit.OId b)
+       {
+               GLib.debug("update_tips");
+               //d_remote.tip_updated(refname, a, b);
+
+               if (d_proxy != null)
+               {
+                       d_proxy.update_tips(refname, a, b);
+               }
+       }
+
+       protected override void completion(Ggit.RemoteCompletionType type)
+       {
+               GLib.debug("completion");
+               if (d_proxy != null)
+               {
+                       d_proxy.completion(type);
+               }
+       }
+
+       protected override Ggit.Cred? credentials(string url, string? username_from_url, Ggit.Credtype allowed_types) throws Error
+       {
+
+               GLib.debug("get credentials %s  UN=%s", url, username_from_url);
+               var uri = new Soup.URI(url);
+
+               if (uri != null) {
+                       var ret = this.netrc(uri.get_host());
+                       if (ret != null) {
+                               return ret;
+                       }
+                       
+                       //return new Ggit.CredPlaintext(username_from_url, "test");
+               }
+               return null;
+               /*var provider = d_remote.credentials_provider;
+
+               if (provider != null)
+               {
+                       ret = provider.credentials(url, username_from_url, allowed_types);
+               }
+
+               if (ret == null && d_proxy != null)
+               {
+                       ret = d_proxy.credentials(url, username_from_url, allowed_types);
+               }
+               
+               return ret;
+               */
+       }
+       public  Ggit.Cred netrc(string domain) 
+       {
+               string str;
+               GLib.FileUtils.get_contents(GLib.Environment.get_home_dir() + "/.netrc", out str);
+               var lines = str.split("\n");
+               for(var i=0; i< lines.length; i++) {
+                       // assumes one line per entry.. if not we are buggered...
+                       //GLib.debug("got %s" , lines[i]);
+               
+                       var bits =  Regex.split_simple ("[ \t]+", lines[i].strip());
+                       if (bits.length < 6 || bits[0] != "machine" || bits[1] != domain) {
+                               continue;
+                       }
+                       GLib.debug("found password?");
+                       // we are gussing.... 
+                       return new Ggit.CredPlaintext(bits[3], bits[5]);
+
+               }
+               return null;
+
+
+       
+       
+       }
+       
+}
\ No newline at end of file
index 1b11558..4c79f5e 100644 (file)
@@ -171,24 +171,8 @@ public class GitMonitor : Monitor
 
                                this.monitor(this.top.index(i) );
                        }
-                       StatusIconA.statusicon.resume();
-                   this.paused = false;
-                  
                        
-                       try {
-
-                         
-                               var notification = new Notify.Notification(
-                                       "Git Live",
-                                       "%s\nMonitoring %u Directories".printf(GitMonitor.gitlive, this.monitors.length), 
-                                        "dialog-information"
-                               );
-               
-                               notification.set_timeout(5);
-                               notification.show();
-                       } catch(Error e) {
-                               GLib.debug("Error sending notification to screen: %s",e.message);
-                       }
+                       
                        return false; // do not keep doing this..
 
                });
@@ -197,7 +181,29 @@ public class GitMonitor : Monitor
                
                 
        }
+       int scanning = 0;
+       int scancomplete = 0;
+       public void updateMonitorsComplete()
+       {
+               StatusIconA.statusicon.resume();
+           this.paused = false;
+          
+               
+               try {
 
+                 
+                       var notification = new Notify.Notification(
+                               "Git Live",
+                               "%s\nMonitoring %u Directories".printf(GitMonitor.gitlive, this.monitors.length), 
+                                "dialog-information"
+                       );
+       
+                       notification.set_timeout(5);
+                       notification.show();
+               } catch(Error e) {
+                       GLib.debug("Error sending notification to screen: %s",e.message);
+               }
+       }
 
        public new void stop() {
                StatusIconA.statusicon.pause();
@@ -205,12 +211,18 @@ public class GitMonitor : Monitor
        }
        
        
+       // this is called recursively until we end..
+       
        public override void monitor (string path,  int depth = 0)
        {
                
                //GLib.debug("GitMonitor : monitor %d %s", depth, path);
                //var depth = typeof(depth) == 'number'  ? depth *1 : 0;
                
+               if (depth == 0) {
+                       this.scancomplete = 0;  
+                       this.scanning = 0;      
+               }
                 
                // if we are not at top level.. and there is a .git directory  (it's a submodule .. ignore) 
                if (depth > 1 && FileUtils.test(path + "/.git" , FileTest.IS_DIR)) {
@@ -222,9 +234,17 @@ public class GitMonitor : Monitor
                        if (!FileUtils.test(path + "/.git" , FileTest.IS_DIR)) {
                                return; // skip non-git directories..
                        }
-               
-                       GitRepo.get(path);
-               
+                       this.scanning++;
+                       GitRepo.get.begin(path, (ojb,res) => {
+                               
+                               GitRepo.get.end(res);
+                               base.monitor(path, depth);
+                               this.scanning--;
+                               if (this.scanning == 0 && this.scancomplete == 1) {
+                                       this.updateMonitorsComplete();
+                               }
+                       });
+                       return;
                        // FIXME - check if repo is flagged as not autocommit..
                        //var repo = imports.Scm.Repo.Repo.get(path);
                        //if (!repo || !repo.autocommit()) {
@@ -238,6 +258,11 @@ public class GitMonitor : Monitor
                
                
                base.monitor(path, depth);
+               if (depth == 0) {
+                       this.scancomplete = 1;          
+               }
+               
+               
        }
 
        
@@ -306,7 +331,7 @@ public class GitMonitor : Monitor
                
                        var gitpath = cmd.gitpath; 
                        
-                       var repo = GitRepo.get( gitpath );
+                       var repo = GitRepo.get_sync( gitpath );
                        if ( repo.is_master_branch() && repo.is_auto_branch()) {
                                leave_queued.add(cmd);
                                continue;
@@ -316,7 +341,7 @@ public class GitMonitor : Monitor
                
                        var ix  = GitRepo.indexOf(repo_list,   gitpath);
                        if (ix < 0) {
-                               repo_list.append_val( GitRepo.get( gitpath ));
+                               repo_list.append_val( GitRepo.get_sync( gitpath ));
                                ix = GitRepo.indexOf(repo_list,  cmd.gitpath);
                        }
                        GLib.debug("GitMonitor.runQueue - adding to repolist %d", ix);
index 00ab465..ff3bd28 100644 (file)
@@ -41,7 +41,7 @@ public class GitMonitorQueue : MonitorNamePathDir {
 
                        this.vname =  this.vdir + (this.vdir.length > 0 ? "/" : "") + this.name;
                        
-                       this.repo = GitRepo.get(this.gitpath);
+                       this.repo = GitRepo.get_sync(this.gitpath);
                        
                        // trigger the suggestion to start a new branch
                        
index d1ee645..9cb29f6 100644 (file)
@@ -25,13 +25,26 @@ public class GitRepo : Object
     public string ahead_or_behind = "";
     
     public Gee.HashMap<string,bool> ignore_files;
-    public GitBranch currentBranch;
+     
+    public GitBranch  _currentBranch;
+    public GitBranch  getCurrentBranch() {
+       if (this._currentBranch == null) {
+               this.loadBranches();
+       }
+       if (this._currentBranch == null) {      
+               GLib.error("could not work out current branch?");
+               }
+               return this._currentBranch;
+    }
+    
+    
     public Gee.HashMap<string,GitBranch> branches; // accessed in GitBranch..
        public RooTicket? activeTicket;
-    public  Gee.HashMap<string,GitRepo> cache;
-    public  Gee.HashMap<string,string> config_cache;
-    
+    public Gee.HashMap<string,GitRepo> cache;
+    public Gee.HashMap<string,string> config_cache;
     
+    public Ggit.Repository repo;
+    public Ggit.RemoteHead[]                           remote_heads = null;
     
        public static GitRepo singleton()
     {
@@ -47,7 +60,7 @@ public class GitRepo : Object
     */
     public static int indexOf( Array<GitRepo> repos, string gitpath) {
         // make a fake object to compare against..
-        var test_repo = GitRepo.get(gitpath);
+        var test_repo = GitRepo.get_sync(gitpath);
         
         for(var i =0; i < repos.length; i++) {
             if (repos.index(i).gitdir == test_repo.gitdir) {
@@ -127,7 +140,7 @@ public class GitRepo : Object
                 continue;
             }
             
-               var rep =  GitRepo.get(  sp );
+               var rep =  GitRepo.get_sync(  sp );
                list_cache.append_val(rep);             
             
         }
@@ -136,13 +149,39 @@ public class GitRepo : Object
          
        }
        
-       public static GitRepo get(string path) 
+       public  static GitRepo get_sync(string path) 
        {
+               GitRepo ret;
                var cache = GitRepo.singleton().cache;
                if (cache.has_key(path)) {
-                       return cache.get(path);
+                       ret =  cache.get(path);
+               } else {
+                       ret =  new GitRepo(path);
                }
-               return new GitRepo(path);
+               return ret;
+       }
+        
+       public static  async  GitRepo? get(string path) 
+       {
+               
+               SourceFunc callback = GitRepo.get.callback;
+               GitRepo ret = null;
+               ThreadFunc<bool> run = () => {
+                       
+                       var cache = GitRepo.singleton().cache;
+                       if (cache.has_key(path)) {
+                               ret =  cache.get(path);
+                       } else {
+                               ret =  new GitRepo(path);
+                       }
+                       Idle.add((owned) callback);
+               return true;
+                       
+               };
+               new Thread<bool>("thread-new-gitrepo-" + path, run);
+               yield;
+               return ret;
+               
        }
        
     private GitRepo.single() {
@@ -175,8 +214,13 @@ public class GitRepo : Object
                        cache.set( path, this);
        }
        
-       var r = this.git({ "remote" , "get-url" , "--push" , "origin"});
-       var uri = new Soup.URI(r);      
+       this.repo =  Ggit.Repository.open(GLib.File.new_for_path(path));
+       
+       var r = this.repo.lookup_remote("origin");
+       
+       
+       //var r = this.git({ "remote" , "get-url" , "--push" , "origin"});
+       var uri = new Soup.URI(r.get_url());            
        this.host = uri.get_host();
                this.init_config();
        
@@ -188,7 +232,7 @@ public class GitRepo : Object
     public bool is_master_branch()
     {
        // special branches that do not allow autopushing now...
-       return this.currentBranch.name == "master" || this.currentBranch.name == "roojs";
+       return this.getCurrentBranch().name == "master" || this.getCurrentBranch().name == "roojs";
                
     }
     public void init_config()
@@ -209,27 +253,30 @@ public class GitRepo : Object
     
     
     
-    public string get_config(string key) {
+    public string get_config(string key) 
+    {
     
        if (this.config_cache.has_key(key)) {
                //GLib.debug("get_config %s = '%s'", key, this.config_cache.get(key));
                return this.config_cache.get(key);
                }
        try {
-               var ret =   this.git({ "config" , "gitlive." + key }).strip();
-               this.config_cache.set(key, ret);
-               //GLib.debug("get_config %s = '%s'", key, ret);
+               var cfg = this.repo.get_config().snapshot();
+               var ret = cfg.get_string("gitlive." + key).strip();
                return ret;
        } catch (Error e) {
-               this.config_cache.set(key, "");
+               this.repo.get_config().set_string("gitlive." + key, "");
+               //this.config_cache.set(key, "");
                //GLib.debug("get_config (fail) %s = '%s'", key, "");
                return ""; // happens when there is nothing set...
        }
 
        }
-    public void set_config(string key, string value) {
-       this.git({ "config" , "gitlive." + key, value });
-       this.config_cache.set(key,value);
+    public void set_config(string key, string value) 
+    {
+       this.repo.get_config().set_string("gitlive." + key, value);
+       //this.git({ "config" , "gitlive." + key, value });
+       //this.config_cache.set(key,value);
        }
     
     public bool is_managed()
@@ -283,16 +330,18 @@ public class GitRepo : Object
     
        public void loadStatus()
        {
+               // status??/ 
                var r = this.git({ "status" , "--porcelain" });
                this.git_status = r;
                this.has_local_changes = r.length > 0;
                
-               var rs = this.git({ "status" , "-sb" });
-
-               this.ahead_or_behind = rs.contains("[ahead") ? "A" : (rs.contains("[behind") ? "B" : "");
+               //var rs = this.git({ "status" , "-sb" });
+               var cb = this.getCurrentBranch();
+                 
+               this.ahead_or_behind = cb.ahead > 0 ?  "A" : (cb.behind > 0  ? "B" : "");
                
                
-               this.git_diff  = this.git({ "diff" , "HEAD", "--no-color" });
+               this.git_diff  = this.diffWorking();
        }    
 
     
@@ -343,7 +392,7 @@ public class GitRepo : Object
                                continue;
                        }
                        commitrevs += commitrevs.length > 0 ? " " : "";
-                       commitrevs += repo.currentBranch.lastrev;
+                       commitrevs += repo.getCurrentBranch().lastrev;
                }
        }
        if (sucess && action == "CLOSE") {
@@ -363,7 +412,7 @@ public class GitRepo : Object
                   if (action == "CLOSE" || action == "LEAVE") {
                                   
                try {
-                   var oldbranch = this.currentBranch.name;
+                   var oldbranch = this.getCurrentBranch().name;
                    this.setActiveTicket(null, master);
                           string [] cmd = { "merge",   "--squash",  oldbranch };
                           this.git( cmd );
@@ -399,7 +448,7 @@ public class GitRepo : Object
                        string[] cmd = { "merge", master};
                        this.git( cmd );
                        var notification = new Notify.Notification(
-                                       "Merged code from %s to %s".printf(master,this.currentBranch.name),
+                                       "Merged code from %s to %s".printf(master,this.getCurrentBranch().name),
                                        "",
                                         "dialog-information"
                                        
@@ -415,7 +464,7 @@ public class GitRepo : Object
            }
        if (action == "EXIT") {
                        try {
-                       var oldbranch  = this.currentBranch.name;
+                       var oldbranch  = this.getCurrentBranch().name;
                          this.setActiveTicket(null, master);
                        this.loadBranches();
                        var notification = new Notify.Notification(
@@ -634,11 +683,32 @@ public class GitRepo : Object
                        GitMonitor.gitmonitor.pauseError(ee.message);
                        return "Error getting diff";            
                }
-        
-     
+         
      }
     
     
+    public string diffWorking()
+    {
+       var cb = this.getCurrentBranch();
+       GLib.debug("Calling diff working");
+       var diff = new Ggit.Diff.tree_to_workdir(this.repo, cb.getTree(), new Ggit.DiffOptions());
+       var ret = "";
+       diff.print(Ggit.DiffFormatType.PATCH, (delta, hunk, line) => {
+               switch(line.get_origin()) {
+                       case Ggit.DiffLineType.ADDITION: ret+="+"; break;
+                               case Ggit.DiffLineType.DELETION: ret+="-";break;
+                               case Ggit.DiffLineType.CONTEXT:  ret+=" ";break;
+                               case Ggit.DiffLineType.HUNK_HDR: break;                                 
+                               case Ggit.DiffLineType.FILE_HDR: break;
+                               default: ret+=" ";break;
+                       }
+               ret += " " + line.get_text() ;
+               return 0;
+       });
+       //GLib.debug("returning %s", ret);
+       return ret;
+    }    
+    
     
     /**
      * add:
@@ -916,7 +986,88 @@ public class GitRepo : Object
     
     }
     
+    
+    public async void doUpdate()
+    {
+       SourceFunc callback = this.doUpdate.callback;
+               GitRepo ret = null;
+               ThreadFunc<bool> run = () => {
+                       
+                       
+               // update the branches..
+                       this.loadBranches();
+
+                       //GLib.debug("connecting '%s'", r.get_url());
+                       string[] far = {};
+                       foreach(var br in this.branches.values) {
+                               if (br.remote == "" || br.remoterev == br.lastrev) {
+                                       continue;
+                               }
+                               far +=  ("+refs/heads/" + br.name + ":refs/remotes/" + br.remote);
+                       }
+                       if (far.length > 0) {
+                               GLib.debug("PUlling %s", this.name);
+                               var r = this.repo.lookup_remote("origin");
+                               r.connect(Ggit.Direction.FETCH, new GitCallbacks(this), null, null);
+                               var options = new Ggit.FetchOptions();
+                               options.set_remote_callbacks( new GitCallbacks(this));
+                               r.download(far, options);
+                       }
+                       this.loadStatus();
+                        
+               
+                       Idle.add((owned) callback);
+               return true;
+                       
+               };
+               new Thread<bool>("thread-new-gitpull-" + this.name, run);
+               yield;
+                  
+       
+    }
+    
+       
+       public static void updateAllAsync(string after)
+       {
  
+               
+               var doing = new  Gee.HashMap<string,bool>();;
+               
+               var tr =  GitRepo.singleton().cache;
+        
+       var update_all_total = tr.size;
+       foreach(var repo  in tr.values) {
+               if (!repo.is_managed()) {
+                       update_all_total--;                     
+                               continue;
+                       }
+                       doing.set(repo.name, true);
+                       repo.doUpdate.begin((obj, res) => {
+                               repo.doUpdate.end(res);
+                               doing.set(repo.name, false);
+                                
+                               foreach(var b in doing.keys) {
+                                       if (doing.get(b)) {
+                                               GLib.debug("pending: %s", b);
+                                               return;
+                                       }
+                               }
+                       
+                               
+                               switch (after) {
+                                       case "show_clones":
+                                               Clones.singleton().show();
+                                               break;
+                                       default:
+                                               GLib.debug("Unkown call after load = %s", update_all_after);            
+                                               break;
+                               }
+                       });
+               }
+
+       
+       }
+       
         
     
  
@@ -947,6 +1098,9 @@ public class GitRepo : Object
         } 
                GLib.debug("calls total = %d", (int) update_all_total);
     }
+    
+    
+    
     public static void  updateAllCallback(GitRepo repo, int err, string res)
     {
        repo.loadBranches();
@@ -971,6 +1125,17 @@ public class GitRepo : Object
                return;
     }
     
-    
+    public void loadRemoteHeads(bool force = false)
+       {
+               
+               if (!force && this.remote_heads != null) {
+                       return;
+               }
+               var r = this.repo.lookup_remote("origin");
+               var cb = new GitCallbacks(this);
+               r.connect(Ggit.Direction.FETCH, cb, null, null);
+               this.remote_heads = r.list();
+       
+       }
     
 }
index e3ded34..4c790f5 100644 (file)
@@ -38,7 +38,7 @@ static int main (string[] args) {
             }
          ); 
 
-
+       Ggit.init();
     Gtk.init (ref args);
     
     GitMonitor.gitlive =  Environment.get_home_dir() + "/gitlive";
index aa78ad4..f1368fd 100644 (file)
@@ -17,7 +17,8 @@ Gitlive_PKGS = \
                --pkg libsoup-2.4 \
                --pkg json-glib-1.0 \
                --pkg  gtksourceview-3.0 \
-               --pkg  webkit2gtk-4.0
+               --pkg  webkit2gtk-4.0 \
+               --pkg libgit2-glib-1.0 
                
 
 Gitlive_SOURCES = \
@@ -39,7 +40,8 @@ Gitlive_SOURCES = \
           Ticket.vala \
           NewBranch.vala \
           MergeBranch.vala \
-          RepoStatusPopover.vala
+          RepoStatusPopover.vala \
+          GitCallbacks.vala
 
           
 
index f53c0be..c30e8fe 100644 (file)
@@ -13,8 +13,8 @@
     "response" : " (self, response_id) =>  { \n  \n\tGLib.debug(\"got %d\", (int) response_id);\n\tif (response_id < 1) {\n\t    _this.el.hide();\t\n\t    this.running = false; \n    \tGitMonitor.gitmonitor.start();\n\t \treturn;\n\t}\n\t\n\t\n\t\n\t /*\n\t// have they selected a ticket..\n\t// make that the current active ticket?\n\t// we really need to store locally what ticket is being worked on..\n\t// in theory we could be working on multiple project and not merging..\n\t// -- each repo would have their active ticket (only one per repo)\n\t// -- so we could just store that in there\n\t// -- initial load can check the contents of the ticket files on first scan.\n\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\n    if (this.repo != null) {\n    \tvar bn = _this.name.el.get_text();\n    \tif (ticket_id != \"\" ) {\n\t\t\tthis.repo.setActiveTicket( RooTicket.singleton().getById(ticket_id), bn);\n\t\t} else {\n\t\t\tthis.repo.createBranchNamed(bn);\n\t\t}\n    }\n\t*/\n\t\n\tif (this.repo != null) {\n\t\trepo.doMerge(\n\t\t\t_this.actionsel.selectedAction(), \n\t\t\t_this.ticketsel.selectedTicketId(),\n\t\t\t_this.name.el.get_text()\n\t\t);\n\t\n\t} else {\n\t\tGitRepo.doMerges(\n\t\t\t_this.actionsel.selectedAction(), \n\t\t\t_this.ticketsel.selectedTicketId(),\n\t\t\t_this.name.el.get_text()\n\t\t);\n\t}\n\tthis.running = false; \n\n\t \n\t_this.el.hide();\t\n \tGitMonitor.gitmonitor.start();\n\n\t \n}"
    },
    "default_width" : 500,
-   "# GitRepo repo" : "",
    "$ deletable" : true,
+   "# GitRepo repo" : "",
    "title" : "Merge Branch",
    "xtype" : "Dialog",
    "|   void show" : "(  RooTicket ticket, GitRepo? repo ) \n{\n     // this.el.set_gravity(Gdk.Gravity.NORTH);\n    if (this.running) {\n    \treturn;\n\t}\n\tGitMonitor.gitmonitor.stop();\n\t\n\t_this.el.show_all();\n\t\n\t_this.table.el.hide();\n\t_this.scrolled_window.el.hide();\n\t_this.spinner.el.show();\n\t_this.spinner.el.start();\t\n\tthis.el.set_keep_above(true);    \n\tthis.el.move((Gdk.Screen.width() / 2)- 250 ,0);\n       \tGLib.debug(\"Loading tickets\"); \n \n\t\n    this.ticket = ticket;\n    this.repo = repo;\n    \n\t\n\tTimeout.add_seconds(1, () => {\n\t\n        _this.prmodel.loadProjects(ticket.project_id);\n\t\n\t    _this.diff_view.el.get_buffer().set_text(\n\t    \trepo != null ? repo.previewMerge() : GitRepo.previewMerges(ticket.id)\n    \t);\t\t\n\t\t// if we are not working on a ticket, then we should be able to pick one?\n\t \t_this.dbmodel.loadTickets(ticket.project_id);\n\t \t_this.actionmodel.loadActions();\n\t \t_this.mergebtn.updateState();\n\t\t_this.view.loadTicket(ticket.id);\n\t\t_this.spinner.el.stop();\n\t\t_this.spinner.el.hide();\t\n\n\t\tthis.table.el.show();\n\t\treturn false;\n\t});\n\t\n\tthis.el.run();\n\t \n}",
          "items" : [
           {
            "id" : "actioncellrenderer",
-           "* pack" : "pack_start,true",
            "xtype" : "CellRendererText",
+           "* pack" : "pack_start,true",
            "$ xns" : "Gtk"
           },
           {
            "id" : "actionmodel",
-           "* pack" : "set_model",
            "xtype" : "ListStore",
+           "* pack" : "set_model",
            "$ columns" : "typeof(string),typeof(string)",
            "n_columns" : 2,
            "$ xns" : "Gtk",
@@ -96,8 +96,8 @@
           "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar project_id = this.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\n\t\n\t\n\t/*if (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n\t*/\n}"
          },
          "* ctor" : "new Gtk.ComboBox.with_entry()",
-         "| string selectedProjectId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.prmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
          "id" : "projectsel",
+         "| string selectedProjectId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.prmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
          "* init" : "this.el.set_entry_text_column(1);\nthis.el.get_child().set_sensitive(false);",
          "bool hexpand" : true,
          "* pack" : "attach_defaults,1,2,1,2",
          "items" : [
           {
            "id" : "prcellrenderer",
-           "* pack" : "pack_start,true",
            "xtype" : "CellRendererText",
+           "* pack" : "pack_start,true",
            "$ xns" : "Gtk"
           },
           {
          "items" : [
           {
            "id" : "dbcellrenderer",
-           "xtype" : "CellRendererText",
            "* pack" : "pack_start,true",
+           "xtype" : "CellRendererText",
            "$ xns" : "Gtk"
           },
           {
            "id" : "dbmodel",
-           "xtype" : "ListStore",
            "* pack" : "set_model",
+           "xtype" : "ListStore",
            "| void loadTickets" : "(string project_id  ) {\n\n\n    \n    // fixme .. get project id from selection..\n    \n     RooTicket.singleton().loadTickets(\n \t\t\tproject_id,\n \t\t\t_this.btn_not_me.el.active ? RooTicket.Who.ANYBODY :  RooTicket.Who.ME,\n \t\t\t _this.btn_closed.el.active ? RooTicket.Status.ALL :  RooTicket.Status.ACTIVE\n\t\t );\n        \n    _this.ticketsel.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a ticket --\");\n    \n    _this.ticketsel.el.set_active_iter(iter);\n    \n    if (_this.ticket != null &&  _this.ticket.id == \"-1\") {\n\t\tel.append(out iter);\n\t\tel.set_value(iter, 0, \"-1\");\n\t\tel.set_value(iter, 1, \"Temporary Branch - No ticket specified/relivant\");\n        _this.ticketsel.el.set_active_iter(iter);\t\n     }\n    \n    \n    \n    var tickets = RooTicket.singleton().tickets;\n    foreach(var ticket in tickets) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, ticket.id);\n        el.set_value(iter, 1, \"#%s [%s] %s\".printf( ticket.id, ticket.project_id_name , ticket.summary));\n        \n        if (_this.ticket != null && _this.ticket.id == ticket.id) {\n\t\t    _this.ticketsel.el.set_active_iter(iter);\n        }\n        \n    }\n    \n    _this.ticketsel.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
            "$ columns" : "typeof(string),typeof(string)",
            "n_columns" : 2,
             "toggled" : "() => {\n\tvar project_id = _this.projectsel.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\t\n}"
            },
            "id" : "btn_not_me",
-           "* pack" : "add",
            "string label" : "Show tickets not assigned to me",
+           "* pack" : "add",
            "xtype" : "CheckButton",
            "$ xns" : "Gtk"
           },
             "toggled" : "() => {\n \tvar project_id = _this.projectsel.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\t\n\t \n}"
            },
            "id" : "btn_closed",
-           "string label" : "Show closed Tickets",
            "xtype" : "CheckButton",
+           "string label" : "Show closed Tickets",
            "* pack" : "add",
            "$ xns" : "Gtk"
           },
        "items" : [
         {
          "id" : "label_diff",
-         "* pack" : false,
          "xtype" : "Label",
+         "* pack" : false,
          "string label" : "Projected Commit Diff",
          "$ xns" : "Gtk"
         },
         {
          "id" : "label_ticket",
-         "string label" : "Ticket Details",
          "* pack" : false,
+         "string label" : "Ticket Details",
          "xtype" : "Label",
          "$ xns" : "Gtk"
         },
          "items" : [
           {
            "int height_request" : 400,
-           "* pack" : "pack_start,true,true,0",
            "xtype" : "ScrolledWindow",
+           "* pack" : "pack_start,true,true,0",
            "$ xns" : "Gtk",
            "items" : [
             {
            "items" : [
             {
              "id" : "view",
-             "* pack" : "add",
              "xtype" : "WebView",
+             "* pack" : "add",
              "$ xns" : "WebKit",
              "| void loadTicket" : "(string tid) {\n\tint h,w;\n\t_this.el.get_size(out w, out h);\n\t\n\tif (tid == \"\") {\n\t\t_this.scrolled_window.el.hide();\n\t\t_this.el.resize(w, 150);\n\t} else {\n\t\t_this.scrolled_window.el.show();\n\t\t_this.el.resize(w, 800);\n\t}\n\t\n\tvar rs =  RooTicket.singleton();\t\t\n\tvar uri = new WebKit.URIRequest(\"https://roojs.com/admin.php/MTrack/View/\" + tid);\n\tvar hd = uri.get_http_headers();\n\tvar authCode = Base64.encode (\"%s:%s\".printf(rs.username, rs.password).data);\n\thd.append(\"Authorization\", \"Basic %s\".printf(authCode));\n\t\n\t this.el.load_request(uri);\n}\n"
             }
     },
     {
      "label" : "Cancel",
-     "xtype" : "Button",
      "* pack" : "add_action_widget,0",
+     "xtype" : "Button",
      "Gtk.ReliefStyle relief" : "Gtk.ReliefStyle.NONE",
      "$ xns" : "Gtk"
     },
     {
      "label" : "Do Merge",
-     "id" : "mergebtn",
      "| void updateState" : "() {\n\tif (_this.actionsel.selectedAction() == \"\") {\n\t\t// need to select an action..\n\t\tthis.el.set_sensitive(false);\n\t\treturn;\n\t\n\t\n\t}\n\t\tthis.el.set_sensitive(true);\n\t\treturn;\n}\n",
+     "id" : "mergebtn",
      "* init" : "{\n   this.el.get_style_context().add_class(\"suggested-action\");\n}\n",
      "xtype" : "Button",
      "* pack" : "add_action_widget,1",
index dd19c38..2d55a7a 100644 (file)
   {
    "listeners" : {
     "delete_event" : "(self, event) => {\n    this.el.hide();\n    return true; \n    //test  \n}\n ",
-    "response" : " (self, response_id) =>  { \n  \n\tGLib.debug(\"got %d\", (int) response_id);\n\t\n\t \n\t\n\t \n\t// have they selected a ticket..\n\t// make that the current active ticket?\n\t// we really need to store locally what ticket is being worked on..\n\t// in theory we could be working on multiple project and not merging..\n\t// -- each repo would have their active ticket (only one per repo)\n\t// -- so we could just store that in there\n\t// -- initial load can check the contents of the ticket files on first scan.\n\n\t \n\tif (response_id < 1) {\n\t    _this.el.hide();\t\n\t    this.running = false; \n\t \treturn;\n\t}\n\t\n\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\n    if (this.repo != null) {\n    \tvar bn = _this.name.el.get_text();\n\n\t\tvar res = this.repo.setActiveTicket(\t\t\t\n\t\t\t RooTicket.singleton().getById(ticket_id != \"\" ? ticket_id : \"-1\"), bn\n\t\t );\n\t\t if (res) {\n\t\t \t// start the monitoring..\n\t\t \t GitMonitor.gitmonitor.start();\n\t\t \t \n\t\t }\n    }\n     \n\n    this.running = false; \n\n\tthis.el.hide();\n\t \n\t \n\n\t \n}"
+    "response" : " (self, response_id) =>  { \n  \n\tGLib.debug(\"got %d\", (int) response_id);\n\t\n\t \n\t\n\t \n\t// have they selected a ticket..\n\t// make that the current active ticket?\n\t// we really need to store locally what ticket is being worked on..\n\t// in theory we could be working on multiple project and not merging..\n\t// -- each repo would have their active ticket (only one per repo)\n\t// -- so we could just store that in there\n\t// -- initial load can check the contents of the ticket files on first scan.\n\n\t \n\tif (response_id < 1) {\n\t    _this.el.hide();\t \n\t    this.running = false; \t    \n\t    GitMonitor.gitmonitor.start();\n\n\t \treturn;\n\t}\n\t\n\tswitch(response_id) {\n\t\tcase 1: \n\t\n\t\t\t\n\t\t\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\t\t\n\t\t\tif (this.repo != null) {\n\t\t\t\t var bn = _this.name.el.get_text();\n\n\t\t\t\t var res = this.repo.setActiveTicket(\t\t\t\n\t\t\t\t\t RooTicket.singleton().getById(ticket_id != \"\" ? ticket_id : \"-1\"), bn\n\t\t\t\t );\n\t\t\t\t if (res) {\n\t\t\t\t \t// start the monitoring..\n\t\t\t\t \t GitMonitor.gitmonitor.start();\n\t\t\t\t \t \n\t\t\t\t }\n\t\t\t}\n     \t\tbreak;\n \t\tcase 2: // create ticket + branch\n \t\t\n\t \t\tvar tid = RooTicket.singleton().createTicket(\n\t\t\n\t\t\t\t_this.project_id.selectedProjectId(),\n\t\t\t\n\t\t\t\t_this.milestone_id.selectedMilestoneId(),\n\t\t\t\t_this.priority_id.selectedPriorityId() ,\n\t\t\t\t_this.severity_id.selectedSeverityId() ,\t\t\n\t\t\t\t_this.classification_id.selectedClassificationId() ,\n\t\t\t\t_this.developer_id.selectedDeveloperId(),\n\t\t\t\t_this.summary.el.get_text() ,\n\t\t\t\t_this.description.el.buffer.text \n\t\t\t);\n\t\t\tvar ticket = RooTicket.singleton().getById(tid);\n\t\t\tvar name = RooTicket.singleton().usernameLocal();\n\t\t\t var bn = \"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName());\n\n\n\t\t\t var res = this.repo.setActiveTicket( ticket, bn );\n\t\t\tif (res) {\n\t\t\t \t// start the monitoring..\n\t\t\t \t GitMonitor.gitmonitor.start(); \n\t\t\t }\n\t\t\t \n\t \t\t\n \t\t\n \t\t\n\t \t\tbreak;\n \t\t\n \t\tcase 3: // just commit...\n\t\t   _this.repo.git({ \"commit\" , \"-a\" ,\"-m\", _this.commit_message.el.get_text() });\n\t\t   _this.repo.push();\n\t\t   _this.repo.loadBranches();\n\t\t   _this.repo.loadStatus();\n\t\t \t GitMonitor.gitmonitor.start(); \n \t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n    this.running = false; \n\n\tthis.el.hide();\n\t \n\t \n\n\t \n}"
    },
    "default_width" : 500,
    "$ deletable" : true,
    "title" : "Create a working branch ",
    "xtype" : "Dialog",
    "# GitRepo? repo" : "null",
-   "|   void show" : "( GitRepo repo, Gee.ArrayList<GitMonitorQueue> queue, string tid = \"\" ) \n{\n     // this.el.set_gravity(Gdk.Gravity.NORTH);\n    if (this.running) { // should not happen!!\n    \tGLib.error(\"new branch show called, when already being displayed?\");\n\t}\n\tthis.queue = queue;\n\t\n\tthis.running  = true;\n\tGitMonitor.gitmonitor.stop();\n\t\n    this.repo = repo;\n    \n     \n    \n\tthis.el.move((Gdk.Screen.width() / 2)- 250 ,0);\n\tthis.el.set_default_size( 500,200); // not sure why it grows..\n    GLib.debug(\"Loading tickets\"); \n     \n\n    this.el.show_all();\n    this.el.set_keep_above(true);\n   \n    \n    var curproj = RooProject.getProjectByRepo(this.repo);\n     _this.prmodel.loadProjects(curproj == null ? \"\" : curproj.id);\n    \n \t_this.dbmodel.loadTickets(curproj == null ? \"\": curproj.id, tid);\n \t_this.createbtn.updateState();\n \t\n\t_this.ticketsel.el.get_child().get_style_context().remove_class(\"warning\");\n \tif (tid != \"\") { \n\t \tvar name = RooTicket.singleton().usernameLocal();\n \t\tvar ticket = RooTicket.singleton().getById(tid);\n\t\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t} else {\n\t\t_this.ticketsel.el.get_child().get_style_context().add_class(\"warning\");\n\t}\n    _this.view.loadTicket(tid);\n \tthis.el.run();\n\n}",
+   "|   void show" : "( GitRepo repo, Gee.ArrayList<GitMonitorQueue> queue, string tid = \"\" ) \n{\n     // this.el.set_gravity(Gdk.Gravity.NORTH);\n    if (this.running) { // should not happen!!\n    \tGLib.error(\"new branch show called, when already being displayed?\");\n\t}\n\t\n\t\n\tthis.queue = queue;\n\tthis.running  = true;\n\tGitMonitor.gitmonitor.stop();\n\t\n\t\n    this.repo = repo;\n\n\t\n\t\n\t\n     \n\n    this.el.show_all();\n    _this.table.el.hide(); // hide ticket layout\n\t_this.diff_sv.el.hide();\n\t_this.el.resize( 500,100); \n     \n    this.el.set_keep_above(true);\n\t\n\t_this.notebook.el.set_current_page(0);\n\t\n\t_this.select_ticket_tab.load_data(tid);\n\t_this.create_ticket_tab.load_data();\n\t//_this.quick_commit_tab.load_data();\n     _this.commit_message.el.set_text(\"\");\n    _this.diff_view.el.get_buffer().set_text( this.repo.diffWorking() );\t\n   \n   \n\tthis.el.move((Gdk.Screen.width() / 2)- 250 ,0);\n\tthis.el.resize( 500,100); // not sure why it grows..\n\t    \n     \n    \n \tthis.el.run();\n\n}",
    "default_height" : 500,
    "$ xns" : "Gtk",
    "# bool running" : false,
    "bool modal" : true,
    "items" : [
     {
-     "xtype" : "Box",
-     "$ pack" : "get_content_area().add",
+     "listeners" : {
+      "switch_page" : "(page, page_num) => {\n\tGLib.debug(\"Switch to page: %d\", (int)page_num);\n\tswitch(page_num) {\n\t\tcase 0: \n\t\t\t_this.table.el.hide(); // hide ticket layout\n\t\t\t_this.diff_sv.el.hide();\n\t\t\t_this.el.resize( 500,100); \n\t\t\tbreak; // do nothing.. it's already loaded at start.\n\t\tcase 1: \n\t\t\t_this.diff_sv.el.hide();\n\t\t\t_this.table.el.show(); \n\t\t\t_this.el.resize( 500,100); \n\t\t//\t_this.create_ticket_tab.load_data();\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\t_this.quick_commit_tab.load_data();\n\t\t\t_this.diff_sv.el.show();\n\t\t\t_this.el.resize( 500,100); \n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n"
+     },
+     "id" : "notebook",
+     "* pack" : "get_content_area().add",
+     "xtype" : "Notebook",
      "$ xns" : "Gtk",
-     "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
+     "bool vexpand" : true,
      "items" : [
       {
-       "bool homogeneous" : true,
-       "bool expand" : false,
-       "xtype" : "Table",
-       "* pack" : "pack_start,false,false,0",
-       "uint column_spacing" : 4,
-       "n_columns" : 5,
+       "id" : "label_select_ticket",
+       "* pack" : false,
+       "xtype" : "Label",
+       "string label" : "Select Existing Ticket to work on",
+       "$ xns" : "Gtk"
+      },
+      {
+       "id" : "label_create_ticket",
+       "xtype" : "Label",
+       "* pack" : false,
+       "string label" : "Create a New Ticket",
+       "$ xns" : "Gtk"
+      },
+      {
+       "id" : "label_quick_commit",
+       "* pack" : false,
+       "xtype" : "Label",
+       "string label" : "Quick Commit",
+       "$ xns" : "Gtk"
+      },
+      {
+       "id" : "select_ticket_tab",
+       "bool homogeneous" : false,
+       "* pack" : "append_page,_this.label_select_ticket.el",
+       "xtype" : "Box",
+       "| void load_data" : "(string tid = \"\") {\n\n    \n\t _this.branch_table.el.hide();\n\t  _this.scrolled_window.el.hide();\n\t_this.branch_spinner.el.show();\n\t_this.branch_spinner.el.start();\t\n\t_this.el.resize( 500,100); \t\n    Timeout.add(200, () => {\n\t\n\n\t\tGLib.debug(\"Loading tickets\"); \n\t\t\n\t\tvar curproj = RooProject.getProjectByRepo(_this.repo);\n\t\t _this.prmodel.loadProjects(curproj == null ? \"\" : curproj.id);\n\t\t\n\t \t_this.dbmodel.loadTickets(curproj == null ? \"\": curproj.id, tid);\n\t \t_this.branchbtn.updateState();\n\t \t\n\t\t_this.ticketsel.el.get_child().get_style_context().remove_class(\"warning\");\n\t \tif (tid != \"\") { \n\t\t \tvar name = RooTicket.singleton().usernameLocal();\n\t \t\tvar ticket = RooTicket.singleton().getById(tid);\n\t\t\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t\t} else {\n\t\t\t_this.ticketsel.el.get_child().get_style_context().add_class(\"warning\");\n\t\t}\n\t\t_this.view.loadTicket(tid);\n\t  \t _this.branch_table.el.show();\n\t\t_this.branch_spinner.el.stop();\n\t\t_this.branch_spinner.el.hide();\t\n\t\t_this.el.resize( 500,100); \n\t\treturn false;\n\t});\n\t\n}\n",
        "$ xns" : "Gtk",
-       "n_rows" : 5,
-       "bool vexpand" : false,
-       "int margin" : 2,
+       "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
        "items" : [
         {
-         "label" : "Project",
-         "$ visible" : true,
-         "Gtk.Align halign" : "Gtk.Align.START",
-         "* pack" : "attach_defaults,0,1,0,1",
-         "xtype" : "Label",
-         "$ justify" : "Gtk.Justification.RIGHT",
-         "x_options" : 4,
-         "$ xns" : "Gtk"
-        },
-        {
-         "label" : "Ticket",
-         "$ visible" : true,
-         "Gtk.Align halign" : "Gtk.Align.START",
-         "* pack" : "attach_defaults,1,2,0,1",
-         "xtype" : "Label",
-         "x_options" : 4,
-         "$ xns" : "Gtk"
-        },
-        {
-         "listeners" : {
-          "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar project_id = this.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\n\t\n\t\n\t/*if (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n\t*/\n}"
-         },
-         "* ctor" : "new Gtk.ComboBox.with_entry()",
-         "id" : "projectsel",
-         "| string selectedProjectId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.prmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
-         "* init" : "this.el.set_entry_text_column(1);",
-         "* pack" : "attach_defaults,0,1,1,2",
-         "xtype" : "ComboBox",
-         "# bool loading" : false,
+         "id" : "branch_table",
+         "bool homogeneous" : true,
+         "bool expand" : false,
+         "xtype" : "Table",
+         "* pack" : "pack_start,false,false,0",
+         "uint column_spacing" : 4,
+         "n_columns" : 5,
          "$ xns" : "Gtk",
+         "n_rows" : 5,
+         "bool vexpand" : false,
+         "int margin" : 2,
          "items" : [
           {
-           "id" : "prcellrenderer",
-           "xtype" : "CellRendererText",
-           "* pack" : "pack_start,true",
+           "label" : "Project",
+           "$ visible" : true,
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,0,1,0,1",
+           "xtype" : "Label",
+           "$ justify" : "Gtk.Justification.RIGHT",
+           "x_options" : 4,
            "$ xns" : "Gtk"
           },
           {
-           "| void loadProjects" : "  (string id) {\n\n\n    \n    _this.projectsel.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a project --\");\n    if (id == \"\") {\n\t    _this.projectsel.el.set_active_iter(iter);\n    }\n  \n    foreach(var project in RooProject.projects()) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.name );\n        if (id == project.id) {\n\t \t   _this.projectsel.el.set_active_iter(iter);\n\t    }   \n        \n    }\n    \n    _this.projectsel.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
-           "id" : "prmodel",
-           "* pack" : "set_model",
-           "xtype" : "ListStore",
-           "$ columns" : "typeof(string),typeof(string)",
-           "n_columns" : 2,
+           "label" : "Ticket",
+           "$ visible" : true,
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,1,2,0,1",
+           "xtype" : "Label",
+           "x_options" : 4,
            "$ xns" : "Gtk"
-          }
-         ]
-        },
-        {
-         "listeners" : {
-          "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tthis.el.get_child().get_style_context().remove_class(\"warning\");\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\t_this.view.loadTicket(\"\");\t\t\n\t\t\n\t\tthis.el.get_child().get_style_context().add_class(\"warning\");\n\t\t_this.createbtn.updateState();\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t_this.scrolled_window.el.show();\n\t \n\t_this.view.loadTicket(ticket.id);\n\t_this.createbtn.updateState();\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n}"
-         },
-         "* ctor" : "new Gtk.ComboBox.with_entry()",
-         "id" : "ticketsel",
-         "* init" : "//this.el.add_attribute(_this.dbcellrenderer.el , \"markup\", 1 );\nthis.el.set_entry_text_column(1);\nthis.el.get_child().set_sensitive(false); ",
-         "* pack" : "attach_defaults,1,4,1,2",
-         "xtype" : "ComboBox",
-         "# bool loading" : false,
-         "$ xns" : "Gtk",
-         "| string selectedTicketId" : "() {\nGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.dbmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
-         "items" : [
+          },
           {
-           "id" : "dbcellrenderer",
-           "* pack" : "pack_start,true",
-           "xtype" : "CellRendererText",
+           "listeners" : {
+            "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar project_id = this.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\n\t\n\t\n\t/*if (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n\t*/\n}"
+           },
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "| string selectedProjectId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.prmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "id" : "projectsel",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,1,2",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "items" : [
+            {
+             "id" : "prcellrenderer",
+             "* pack" : "pack_start,true",
+             "xtype" : "CellRendererText",
+             "$ xns" : "Gtk"
+            },
+            {
+             "| void loadProjects" : "  (string id) {\n\n\n    \n    _this.projectsel.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a project --\");\n    if (id == \"\") {\n\t    _this.projectsel.el.set_active_iter(iter);\n    }\n  \n    foreach(var project in RooProject.projects()) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.name );\n        if (id == project.id) {\n\t \t   _this.projectsel.el.set_active_iter(iter);\n\t    }   \n        \n    }\n    \n    _this.projectsel.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
+             "id" : "prmodel",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "listeners" : {
+            "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tthis.el.get_child().get_style_context().remove_class(\"warning\");\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\t_this.view.loadTicket(\"\");\t\t\n\t\t\n\t\tthis.el.get_child().get_style_context().add_class(\"warning\");\n\t\t_this.createbtn.updateState();\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t_this.scrolled_window.el.show();\n\t \n\t_this.view.loadTicket(ticket.id);\n\t_this.branchbtn.updateState();\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n}"
+           },
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "ticketsel",
+           "* init" : "//this.el.add_attribute(_this.dbcellrenderer.el , \"markup\", 1 );\nthis.el.set_entry_text_column(1);\nthis.el.get_child().set_sensitive(false); ",
+           "* pack" : "attach_defaults,1,5,1,2",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "| string selectedTicketId" : "() {\nGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.dbmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "items" : [
+            {
+             "id" : "dbcellrenderer",
+             "xtype" : "CellRendererText",
+             "* pack" : "pack_start,true",
+             "$ xns" : "Gtk"
+            },
+            {
+             "id" : "dbmodel",
+             "xtype" : "ListStore",
+             "* pack" : "set_model",
+             "| void loadTickets" : "(string project_id , string tid = \"\") {\n\n\n    \n    // fixme .. get project id from selection..\n    \n     RooTicket.singleton().loadTickets(\n \t\t\tproject_id,\n \t\t\t_this.btn_not_me.el.active ? RooTicket.Who.ANYBODY :  RooTicket.Who.ME,\n \t\t\t _this.btn_closed.el.active ? RooTicket.Status.ALL :  RooTicket.Status.ACTIVE\n\t\t );\n        \n    _this.ticketsel.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a ticket --\");\n    \n    _this.ticketsel.el.set_active_iter(iter);\n    var tickets = RooTicket.singleton().tickets;\n    foreach(var ticket in tickets) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, ticket.id);\n        el.set_value(iter, 1, \"#%s %s\".printf( ticket.id, ticket.summary));\n        \n        if (ticket.id == tid) {\n\t\t    _this.ticketsel.el.set_active_iter(iter);\n        }\n        \n    }\n    \n    _this.ticketsel.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "label" : "Use this as branch name",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "xalign" : 0.90000000000000002,
+           "* pack" : "attach_defaults,0,1,3,4",
+           "xtype" : "Label",
+           "$ justify" : "Gtk.Justification.RIGHT",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "id" : "name",
+           "$ visible" : true,
+           "xtype" : "Entry",
+           "* pack" : "attach_defaults,0,4,4,5",
            "$ xns" : "Gtk"
           },
           {
-           "id" : "dbmodel",
-           "* pack" : "set_model",
-           "xtype" : "ListStore",
-           "| void loadTickets" : "(string project_id , string tid = \"\") {\n\n\n    \n    // fixme .. get project id from selection..\n    \n     RooTicket.singleton().loadTickets(\n \t\t\tproject_id,\n \t\t\t_this.btn_not_me.el.active ? RooTicket.Who.ANYBODY :  RooTicket.Who.ME,\n \t\t\t _this.btn_closed.el.active ? RooTicket.Status.ALL :  RooTicket.Status.ACTIVE\n\t\t );\n        \n    _this.ticketsel.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a ticket --\");\n    \n    _this.ticketsel.el.set_active_iter(iter);\n    var tickets = RooTicket.singleton().tickets;\n    foreach(var ticket in tickets) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, ticket.id);\n        el.set_value(iter, 1, \"#%s %s\".printf( ticket.id, ticket.summary));\n        \n        if (ticket.id == tid) {\n\t\t    _this.ticketsel.el.set_active_iter(iter);\n        }\n        \n    }\n    \n    _this.ticketsel.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
-           "$ columns" : "typeof(string),typeof(string)",
-           "n_columns" : 2,
+           "listeners" : {
+            "clicked" : "() => {\n\n\tGLib.debug(\"fire response = 1\");\n\t\n\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\n\tif (ticket_id == \"\") {\n\t\t_this.ticketsel.el.get_child().get_style_context().add_class(\"warning\");\n\t\treturn;\n\t}\n\t \n\t_this.el.response(1);\n}"
+           },
+           "label" : "Create Branch",
+           "| void updateState" : "() {\n\n\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\n\tif (ticket_id == \"\") {\n\t\tthis.el.set_sensitive(false);\n\t\treturn;\n\t}\n \n\tthis.el.set_sensitive(true);\n \n}\n",
+           "id" : "branchbtn",
+           "* init" : "{\n   this.el.get_style_context().add_class(\"suggested-action\");\n}\n",
+           "xtype" : "Button",
+           "* pack" : "attach_defaults,4,5,4,5",
            "$ xns" : "Gtk"
+          },
+          {
+           "* pack" : "attach_defaults,0,5,2,3",
+           "xtype" : "Box",
+           "$ xns" : "Gtk",
+           "Gtk.Orientation orientation" : "Gtk.Orientation.HORIZONTAL",
+           "items" : [
+            {
+             "listeners" : {
+              "toggled" : "() => {\n\tvar project_id = _this.projectsel.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\t\n}"
+             },
+             "id" : "btn_not_me",
+             "* pack" : "add",
+             "string label" : "Show tickets not assigned to me",
+             "xtype" : "CheckButton",
+             "$ xns" : "Gtk"
+            },
+            {
+             "listeners" : {
+              "toggled" : "() => {\n \tvar project_id = _this.projectsel.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\t\n\t \n}"
+             },
+             "id" : "btn_closed",
+             "string label" : "Show closed Tickets",
+             "xtype" : "CheckButton",
+             "* pack" : "add",
+             "$ xns" : "Gtk"
+            },
+            {
+             "listeners" : {
+              "activate_link" : "(uri) => {\n\tif (uri == \"refresh\") {\n\t\tRooProject.reload();\n\t\tvar curproj = RooProject.getProjectByRepo(_this.repo);\n\t\t _this.prmodel.loadProjects(curproj == null ? \"\": curproj.id);\n\n\t\t_this.dbmodel.loadTickets(curproj == null ? \"\": curproj.id);\t\t\n\t}\n\treturn true;\n}"
+             },
+             "bool use_markup" : true,
+             "Gtk.Align halign" : "Gtk.Align.END",
+             "bool hexpand" : true,
+             "* pack" : "add",
+             "xtype" : "Label",
+             "string label" : "<a href=\"refresh\">Refresh Ticket list</a>",
+             "$ xns" : "Gtk"
+            }
+           ]
           }
          ]
         },
         {
-         "listeners" : {
-          "clicked" : "() => {\n    _this.el.response(-1);\n\tTicket.singleton().show(_this.repo);\n\n}"
-         },
-         "bool expand" : false,
-         "xtype" : "Button",
-         "* pack" : "attach_defaults,4,5,1,2",
-         "string label" : "New Ticket",
-         "$ xns" : "Gtk"
-        },
-        {
-         "label" : "Use this as branch name",
-         "Gtk.Align halign" : "Gtk.Align.START",
-         "xalign" : 0.90000000000000002,
-         "* pack" : "attach_defaults,0,1,3,4",
-         "xtype" : "Label",
-         "$ justify" : "Gtk.Justification.RIGHT",
-         "x_options" : 4,
-         "$ xns" : "Gtk"
-        },
-        {
-         "id" : "name",
-         "$ visible" : true,
-         "xtype" : "Entry",
-         "* pack" : "attach_defaults,0,4,4,5",
-         "$ xns" : "Gtk"
+         "int height_request" : 500,
+         "id" : "scrolled_window",
+         "* init" : "{\n\tthis.el.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);\n}\n",
+         "* pack" : "add",
+         "xtype" : "ScrolledWindow",
+         "$ xns" : "Gtk",
+         "bool vexpand" : true,
+         "bool visible" : false,
+         "items" : [
+          {
+           "id" : "view",
+           "* pack" : "add",
+           "xtype" : "WebView",
+           "$ xns" : "WebKit",
+           "| void loadTicket" : "(string tid) {\n\tint h,w;\n\t_this.el.get_size(out w, out h);\n\t\n\tif (tid == \"\") {\n\t\t_this.scrolled_window.el.hide();\n\t\t_this.el.resize(w, 150);\n\t} else {\n\t\t_this.scrolled_window.el.show();\n\t\t_this.el.resize(w, 800);\n\t}\n\t\n\tvar rs =  RooTicket.singleton();\t\t\n\tvar uri = new WebKit.URIRequest(\"https://roojs.com/admin.php/MTrack/View/\" + tid);\n\tvar hd = uri.get_http_headers();\n\tvar authCode = Base64.encode (\"%s:%s\".printf(rs.username, rs.password).data);\n\thd.append(\"Authorization\", \"Basic %s\".printf(authCode));\n\t\n\t this.el.load_request(uri);\n}\n"
+          }
+         ]
         },
         {
-         "listeners" : {
-          "clicked" : "() => {\n\n\tGLib.debug(\"fire response = 1\");\n\t\n\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\n\tif (ticket_id == \"\") {\n\t\t_this.ticketsel.el.get_child().get_style_context().add_class(\"warning\");\n\t\treturn;\n\t}\n\t \n\t_this.el.response(1);\n}"
-         },
-         "label" : "Create Branch",
-         "id" : "createbtn",
-         "| void updateState" : "() {\n\n\tvar ticket_id = _this.ticketsel.selectedTicketId();\n\t\n\tif (ticket_id == \"\") {\n\t\tthis.el.set_sensitive(false);\n\t\treturn;\n\t}\n \n\tthis.el.set_sensitive(true);\n \n}\n",
-         "* init" : "{\n   this.el.get_style_context().add_class(\"suggested-action\");\n}\n",
-         "xtype" : "Button",
-         "* pack" : "attach_defaults,4,5,4,5",
-         "$ xns" : "Gtk"
-        },
+         "id" : "branch_spinner",
+         "bool hexpand" : true,
+         "* pack" : "add",
+         "xtype" : "Spinner",
+         "$ xns" : "Gtk",
+         "bool vexpand" : true
+        }
+       ]
+      },
+      {
+       "id" : "create_ticket_tab",
+       "bool homogeneous" : false,
+       "xtype" : "Box",
+       "* pack" : "append_page,_this.label_create_ticket.el",
+       "| void load_data" : "() {\n \n \t// _this.table.el.hide();\n\t//_this.spinner.el.show();\n\t//_this.spinner.el.start();\t\n\t\n    Timeout.add_seconds(1, () => {\n\t\t \n\t\tRooProject? curproj = null;\n\t\tif (_this.repo != null) {\n\t\t\tcurproj = RooProject.getProjectByRepo(_this.repo);\n\t\t}\n\t\t_this.tprmodel.loadProjects(curproj == null ? \"\" : curproj.id);\n\t\tif (curproj != null) {\n\t \n\t\t\t\n\t\t\tvar rt = RooTicket.singleton();\n\t\t\trt.loadProjectOptions(curproj.id);\n\t\t\t\n\t\t\t_this.msmodel.loadMilestones();\n\t\t\t_this.primodel.loadPriorities();\n\t\t\t_this.sevmodel.loadSeverities();\n\t\t\t_this.clmodel.loadClassifications();\t\n\t\t\t_this.devmodel.loadDevelopers();\t\n\t\t\t\n\t\t}\n\t\t_this.summary.el.set_text(\"\");\n\t\t_this.description.el.buffer.text = \"\"; \n\t\t//_this.spinner.el.stop();\n//\t\t_this.spinner.el.hide();\t\n\n\t\t//_this.table.el.show();\n\t    //_this.summary.el.grab_focus();\n \n\t \treturn false;\n \t});\n}\n",
+       "$ xns" : "Gtk",
+       "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
+       "items" : [
         {
-         "* pack" : "attach_defaults,0,5,2,3",
-         "xtype" : "Box",
+         "id" : "table",
+         "bool homogeneous" : true,
+         "bool expand" : false,
+         "xtype" : "Table",
+         "* pack" : "pack_start,false,false,0",
+         "uint column_spacing" : 4,
+         "n_columns" : 4,
          "$ xns" : "Gtk",
-         "Gtk.Orientation orientation" : "Gtk.Orientation.HORIZONTAL",
+         "n_rows" : 14,
+         "bool vexpand" : false,
+         "int margin" : 2,
          "items" : [
           {
-           "listeners" : {
-            "toggled" : "() => {\n\tvar project_id = _this.projectsel.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\t\n}"
-           },
-           "id" : "btn_not_me",
-           "string label" : "Show tickets not assigned to me",
-           "* pack" : "add",
-           "xtype" : "CheckButton",
+           "label" : "Project",
+           "$ visible" : true,
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,0,1,0,1",
+           "xtype" : "Label",
+           "$ xns" : "Gtk"
+          },
+          {
+           "label" : "Summary",
+           "$ visible" : true,
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,1,2,0,1",
+           "xtype" : "Label",
+           "x_options" : 4,
            "$ xns" : "Gtk"
           },
           {
            "listeners" : {
-            "toggled" : "() => {\n \tvar project_id = _this.projectsel.selectedProjectId();\n\t_this.dbmodel.loadTickets(project_id);\t\n\t \n}"
+            "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar project_id = this.selectedProjectId();\n\t\n\tvar rt = RooTicket.singleton();\n\trt.loadProjectOptions(project_id);\n\t\n\t_this.msmodel.loadMilestones();\n\t_this.primodel.loadPriorities();\n\t_this.sevmodel.loadSeverities();\n\t_this.clmodel.loadClassifications();\t\n\t_this.devmodel.loadDevelopers();\t\n\t\n\t// affects projects and milestones..\n\t\n\t\n\t/*if (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n\t*/\n}"
            },
-           "id" : "btn_closed",
-           "xtype" : "CheckButton",
-           "string label" : "Show closed Tickets",
-           "* pack" : "add",
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "project_id",
+           "| string selectedProjectId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.tprmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,1,2",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "items" : [
+            {
+             "id" : "tprcellrenderer",
+             "xtype" : "CellRendererText",
+             "* pack" : "pack_start,true",
+             "$ xns" : "Gtk"
+            },
+            {
+             "| void loadProjects" : "  (string id) {\n\n    \n    _this.project_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a project --\");\n    if (id == \"\") {\n\t    _this.project_id.el.set_active_iter(iter);\n    }\n\n    foreach(var project in RooProject.projects()) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.name );\n        if (id == project.id) {\n\t \t   _this.project_id.el.set_active_iter(iter);\n\t    }   \n        \n    }\n    \n    _this.project_id.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
+             "id" : "tprmodel",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "id" : "summary",
+           "$ visible" : true,
+           "xtype" : "Entry",
+           "* pack" : "attach_defaults,1,4,1,2",
+           "$ xns" : "Gtk"
+          },
+          {
+           "label" : "Milestone",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "xalign" : 0.90000000000000002,
+           "* pack" : "attach_defaults,0,1,2,3",
+           "xtype" : "Label",
+           "$ justify" : "Gtk.Justification.RIGHT",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "milestone_id",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,3,4",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "| string selectedMilestoneId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.msmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "items" : [
+            {
+             "id" : "msmodel",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "| void loadMilestones" : "  ( ) {\n\n    var rt = RooTicket.singleton();\n   // rt.loadProjects();\n    \n    _this.milestone_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a milestone --\");\n    _this.milestone_id.el.set_active_iter(iter);    \n     \n    var projects = rt.milestones;\n    foreach(var project in projects) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.display_name );\n      //  if (id == project.id) {\n\t //\t   _this.milestone.el.set_active_iter(iter);\n\t //   }   \n        \n    }\n    \n    \n    _this.milestone_id.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "label" : "Description",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,1,4,2,3",
+           "xtype" : "Label",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "id" : "description",
+           "* pack" : "attach_defaults,1,4,3,12",
+           "xtype" : "TextView",
+           "$ xns" : "Gtk",
+           "uint border_width" : 1
+          },
+          {
+           "label" : "Priority",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "xalign" : 0.90000000000000002,
+           "* pack" : "attach_defaults,0,1,4,5",
+           "xtype" : "Label",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "priority_id",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,5,6",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "| string selectedPriorityId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.primodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "items" : [
+            {
+             "id" : "primodel",
+             "| void loadPriorities" : "  ( ) {\n\n    var rt = RooTicket.singleton();\n   // rt.loadProjects();\n    \n    _this.priority_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    \n   var projects = rt.priorities;\n    foreach(var project in projects) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.display_name );\n        if (\"normal\" == project.name) {\n\t \t   _this.priority_id.el.set_active_iter(iter);\n\t    }   \n        \n    }\n    \n    _this.priority_id.loading = false;\n           \n                                     \n}\n",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "label" : "Severity",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,0,1,6,7",
+           "xtype" : "Label",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "severity_id",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,7,8",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "| string selectedSeverityId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.sevmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "items" : [
+            {
+             "| void loadSeverities" : "  () {\n\n    var rt = RooTicket.singleton();\n    //rt.loadProjects();\n    \n    _this.severity_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n     \n    var projects = rt.serverities;\n    foreach(var project in projects) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.display_name );\n        if (\"normal\" == project.name) {\n\t \t   _this.severity_id.el.set_active_iter(iter);\n\t    }   \n        \n    }\n   \n    _this.severity_id.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
+             "id" : "sevmodel",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "label" : "Classification",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,0,1,8,9",
+           "xtype" : "Label",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "classification_id",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,9,10",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "$ xns" : "Gtk",
+           "| string selectedClassificationId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.clmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "items" : [
+            {
+             "id" : "clmodel",
+             "| void loadClassifications" : "  ( ) {\n\n    var rt = RooTicket.singleton();\n    // rt.loadProjects();\n    \n    _this.classification_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n     \n    var projects = rt.classifications;\n    foreach(var project in projects) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.display_name );\n        if (\"bug\" == project.name) {\n\t \t   _this.classification_id.el.set_active_iter(iter);\n\t    }   \n        \n    }\n    \n    _this.classification_id.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk"
+            }
+           ]
+          },
+          {
+           "label" : "Assign to",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "* pack" : "attach_defaults,0,1,10,11",
+           "xtype" : "Label",
+           "x_options" : 4,
            "$ xns" : "Gtk"
           },
+          {
+           "* ctor" : "new Gtk.ComboBox.with_entry()",
+           "id" : "developer_id",
+           "* init" : "this.el.set_entry_text_column(1);",
+           "* pack" : "attach_defaults,0,1,11,12",
+           "xtype" : "ComboBox",
+           "# bool loading" : false,
+           "| string selectedDeveloperId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.devmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+           "$ xns" : "Gtk",
+           "items" : [
+            {
+             "id" : "devmodel",
+             "* pack" : "set_model",
+             "xtype" : "ListStore",
+             "$ columns" : "typeof(string),typeof(string)",
+             "n_columns" : 2,
+             "$ xns" : "Gtk",
+             "| void loadDevelopers" : "  ( ) {\n\n    var rt = RooTicket.singleton();\n    //rt.loadProjects();\n    \n    _this.developer_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a developer --\");\n  //  if (id == \"\") {\n\t    _this.developer_id.el.set_active_iter(iter);\n   // }\n    \n    var peps = rt.developers;\n    foreach(var p in peps) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, p.id);\n        el.set_value(iter, 1,  p.display_name );\n        if (rt.authuser_id == p.id) {\n\t \t   _this.developer_id.el.set_active_iter(iter);\n\t    }   \n    }\n \n    _this.developer_id.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n"
+            }
+           ]
+          },
           {
            "listeners" : {
-            "activate_link" : "(uri) => {\n\tif (uri == \"refresh\") {\n\t\tRooProject.reload();\n\t\tvar curproj = RooProject.getProjectByRepo(_this.repo);\n\t\t _this.prmodel.loadProjects(curproj == null ? \"\": curproj.id);\n\n\t\t_this.dbmodel.loadTickets(curproj == null ? \"\": curproj.id);\t\t\n\t}\n\treturn true;\n}"
+            "clicked" : "() => {\n\tGLib.debug(\"fire response = 1\");\n\t\n\t\n\tvar invalid = false;\n\t\n\t// validate first...\n\t_this.project_id.el.get_child().get_style_context().remove_class(\"warning\");\t\n\tif (_this.project_id.selectedProjectId() == \"\") {\n\t\t_this.project_id.el.get_child().get_style_context().add_class(\"warning\");\n\t\tinvalid = true;\n\t}\n\t\n\t_this.milestone_id.el.get_child().get_style_context().remove_class(\"warning\");\t\n\n\t_this.priority_id.el.get_child().get_style_context().remove_class(\"warning\");\t\n\tif (_this.priority_id.selectedPriorityId() == \"\") {\n\t\t_this.priority_id.el.get_child().get_style_context().add_class(\"warning\");\n\t\tinvalid = true;\n\t}\n\t\n\t_this.classification_id.el.get_child().get_style_context().remove_class(\"warning\");\t\n\tif (_this.classification_id.selectedClassificationId() == \"\") {\n\t\t_this.classification_id.el.get_child().get_style_context().add_class(\"warning\");\n\t\tinvalid = true;\n\t}\n\t\n\t_this.developer_id.el.get_child().get_style_context().remove_class(\"warning\");\t\n\tif (_this.developer_id.selectedDeveloperId() == \"\") {\n\t\t_this.developer_id.el.get_child().get_style_context().add_class(\"warning\");\n\t\tinvalid = true;\n\t}\n\t\n\t_this.summary.el.get_style_context().remove_class(\"warning\");\t\n\tif (_this.summary.el.get_text() == \"\") {\n\t\t_this.summary.el.get_style_context().add_class(\"warning\");\n\t\tinvalid = true;\n\t}\n\t\n\t_this.description.el.get_style_context().remove_class(\"warning\");\t\n \n\tif (invalid) {\n\t\treturn;\n\t}\n\tGLib.debug(\"for is valid\");\n\t\n\t_this.el.response(2);\n}"
            },
-           "bool use_markup" : true,
-           "Gtk.Align halign" : "Gtk.Align.END",
-           "bool hexpand" : true,
-           "* pack" : "add",
-           "xtype" : "Label",
-           "string label" : "<a href=\"refresh\">Refresh Ticket list</a>",
+           "label" : "Create Ticket & Branch",
+           "* init" : "{\n   this.el.get_style_context().add_class(\"suggested-action\");\n}\n",
+           "xtype" : "Button",
+           "* pack" : "attach_defaults,0,4,13,14",
            "$ xns" : "Gtk"
           }
          ]
        ]
       },
       {
-       "int height_request" : 500,
-       "id" : "scrolled_window",
-       "* init" : "{\n\tthis.el.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC);\n}\n",
-       "* pack" : "add",
-       "xtype" : "ScrolledWindow",
+       "id" : "quick_commit_tab",
+       "bool homogeneous" : false,
+       "* pack" : "append_page,_this.label_quick_commit.el",
+       "xtype" : "Box",
+       "| void load_data" : "() {\n\n  _this.createbtn.updateState();\n}\n",
        "$ xns" : "Gtk",
-       "bool vexpand" : true,
+       "Gtk.Orientation orientation" : "Gtk.Orientation.VERTICAL",
        "items" : [
         {
-         "id" : "view",
-         "xtype" : "WebView",
+         "bool homogeneous" : true,
+         "bool expand" : false,
+         "xtype" : "Table",
+         "* pack" : "pack_start,false,false,0",
+         "uint column_spacing" : 4,
+         "n_columns" : 5,
+         "$ xns" : "Gtk",
+         "n_rows" : 3,
+         "bool vexpand" : false,
+         "int margin" : 2,
+         "items" : [
+          {
+           "label" : "Just commit with this comment",
+           "Gtk.Align halign" : "Gtk.Align.START",
+           "xalign" : 0.90000000000000002,
+           "* pack" : "attach_defaults,0,1,0,1",
+           "xtype" : "Label",
+           "$ justify" : "Gtk.Justification.RIGHT",
+           "x_options" : 4,
+           "$ xns" : "Gtk"
+          },
+          {
+           "listeners" : {
+            "key_release_event" : "() => { \n\n\t_this.createbtn.updateState();\n\treturn true;\n}"
+           },
+           "id" : "commit_message",
+           "$ visible" : true,
+           "xtype" : "Entry",
+           "* pack" : "attach_defaults,0,5,1,2",
+           "$ xns" : "Gtk"
+          },
+          {
+           "listeners" : {
+            "clicked" : "() => {\n\n\tGLib.debug(\"fire response = 1\");\n\t\n\t \n\t \n\t_this.el.response(3);\n}"
+           },
+           "label" : "Commit Changes",
+           "id" : "createbtn",
+           "| void updateState" : "() {\n\n\tvar msg = _this.commit_message.el.get_text();\n\t\n\tif (msg == \"\") {\n\t\tthis.el.set_sensitive(false);\n\t\treturn;\n\t}\n \n\tthis.el.set_sensitive(true);\n \n}\n",
+           "* init" : "{\n   this.el.get_style_context().add_class(\"suggested-action\");\n}\n",
+           "xtype" : "Button",
+           "* pack" : "attach_defaults,0,5,2,3",
+           "$ xns" : "Gtk"
+          }
+         ]
+        },
+        {
+         "int height_request" : 400,
+         "id" : "diff_sv",
          "* pack" : "add",
-         "$ xns" : "WebKit",
-         "| void loadTicket" : "(string tid) {\n\tint h,w;\n\t_this.el.get_size(out w, out h);\n\t\n\tif (tid == \"\") {\n\t\t_this.scrolled_window.el.hide();\n\t\t_this.el.resize(w, 150);\n\t} else {\n\t\t_this.scrolled_window.el.show();\n\t\t_this.el.resize(w, 800);\n\t}\n\t\n\tvar rs =  RooTicket.singleton();\t\t\n\tvar uri = new WebKit.URIRequest(\"https://roojs.com/admin.php/MTrack/View/\" + tid);\n\tvar hd = uri.get_http_headers();\n\tvar authCode = Base64.encode (\"%s:%s\".printf(rs.username, rs.password).data);\n\thd.append(\"Authorization\", \"Basic %s\".printf(authCode));\n\t\n\t this.el.load_request(uri);\n}\n"
+         "xtype" : "ScrolledWindow",
+         "$ xns" : "Gtk",
+         "bool vexpand" : true,
+         "bool visible" : false,
+         "items" : [
+          {
+           "id" : "diff_view",
+           "* init" : " \n    var description =   Pango.FontDescription.from_string(\"monospace\");\n    description.set_size(9000);\n    this.el.override_font(description);\n     var lm = Gtk.SourceLanguageManager.get_default();\n                    \n    ((Gtk.SourceBuffer)(this.el.get_buffer())).set_language(\n        lm.get_language(\"diff\")\n    );",
+           "xtype" : "View",
+           "* pack" : "add",
+           "$ xns" : "GtkSource"
+          }
+         ]
         }
        ]
       }
index fbf036d..ea3833a 100644 (file)
@@ -12,6 +12,12 @@ public class NewBranch : Object
         }
         return _NewBranch;
     }
+    public Xcls_notebook notebook;
+    public Xcls_label_select_ticket label_select_ticket;
+    public Xcls_label_create_ticket label_create_ticket;
+    public Xcls_label_quick_commit label_quick_commit;
+    public Xcls_select_ticket_tab select_ticket_tab;
+    public Xcls_branch_table branch_table;
     public Xcls_projectsel projectsel;
     public Xcls_prcellrenderer prcellrenderer;
     public Xcls_prmodel prmodel;
@@ -19,11 +25,34 @@ public class NewBranch : Object
     public Xcls_dbcellrenderer dbcellrenderer;
     public Xcls_dbmodel dbmodel;
     public Xcls_name name;
-    public Xcls_createbtn createbtn;
+    public Xcls_branchbtn branchbtn;
     public Xcls_btn_not_me btn_not_me;
     public Xcls_btn_closed btn_closed;
     public Xcls_scrolled_window scrolled_window;
     public Xcls_view view;
+    public Xcls_branch_spinner branch_spinner;
+    public Xcls_create_ticket_tab create_ticket_tab;
+    public Xcls_table table;
+    public Xcls_project_id project_id;
+    public Xcls_tprcellrenderer tprcellrenderer;
+    public Xcls_tprmodel tprmodel;
+    public Xcls_summary summary;
+    public Xcls_milestone_id milestone_id;
+    public Xcls_msmodel msmodel;
+    public Xcls_description description;
+    public Xcls_priority_id priority_id;
+    public Xcls_primodel primodel;
+    public Xcls_severity_id severity_id;
+    public Xcls_sevmodel sevmodel;
+    public Xcls_classification_id classification_id;
+    public Xcls_clmodel clmodel;
+    public Xcls_developer_id developer_id;
+    public Xcls_devmodel devmodel;
+    public Xcls_quick_commit_tab quick_commit_tab;
+    public Xcls_commit_message commit_message;
+    public Xcls_createbtn createbtn;
+    public Xcls_diff_sv diff_sv;
+    public Xcls_diff_view diff_view;
 
         // my vars (def)
     public GitRepo? repo;
@@ -47,7 +76,7 @@ public class NewBranch : Object
         this.el.default_width = 500;
         this.el.deletable = true;
         this.el.modal = true;
-        var child_0 = new Xcls_Box2( _this );
+        var child_0 = new Xcls_notebook( _this );
         child_0.ref();
         this.el.get_content_area().add (  child_0.el  );
 
@@ -74,27 +103,72 @@ public class NewBranch : Object
         
                 
                if (response_id < 1) {
-                   _this.el.hide();    
-                   this.running = false; 
+                   _this.el.hide();     
+                   this.running = false;           
+                   GitMonitor.gitmonitor.start();
+        
                        return;
                }
                
-               var ticket_id = _this.ticketsel.selectedTicketId();
+               switch(response_id) {
+                       case 1: 
                
-            if (this.repo != null) {
-               var bn = _this.name.el.get_text();
+                               
+                               var ticket_id = _this.ticketsel.selectedTicketId();
+                               
+                               if (this.repo != null) {
+                                        var bn = _this.name.el.get_text();
+        
+                                        var res = this.repo.setActiveTicket(                   
+                                                RooTicket.singleton().getById(ticket_id != "" ? ticket_id : "-1"), bn
+                                        );
+                                        if (res) {
+                                               // start the monitoring..
+                                                GitMonitor.gitmonitor.start();
+                                                
+                                        }
+                               }
+                       break;
+                       case 2: // create ticket + branch
+                       
+                               var tid = RooTicket.singleton().createTicket(
+                       
+                                       _this.project_id.selectedProjectId(),
+                               
+                                       _this.milestone_id.selectedMilestoneId(),
+                                       _this.priority_id.selectedPriorityId() ,
+                                       _this.severity_id.selectedSeverityId() ,                
+                                       _this.classification_id.selectedClassificationId() ,
+                                       _this.developer_id.selectedDeveloperId(),
+                                       _this.summary.el.get_text() ,
+                                       _this.description.el.buffer.text 
+                               );
+                               var ticket = RooTicket.singleton().getById(tid);
+                               var name = RooTicket.singleton().usernameLocal();
+                                var bn = "wip_%s_T%s_%s".printf(name,ticket.id, ticket.summaryToBranchName());
         
-                       var res = this.repo.setActiveTicket(                    
-                                RooTicket.singleton().getById(ticket_id != "" ? ticket_id : "-1"), bn
-                        );
-                        if (res) {
-                               // start the monitoring..
-                                GitMonitor.gitmonitor.start();
-                                
-                        }
-            }
-             
         
+                                var res = this.repo.setActiveTicket( ticket, bn );
+                               if (res) {
+                                       // start the monitoring..
+                                        GitMonitor.gitmonitor.start(); 
+                                }
+                                
+                               
+                       
+                       
+                               break;
+                       
+                       case 3: // just commit...
+                          _this.repo.git({ "commit" , "-a" ,"-m", _this.commit_message.el.get_text() });
+                          _this.repo.push();
+                          _this.repo.loadBranches();
+                          _this.repo.loadStatus();
+                                GitMonitor.gitmonitor.start(); 
+                               break;
+                       default:
+                               break;
+               }
             this.running = false; 
         
                this.el.hide();
@@ -112,43 +186,177 @@ public class NewBranch : Object
         if (this.running) { // should not happen!!
                GLib.error("new branch show called, when already being displayed?");
        }
-       this.queue = queue;
        
+       
+       this.queue = queue;
        this.running  = true;
        GitMonitor.gitmonitor.stop();
        
+       
         this.repo = repo;
-        
-         
-        
-       this.el.move((Gdk.Screen.width() / 2)- 250 ,0);
-       this.el.set_default_size( 500,200); // not sure why it grows..
-        GLib.debug("Loading tickets"); 
+    
+       
+       
+       
          
     
         this.el.show_all();
+        _this.table.el.hide(); // hide ticket layout
+       _this.diff_sv.el.hide();
+       _this.el.resize( 500,100); 
+         
         this.el.set_keep_above(true);
+       
+       _this.notebook.el.set_current_page(0);
+       
+       _this.select_ticket_tab.load_data(tid);
+       _this.create_ticket_tab.load_data();
+       //_this.quick_commit_tab.load_data();
+         _this.commit_message.el.set_text("");
+        _this.diff_view.el.get_buffer().set_text( this.repo.diffWorking() );   
        
+       
+       this.el.move((Gdk.Screen.width() / 2)- 250 ,0);
+       this.el.resize( 500,100); // not sure why it grows..
+           
+         
         
-        var curproj = RooProject.getProjectByRepo(this.repo);
-         _this.prmodel.loadProjects(curproj == null ? "" : curproj.id);
-        
-       _this.dbmodel.loadTickets(curproj == null ? "": curproj.id, tid);
-       _this.createbtn.updateState();
-       
-       _this.ticketsel.el.get_child().get_style_context().remove_class("warning");
-       if (tid != "") { 
-               var name = RooTicket.singleton().usernameLocal();
-               var ticket = RooTicket.singleton().getById(tid);
-               _this.name.el.set_text("wip_%s_T%s_%s".printf(name,ticket.id, ticket.summaryToBranchName()));
-       } else {
-               _this.ticketsel.el.get_child().get_style_context().add_class("warning");
-       }
-        _this.view.loadTicket(tid);
        this.el.run();
     
     }
-    public class Xcls_Box2 : Object
+    public class Xcls_notebook : Object
+    {
+        public Gtk.Notebook el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_notebook(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.notebook = this;
+            this.el = new Gtk.Notebook();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.vexpand = true;
+            var child_0 = new Xcls_label_select_ticket( _this );
+            child_0.ref();
+            var child_1 = new Xcls_label_create_ticket( _this );
+            child_1.ref();
+            var child_2 = new Xcls_label_quick_commit( _this );
+            child_2.ref();
+            var child_3 = new Xcls_select_ticket_tab( _this );
+            child_3.ref();
+            this.el.append_page (  child_3.el , _this.label_select_ticket.el );
+            var child_4 = new Xcls_create_ticket_tab( _this );
+            child_4.ref();
+            this.el.append_page (  child_4.el , _this.label_create_ticket.el );
+            var child_5 = new Xcls_quick_commit_tab( _this );
+            child_5.ref();
+            this.el.append_page (  child_5.el , _this.label_quick_commit.el );
+
+            //listeners
+            this.el.switch_page.connect( (page, page_num) => {
+               GLib.debug("Switch to page: %d", (int)page_num);
+               switch(page_num) {
+                       case 0: 
+                               _this.table.el.hide(); // hide ticket layout
+                               _this.diff_sv.el.hide();
+                               _this.el.resize( 500,100); 
+                               break; // do nothing.. it's already loaded at start.
+                       case 1: 
+                               _this.diff_sv.el.hide();
+                               _this.table.el.show(); 
+                               _this.el.resize( 500,100); 
+                       //      _this.create_ticket_tab.load_data();
+                               break;
+                       case 2:
+                               _this.quick_commit_tab.load_data();
+                               _this.diff_sv.el.show();
+                               _this.el.resize( 500,100); 
+                               break;
+                       default:
+                               break;
+               }
+            });
+        }
+
+        // user defined functions
+    }
+    public class Xcls_label_select_ticket : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_label_select_ticket(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.label_select_ticket = this;
+            this.el = new Gtk.Label( "Select Existing Ticket to work on" );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_label_create_ticket : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_label_create_ticket(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.label_create_ticket = this;
+            this.el = new Gtk.Label( "Create a New Ticket" );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_label_quick_commit : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_label_quick_commit(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.label_quick_commit = this;
+            this.el = new Gtk.Label( "Quick Commit" );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_select_ticket_tab : Object
     {
         public Gtk.Box el;
         private NewBranch  _this;
@@ -157,25 +365,66 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Box2(NewBranch _owner )
+        public Xcls_select_ticket_tab(NewBranch _owner )
         {
             _this = _owner;
+            _this.select_ticket_tab = this;
             this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
 
             // my vars (dec)
 
             // set gobject values
-            var child_0 = new Xcls_Table3( _this );
+            this.el.homogeneous = false;
+            var child_0 = new Xcls_branch_table( _this );
             child_0.ref();
             this.el.pack_start (  child_0.el , false,false,0 );
             var child_1 = new Xcls_scrolled_window( _this );
             child_1.ref();
             this.el.add (  child_1.el  );
+            var child_2 = new Xcls_branch_spinner( _this );
+            child_2.ref();
+            this.el.add (  child_2.el  );
         }
 
         // user defined functions
+        public void load_data (string tid = "") {
+        
+            
+                _this.branch_table.el.hide();
+                 _this.scrolled_window.el.hide();
+               _this.branch_spinner.el.show();
+               _this.branch_spinner.el.start();        
+               _this.el.resize( 500,100);      
+            Timeout.add(200, () => {
+               
+        
+                       GLib.debug("Loading tickets"); 
+                       
+                       var curproj = RooProject.getProjectByRepo(_this.repo);
+                        _this.prmodel.loadProjects(curproj == null ? "" : curproj.id);
+                       
+                       _this.dbmodel.loadTickets(curproj == null ? "": curproj.id, tid);
+                       _this.branchbtn.updateState();
+                       
+                       _this.ticketsel.el.get_child().get_style_context().remove_class("warning");
+                       if (tid != "") { 
+                               var name = RooTicket.singleton().usernameLocal();
+                               var ticket = RooTicket.singleton().getById(tid);
+                               _this.name.el.set_text("wip_%s_T%s_%s".printf(name,ticket.id, ticket.summaryToBranchName()));
+                       } else {
+                               _this.ticketsel.el.get_child().get_style_context().add_class("warning");
+                       }
+                       _this.view.loadTicket(tid);
+                        _this.branch_table.el.show();
+                       _this.branch_spinner.el.stop();
+                       _this.branch_spinner.el.hide(); 
+                       _this.el.resize( 500,100); 
+                       return false;
+               });
+               
+        }
     }
-    public class Xcls_Table3 : Object
+    public class Xcls_branch_table : Object
     {
         public Gtk.Table el;
         private NewBranch  _this;
@@ -184,9 +433,10 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Table3(NewBranch _owner )
+        public Xcls_branch_table(NewBranch _owner )
         {
             _this = _owner;
+            _this.branch_table = this;
             this.el = new Gtk.Table( 5, 5, true );
 
             // my vars (dec)
@@ -196,10 +446,10 @@ public class NewBranch : Object
             this.el.margin = 2;
             this.el.column_spacing = 4;
             this.el.vexpand = false;
-            var child_0 = new Xcls_Label4( _this );
+            var child_0 = new Xcls_Label8( _this );
             child_0.ref();
             this.el.attach_defaults (  child_0.el , 0,1,0,1 );
-            var child_1 = new Xcls_Label5( _this );
+            var child_1 = new Xcls_Label9( _this );
             child_1.ref();
             this.el.attach_defaults (  child_1.el , 1,2,0,1 );
             var child_2 = new Xcls_projectsel( _this );
@@ -207,27 +457,24 @@ public class NewBranch : Object
             this.el.attach_defaults (  child_2.el , 0,1,1,2 );
             var child_3 = new Xcls_ticketsel( _this );
             child_3.ref();
-            this.el.attach_defaults (  child_3.el , 1,4,1,2 );
-            var child_4 = new Xcls_Button12( _this );
+            this.el.attach_defaults (  child_3.el , 1,5,1,2 );
+            var child_4 = new Xcls_Label16( _this );
             child_4.ref();
-            this.el.attach_defaults (  child_4.el , 4,5,1,2 );
-            var child_5 = new Xcls_Label13( _this );
+            this.el.attach_defaults (  child_4.el , 0,1,3,4 );
+            var child_5 = new Xcls_name( _this );
             child_5.ref();
-            this.el.attach_defaults (  child_5.el , 0,1,3,4 );
-            var child_6 = new Xcls_name( _this );
+            this.el.attach_defaults (  child_5.el , 0,4,4,5 );
+            var child_6 = new Xcls_branchbtn( _this );
             child_6.ref();
-            this.el.attach_defaults (  child_6.el , 0,4,4,5 );
-            var child_7 = new Xcls_createbtn( _this );
+            this.el.attach_defaults (  child_6.el , 4,5,4,5 );
+            var child_7 = new Xcls_Box19( _this );
             child_7.ref();
-            this.el.attach_defaults (  child_7.el , 4,5,4,5 );
-            var child_8 = new Xcls_Box16( _this );
-            child_8.ref();
-            this.el.attach_defaults (  child_8.el , 0,5,2,3 );
+            this.el.attach_defaults (  child_7.el , 0,5,2,3 );
         }
 
         // user defined functions
     }
-    public class Xcls_Label4 : Object
+    public class Xcls_Label8 : Object
     {
         public Gtk.Label el;
         private NewBranch  _this;
@@ -236,7 +483,7 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Label4(NewBranch _owner )
+        public Xcls_Label8(NewBranch _owner )
         {
             _this = _owner;
             this.el = new Gtk.Label( "Project" );
@@ -252,7 +499,7 @@ public class NewBranch : Object
         // user defined functions
     }
 
-    public class Xcls_Label5 : Object
+    public class Xcls_Label9 : Object
     {
         public Gtk.Label el;
         private NewBranch  _this;
@@ -261,7 +508,7 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Label5(NewBranch _owner )
+        public Xcls_Label9(NewBranch _owner )
         {
             _this = _owner;
             this.el = new Gtk.Label( "Ticket" );
@@ -500,7 +747,7 @@ public class NewBranch : Object
                _this.scrolled_window.el.show();
                 
                _this.view.loadTicket(ticket.id);
-               _this.createbtn.updateState();
+               _this.branchbtn.updateState();
                
                //GLib.debug (//"Selection: %s, %s\n", (string) val1, (string) val2);
             });
@@ -613,38 +860,7 @@ public class NewBranch : Object
     }
 
 
-    public class Xcls_Button12 : Object
-    {
-        public Gtk.Button el;
-        private NewBranch  _this;
-
-
-            // my vars (def)
-
-        // ctor
-        public Xcls_Button12(NewBranch _owner )
-        {
-            _this = _owner;
-            this.el = new Gtk.Button();
-
-            // my vars (dec)
-
-            // set gobject values
-            this.el.expand = false;
-            this.el.label = "New Ticket";
-
-            //listeners
-            this.el.clicked.connect( () => {
-                _this.el.response(-1);
-               Ticket.singleton().show(_this.repo);
-            
-            });
-        }
-
-        // user defined functions
-    }
-
-    public class Xcls_Label13 : Object
+    public class Xcls_Label16 : Object
     {
         public Gtk.Label el;
         private NewBranch  _this;
@@ -653,7 +869,7 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Label13(NewBranch _owner )
+        public Xcls_Label16(NewBranch _owner )
         {
             _this = _owner;
             this.el = new Gtk.Label( "Use this as branch name" );
@@ -693,7 +909,7 @@ public class NewBranch : Object
         // user defined functions
     }
 
-    public class Xcls_createbtn : Object
+    public class Xcls_branchbtn : Object
     {
         public Gtk.Button el;
         private NewBranch  _this;
@@ -702,10 +918,10 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_createbtn(NewBranch _owner )
+        public Xcls_branchbtn(NewBranch _owner )
         {
             _this = _owner;
-            _this.createbtn = this;
+            _this.branchbtn = this;
             this.el = new Gtk.Button();
 
             // my vars (dec)
@@ -750,7 +966,7 @@ public class NewBranch : Object
         }
     }
 
-    public class Xcls_Box16 : Object
+    public class Xcls_Box19 : Object
     {
         public Gtk.Box el;
         private NewBranch  _this;
@@ -759,7 +975,7 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Box16(NewBranch _owner )
+        public Xcls_Box19(NewBranch _owner )
         {
             _this = _owner;
             this.el = new Gtk.Box( Gtk.Orientation.HORIZONTAL, 0 );
@@ -773,7 +989,7 @@ public class NewBranch : Object
             var child_1 = new Xcls_btn_closed( _this );
             child_1.ref();
             this.el.add (  child_1.el  );
-            var child_2 = new Xcls_Label19( _this );
+            var child_2 = new Xcls_Label22( _this );
             child_2.ref();
             this.el.add (  child_2.el  );
         }
@@ -841,7 +1057,7 @@ public class NewBranch : Object
         // user defined functions
     }
 
-    public class Xcls_Label19 : Object
+    public class Xcls_Label22 : Object
     {
         public Gtk.Label el;
         private NewBranch  _this;
@@ -850,7 +1066,7 @@ public class NewBranch : Object
             // my vars (def)
 
         // ctor
-        public Xcls_Label19(NewBranch _owner )
+        public Xcls_Label22(NewBranch _owner )
         {
             _this = _owner;
             this.el = new Gtk.Label( "<a href=\"refresh\">Refresh Ticket list</a>" );
@@ -900,6 +1116,7 @@ public class NewBranch : Object
             // set gobject values
             this.el.height_request = 500;
             this.el.vexpand = true;
+            this.el.visible = false;
             var child_0 = new Xcls_view( _this );
             child_0.ref();
             this.el.add (  child_0.el  );
@@ -957,5 +1174,1409 @@ public class NewBranch : Object
     }
 
 
+    public class Xcls_branch_spinner : Object
+    {
+        public Gtk.Spinner el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_branch_spinner(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.branch_spinner = this;
+            this.el = new Gtk.Spinner();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.hexpand = true;
+            this.el.vexpand = true;
+        }
+
+        // user defined functions
+    }
+
+
+    public class Xcls_create_ticket_tab : Object
+    {
+        public Gtk.Box el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_create_ticket_tab(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.create_ticket_tab = this;
+            this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.homogeneous = false;
+            var child_0 = new Xcls_table( _this );
+            child_0.ref();
+            this.el.pack_start (  child_0.el , false,false,0 );
+        }
+
+        // user defined functions
+        public void load_data () {
+         
+               // _this.table.el.hide();
+               //_this.spinner.el.show();
+               //_this.spinner.el.start();     
+               
+            Timeout.add_seconds(1, () => {
+                        
+                       RooProject? curproj = null;
+                       if (_this.repo != null) {
+                               curproj = RooProject.getProjectByRepo(_this.repo);
+                       }
+                       _this.tprmodel.loadProjects(curproj == null ? "" : curproj.id);
+                       if (curproj != null) {
+                
+                               
+                               var rt = RooTicket.singleton();
+                               rt.loadProjectOptions(curproj.id);
+                               
+                               _this.msmodel.loadMilestones();
+                               _this.primodel.loadPriorities();
+                               _this.sevmodel.loadSeverities();
+                               _this.clmodel.loadClassifications();    
+                               _this.devmodel.loadDevelopers();        
+                               
+                       }
+                       _this.summary.el.set_text("");
+                       _this.description.el.buffer.text = ""; 
+                       //_this.spinner.el.stop();
+        //             _this.spinner.el.hide();        
+        
+                       //_this.table.el.show();
+                   //_this.summary.el.grab_focus();
+         
+                       return false;
+               });
+        }
+    }
+    public class Xcls_table : Object
+    {
+        public Gtk.Table el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_table(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.table = this;
+            this.el = new Gtk.Table( 14, 4, true );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.expand = false;
+            this.el.margin = 2;
+            this.el.column_spacing = 4;
+            this.el.vexpand = false;
+            var child_0 = new Xcls_Label28( _this );
+            child_0.ref();
+            this.el.attach_defaults (  child_0.el , 0,1,0,1 );
+            var child_1 = new Xcls_Label29( _this );
+            child_1.ref();
+            this.el.attach_defaults (  child_1.el , 1,2,0,1 );
+            var child_2 = new Xcls_project_id( _this );
+            child_2.ref();
+            this.el.attach_defaults (  child_2.el , 0,1,1,2 );
+            var child_3 = new Xcls_summary( _this );
+            child_3.ref();
+            this.el.attach_defaults (  child_3.el , 1,4,1,2 );
+            var child_4 = new Xcls_Label34( _this );
+            child_4.ref();
+            this.el.attach_defaults (  child_4.el , 0,1,2,3 );
+            var child_5 = new Xcls_milestone_id( _this );
+            child_5.ref();
+            this.el.attach_defaults (  child_5.el , 0,1,3,4 );
+            var child_6 = new Xcls_Label37( _this );
+            child_6.ref();
+            this.el.attach_defaults (  child_6.el , 1,4,2,3 );
+            var child_7 = new Xcls_description( _this );
+            child_7.ref();
+            this.el.attach_defaults (  child_7.el , 1,4,3,12 );
+            var child_8 = new Xcls_Label39( _this );
+            child_8.ref();
+            this.el.attach_defaults (  child_8.el , 0,1,4,5 );
+            var child_9 = new Xcls_priority_id( _this );
+            child_9.ref();
+            this.el.attach_defaults (  child_9.el , 0,1,5,6 );
+            var child_10 = new Xcls_Label42( _this );
+            child_10.ref();
+            this.el.attach_defaults (  child_10.el , 0,1,6,7 );
+            var child_11 = new Xcls_severity_id( _this );
+            child_11.ref();
+            this.el.attach_defaults (  child_11.el , 0,1,7,8 );
+            var child_12 = new Xcls_Label45( _this );
+            child_12.ref();
+            this.el.attach_defaults (  child_12.el , 0,1,8,9 );
+            var child_13 = new Xcls_classification_id( _this );
+            child_13.ref();
+            this.el.attach_defaults (  child_13.el , 0,1,9,10 );
+            var child_14 = new Xcls_Label48( _this );
+            child_14.ref();
+            this.el.attach_defaults (  child_14.el , 0,1,10,11 );
+            var child_15 = new Xcls_developer_id( _this );
+            child_15.ref();
+            this.el.attach_defaults (  child_15.el , 0,1,11,12 );
+            var child_16 = new Xcls_Button51( _this );
+            child_16.ref();
+            this.el.attach_defaults (  child_16.el , 0,4,13,14 );
+        }
+
+        // user defined functions
+    }
+    public class Xcls_Label28 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label28(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Project" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+            this.el.visible = true;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_Label29 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label29(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Summary" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+            this.el.visible = true;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_project_id : Object
+    {
+        public Gtk.ComboBox el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+        public bool loading;
+
+        // ctor
+        public Xcls_project_id(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.project_id = this;
+            this.el = new Gtk.ComboBox.with_entry();
+
+            // my vars (dec)
+            this.loading = false;
+
+            // set gobject values
+            var child_0 = new Xcls_tprcellrenderer( _this );
+            child_0.ref();
+            this.el.pack_start (  child_0.el , true );
+            var child_1 = new Xcls_tprmodel( _this );
+            child_1.ref();
+            this.el.set_model (  child_1.el  );
+
+            // init method
+
+            this.el.set_entry_text_column(1);
+
+            //listeners
+            this.el.changed.connect( () => {
+               if (this.loading) {
+                       return;
+               }
+               var project_id = this.selectedProjectId();
+               
+               var rt = RooTicket.singleton();
+               rt.loadProjectOptions(project_id);
+               
+               _this.msmodel.loadMilestones();
+               _this.primodel.loadPriorities();
+               _this.sevmodel.loadSeverities();
+               _this.clmodel.loadClassifications();    
+               _this.devmodel.loadDevelopers();        
+               
+               // affects projects and milestones..
+               
+               
+               /*if (this.loading) {
+                       return;
+               }
+               var ticket_id = this.selectedTicketId();
+               
+               var name = RooTicket.singleton().usernameLocal();
+               
+               if (ticket_id == "" || ticket_id == null) {
+               
+                       var dt = new  DateTime.now_local();
+                       _this.name.el.set_text("wip_%s_%s".printf(name,dt.format("%Y_%b_%d")));
+                       return;
+               }
+               
+               
+               var ticket = RooTicket.singleton().getById(ticket_id);
+               
+               _this.name.el.set_text("wip_%s_T%s_%s".printf(name,ticket.id, ticket.summaryToBranchName()));
+               
+               //GLib.debug (//"Selection: %s, %s\n", (string) val1, (string) val2);
+               */
+            });
+        }
+
+        // user defined functions
+        public string selectedProjectId () {
+               Gtk.TreeIter iter;
+               Value val1;
+         
+         
+               this.el.get_active_iter (out iter);
+               _this.tprmodel.el.get_value (iter, 0, out val1);
+         
+        
+               return  (string) val1;
+               
+               
+               
+               
+        }
+    }
+    public class Xcls_tprcellrenderer : Object
+    {
+        public Gtk.CellRendererText el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_tprcellrenderer(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.tprcellrenderer = this;
+            this.el = new Gtk.CellRendererText();
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_tprmodel : Object
+    {
+        public Gtk.ListStore el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_tprmodel(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.tprmodel = this;
+            this.el = new Gtk.ListStore( 2, typeof(string),typeof(string) );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+        public void loadProjects (string id) {
+        
+            
+            _this.project_id.loading = true;
+        
+            this.el.clear();                                    
+            Gtk.TreeIter iter;
+            var el = this.el;
+            
+            el.append(out iter);
+        
+            
+            el.set_value(iter, 0, "");
+            el.set_value(iter, 1, "-- select a project --");
+            if (id == "") {
+                   _this.project_id.el.set_active_iter(iter);
+            }
+        
+            foreach(var project in RooProject.projects()) {
+            
+                el.append(out iter);
+                
+                el.set_value(iter, 0, project.id);
+                el.set_value(iter, 1,  project.name );
+                if (id == project.id) {
+                          _this.project_id.el.set_active_iter(iter);
+                   }   
+                
+            }
+            
+            _this.project_id.loading = false;
+             //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          
+                                             
+        }
+    }
+
+
+    public class Xcls_summary : Object
+    {
+        public Gtk.Entry el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_summary(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.summary = this;
+            this.el = new Gtk.Entry();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.visible = true;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_Label34 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label34(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Milestone" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+            this.el.justify = Gtk.Justification.RIGHT;
+            this.el.xalign = 0.900000f;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_milestone_id : Object
+    {
+        public Gtk.ComboBox el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+        public bool loading;
+
+        // ctor
+        public Xcls_milestone_id(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.milestone_id = this;
+            this.el = new Gtk.ComboBox.with_entry();
+
+            // my vars (dec)
+            this.loading = false;
+
+            // set gobject values
+            var child_0 = new Xcls_msmodel( _this );
+            child_0.ref();
+            this.el.set_model (  child_0.el  );
+
+            // init method
+
+            this.el.set_entry_text_column(1);
+        }
+
+        // user defined functions
+        public string selectedMilestoneId () {
+               Gtk.TreeIter iter;
+               Value val1;
+         
+         
+               this.el.get_active_iter (out iter);
+               _this.msmodel.el.get_value (iter, 0, out val1);
+         
+        
+               return  (string) val1;
+               
+               
+               
+               
+        }
+    }
+    public class Xcls_msmodel : Object
+    {
+        public Gtk.ListStore el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_msmodel(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.msmodel = this;
+            this.el = new Gtk.ListStore( 2, typeof(string),typeof(string) );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+        public void loadMilestones ( ) {
+        
+            var rt = RooTicket.singleton();
+           // rt.loadProjects();
+            
+            _this.milestone_id.loading = true;
+        
+            this.el.clear();                                    
+            Gtk.TreeIter iter;
+            var el = this.el;
+            
+            el.append(out iter);
+        
+            
+            el.set_value(iter, 0, "");
+            el.set_value(iter, 1, "-- select a milestone --");
+            _this.milestone_id.el.set_active_iter(iter);    
+             
+            var projects = rt.milestones;
+            foreach(var project in projects) {
+            
+                el.append(out iter);
+                
+                el.set_value(iter, 0, project.id);
+                el.set_value(iter, 1,  project.display_name );
+              //  if (id == project.id) {
+                //        _this.milestone.el.set_active_iter(iter);
+                //   }   
+                
+            }
+            
+            
+            _this.milestone_id.loading = false;
+             //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          
+                                             
+        }
+    }
+
+
+    public class Xcls_Label37 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label37(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Description" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_description : Object
+    {
+        public Gtk.TextView el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_description(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.description = this;
+            this.el = new Gtk.TextView();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.border_width = 1;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_Label39 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label39(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Priority" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+            this.el.xalign = 0.900000f;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_priority_id : Object
+    {
+        public Gtk.ComboBox el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+        public bool loading;
+
+        // ctor
+        public Xcls_priority_id(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.priority_id = this;
+            this.el = new Gtk.ComboBox.with_entry();
+
+            // my vars (dec)
+            this.loading = false;
+
+            // set gobject values
+            var child_0 = new Xcls_primodel( _this );
+            child_0.ref();
+            this.el.set_model (  child_0.el  );
+
+            // init method
+
+            this.el.set_entry_text_column(1);
+        }
+
+        // user defined functions
+        public string selectedPriorityId () {
+               Gtk.TreeIter iter;
+               Value val1;
+         
+         
+               this.el.get_active_iter (out iter);
+               _this.primodel.el.get_value (iter, 0, out val1);
+         
+        
+               return  (string) val1;
+               
+               
+               
+               
+        }
+    }
+    public class Xcls_primodel : Object
+    {
+        public Gtk.ListStore el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_primodel(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.primodel = this;
+            this.el = new Gtk.ListStore( 2, typeof(string),typeof(string) );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+        public void loadPriorities ( ) {
+        
+            var rt = RooTicket.singleton();
+           // rt.loadProjects();
+            
+            _this.priority_id.loading = true;
+        
+            this.el.clear();                                    
+            Gtk.TreeIter iter;
+            var el = this.el;
+            
+            
+           var projects = rt.priorities;
+            foreach(var project in projects) {
+            
+                el.append(out iter);
+                
+                el.set_value(iter, 0, project.id);
+                el.set_value(iter, 1,  project.display_name );
+                if ("normal" == project.name) {
+                          _this.priority_id.el.set_active_iter(iter);
+                   }   
+                
+            }
+            
+            _this.priority_id.loading = false;
+                   
+                                             
+        }
+    }
+
+
+    public class Xcls_Label42 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label42(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Severity" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_severity_id : Object
+    {
+        public Gtk.ComboBox el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+        public bool loading;
+
+        // ctor
+        public Xcls_severity_id(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.severity_id = this;
+            this.el = new Gtk.ComboBox.with_entry();
+
+            // my vars (dec)
+            this.loading = false;
+
+            // set gobject values
+            var child_0 = new Xcls_sevmodel( _this );
+            child_0.ref();
+            this.el.set_model (  child_0.el  );
+
+            // init method
+
+            this.el.set_entry_text_column(1);
+        }
+
+        // user defined functions
+        public string selectedSeverityId () {
+               Gtk.TreeIter iter;
+               Value val1;
+         
+         
+               this.el.get_active_iter (out iter);
+               _this.sevmodel.el.get_value (iter, 0, out val1);
+         
+        
+               return  (string) val1;
+               
+               
+               
+               
+        }
+    }
+    public class Xcls_sevmodel : Object
+    {
+        public Gtk.ListStore el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_sevmodel(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.sevmodel = this;
+            this.el = new Gtk.ListStore( 2, typeof(string),typeof(string) );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+        public void loadSeverities () {
+        
+            var rt = RooTicket.singleton();
+            //rt.loadProjects();
+            
+            _this.severity_id.loading = true;
+        
+            this.el.clear();                                    
+            Gtk.TreeIter iter;
+            var el = this.el;
+             
+            var projects = rt.serverities;
+            foreach(var project in projects) {
+            
+                el.append(out iter);
+                
+                el.set_value(iter, 0, project.id);
+                el.set_value(iter, 1,  project.display_name );
+                if ("normal" == project.name) {
+                          _this.severity_id.el.set_active_iter(iter);
+                   }   
+                
+            }
+           
+            _this.severity_id.loading = false;
+             //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          
+                                             
+        }
+    }
+
+
+    public class Xcls_Label45 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label45(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Classification" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_classification_id : Object
+    {
+        public Gtk.ComboBox el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+        public bool loading;
+
+        // ctor
+        public Xcls_classification_id(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.classification_id = this;
+            this.el = new Gtk.ComboBox.with_entry();
+
+            // my vars (dec)
+            this.loading = false;
+
+            // set gobject values
+            var child_0 = new Xcls_clmodel( _this );
+            child_0.ref();
+            this.el.set_model (  child_0.el  );
+
+            // init method
+
+            this.el.set_entry_text_column(1);
+        }
+
+        // user defined functions
+        public string selectedClassificationId () {
+               Gtk.TreeIter iter;
+               Value val1;
+         
+         
+               this.el.get_active_iter (out iter);
+               _this.clmodel.el.get_value (iter, 0, out val1);
+         
+        
+               return  (string) val1;
+               
+               
+               
+               
+        }
+    }
+    public class Xcls_clmodel : Object
+    {
+        public Gtk.ListStore el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_clmodel(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.clmodel = this;
+            this.el = new Gtk.ListStore( 2, typeof(string),typeof(string) );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+        public void loadClassifications ( ) {
+        
+            var rt = RooTicket.singleton();
+            // rt.loadProjects();
+            
+            _this.classification_id.loading = true;
+        
+            this.el.clear();                                    
+            Gtk.TreeIter iter;
+            var el = this.el;
+            
+            el.append(out iter);
+        
+             
+            var projects = rt.classifications;
+            foreach(var project in projects) {
+            
+                el.append(out iter);
+                
+                el.set_value(iter, 0, project.id);
+                el.set_value(iter, 1,  project.display_name );
+                if ("bug" == project.name) {
+                          _this.classification_id.el.set_active_iter(iter);
+                   }   
+                
+            }
+            
+            _this.classification_id.loading = false;
+             //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          
+                                             
+        }
+    }
+
+
+    public class Xcls_Label48 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label48(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Assign to" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_developer_id : Object
+    {
+        public Gtk.ComboBox el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+        public bool loading;
+
+        // ctor
+        public Xcls_developer_id(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.developer_id = this;
+            this.el = new Gtk.ComboBox.with_entry();
+
+            // my vars (dec)
+            this.loading = false;
+
+            // set gobject values
+            var child_0 = new Xcls_devmodel( _this );
+            child_0.ref();
+            this.el.set_model (  child_0.el  );
+
+            // init method
+
+            this.el.set_entry_text_column(1);
+        }
+
+        // user defined functions
+        public string selectedDeveloperId () {
+               Gtk.TreeIter iter;
+               Value val1;
+         
+         
+               this.el.get_active_iter (out iter);
+               _this.devmodel.el.get_value (iter, 0, out val1);
+         
+        
+               return  (string) val1;
+               
+               
+               
+               
+        }
+    }
+    public class Xcls_devmodel : Object
+    {
+        public Gtk.ListStore el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_devmodel(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.devmodel = this;
+            this.el = new Gtk.ListStore( 2, typeof(string),typeof(string) );
+
+            // my vars (dec)
+
+            // set gobject values
+        }
+
+        // user defined functions
+        public void loadDevelopers ( ) {
+        
+            var rt = RooTicket.singleton();
+            //rt.loadProjects();
+            
+            _this.developer_id.loading = true;
+        
+            this.el.clear();                                    
+            Gtk.TreeIter iter;
+            var el = this.el;
+            
+            el.append(out iter);
+        
+            
+            el.set_value(iter, 0, "");
+            el.set_value(iter, 1, "-- select a developer --");
+          //  if (id == "") {
+                   _this.developer_id.el.set_active_iter(iter);
+           // }
+            
+            var peps = rt.developers;
+            foreach(var p in peps) {
+            
+                el.append(out iter);
+                
+                el.set_value(iter, 0, p.id);
+                el.set_value(iter, 1,  p.display_name );
+                if (rt.authuser_id == p.id) {
+                          _this.developer_id.el.set_active_iter(iter);
+                   }   
+            }
+         
+            _this.developer_id.loading = false;
+             //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          
+                                             
+        }
+    }
+
+
+    public class Xcls_Button51 : Object
+    {
+        public Gtk.Button el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Button51(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Button();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.label = "Create Ticket & Branch";
+
+            // init method
+
+            {
+               this.el.get_style_context().add_class("suggested-action");
+            }
+
+            //listeners
+            this.el.clicked.connect( () => {
+               GLib.debug("fire response = 1");
+               
+               
+               var invalid = false;
+               
+               // validate first...
+               _this.project_id.el.get_child().get_style_context().remove_class("warning");    
+               if (_this.project_id.selectedProjectId() == "") {
+                       _this.project_id.el.get_child().get_style_context().add_class("warning");
+                       invalid = true;
+               }
+               
+               _this.milestone_id.el.get_child().get_style_context().remove_class("warning");  
+            
+               _this.priority_id.el.get_child().get_style_context().remove_class("warning");   
+               if (_this.priority_id.selectedPriorityId() == "") {
+                       _this.priority_id.el.get_child().get_style_context().add_class("warning");
+                       invalid = true;
+               }
+               
+               _this.classification_id.el.get_child().get_style_context().remove_class("warning");     
+               if (_this.classification_id.selectedClassificationId() == "") {
+                       _this.classification_id.el.get_child().get_style_context().add_class("warning");
+                       invalid = true;
+               }
+               
+               _this.developer_id.el.get_child().get_style_context().remove_class("warning");  
+               if (_this.developer_id.selectedDeveloperId() == "") {
+                       _this.developer_id.el.get_child().get_style_context().add_class("warning");
+                       invalid = true;
+               }
+               
+               _this.summary.el.get_style_context().remove_class("warning");   
+               if (_this.summary.el.get_text() == "") {
+                       _this.summary.el.get_style_context().add_class("warning");
+                       invalid = true;
+               }
+               
+               _this.description.el.get_style_context().remove_class("warning");       
+             
+               if (invalid) {
+                       return;
+               }
+               GLib.debug("for is valid");
+               
+               _this.el.response(2);
+            });
+        }
+
+        // user defined functions
+    }
+
+
+
+    public class Xcls_quick_commit_tab : Object
+    {
+        public Gtk.Box el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_quick_commit_tab(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.quick_commit_tab = this;
+            this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.homogeneous = false;
+            var child_0 = new Xcls_Table53( _this );
+            child_0.ref();
+            this.el.pack_start (  child_0.el , false,false,0 );
+            var child_1 = new Xcls_diff_sv( _this );
+            child_1.ref();
+            this.el.add (  child_1.el  );
+        }
+
+        // user defined functions
+        public void load_data () {
+        
+          _this.createbtn.updateState();
+        }
+    }
+    public class Xcls_Table53 : Object
+    {
+        public Gtk.Table el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Table53(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Table( 3, 5, true );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.expand = false;
+            this.el.margin = 2;
+            this.el.column_spacing = 4;
+            this.el.vexpand = false;
+            var child_0 = new Xcls_Label54( _this );
+            child_0.ref();
+            this.el.attach_defaults (  child_0.el , 0,1,0,1 );
+            var child_1 = new Xcls_commit_message( _this );
+            child_1.ref();
+            this.el.attach_defaults (  child_1.el , 0,5,1,2 );
+            var child_2 = new Xcls_createbtn( _this );
+            child_2.ref();
+            this.el.attach_defaults (  child_2.el , 0,5,2,3 );
+        }
+
+        // user defined functions
+    }
+    public class Xcls_Label54 : Object
+    {
+        public Gtk.Label el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_Label54(NewBranch _owner )
+        {
+            _this = _owner;
+            this.el = new Gtk.Label( "Just commit with this comment" );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.halign = Gtk.Align.START;
+            this.el.justify = Gtk.Justification.RIGHT;
+            this.el.xalign = 0.900000f;
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_commit_message : Object
+    {
+        public Gtk.Entry el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_commit_message(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.commit_message = this;
+            this.el = new Gtk.Entry();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.visible = true;
+
+            //listeners
+            this.el.key_release_event.connect( () => { 
+            
+               _this.createbtn.updateState();
+               return true;
+            });
+        }
+
+        // user defined functions
+    }
+
+    public class Xcls_createbtn : Object
+    {
+        public Gtk.Button el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_createbtn(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.createbtn = this;
+            this.el = new Gtk.Button();
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.label = "Commit Changes";
+
+            // init method
+
+            {
+               this.el.get_style_context().add_class("suggested-action");
+            }
+
+            //listeners
+            this.el.clicked.connect( () => {
+            
+               GLib.debug("fire response = 1");
+               
+                
+                
+               _this.el.response(3);
+            });
+        }
+
+        // user defined functions
+        public void updateState () {
+        
+               var msg = _this.commit_message.el.get_text();
+               
+               if (msg == "") {
+                       this.el.set_sensitive(false);
+                       return;
+               }
+         
+               this.el.set_sensitive(true);
+         
+        }
+    }
+
+
+    public class Xcls_diff_sv : Object
+    {
+        public Gtk.ScrolledWindow el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_diff_sv(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.diff_sv = this;
+            this.el = new Gtk.ScrolledWindow( null, null );
+
+            // my vars (dec)
+
+            // set gobject values
+            this.el.height_request = 400;
+            this.el.vexpand = true;
+            this.el.visible = false;
+            var child_0 = new Xcls_diff_view( _this );
+            child_0.ref();
+            this.el.add (  child_0.el  );
+        }
+
+        // user defined functions
+    }
+    public class Xcls_diff_view : Object
+    {
+        public Gtk.SourceView el;
+        private NewBranch  _this;
+
+
+            // my vars (def)
+
+        // ctor
+        public Xcls_diff_view(NewBranch _owner )
+        {
+            _this = _owner;
+            _this.diff_view = this;
+            this.el = new Gtk.SourceView();
+
+            // my vars (dec)
+
+            // init method
+
+            var description =   Pango.FontDescription.from_string("monospace");
+                description.set_size(9000);
+                this.el.override_font(description);
+                 var lm = Gtk.SourceLanguageManager.get_default();
+                                
+                ((Gtk.SourceBuffer)(this.el.get_buffer())).set_language(
+                    lm.get_language("diff")
+                );
+        }
+
+        // user defined functions
+    }
+
+
+
 
 }
index 2b996ec..13510bf 100644 (file)
@@ -35,8 +35,8 @@
        "items" : [
         {
          "Gtk.ToolbarStyle toolbar_style" : "Gtk.ToolbarStyle.BOTH_HORIZ",
-         "xtype" : "Toolbar",
          "* pack" : "add",
+         "xtype" : "Toolbar",
          "$ xns" : "Gtk",
          "items" : [
           {
        "items" : [
         {
          "id" : "label_status",
-         "* pack" : false,
          "xtype" : "Label",
+         "* pack" : false,
          "$ xns" : "Gtk",
          "utf8 label" : "Status"
         },
         {
          "id" : "label_diff",
-         "xtype" : "Label",
          "* pack" : false,
+         "xtype" : "Label",
          "$ xns" : "Gtk",
          "utf8 label" : "Diff"
         },
          "items" : [
           {
            "int height_request" : 400,
-           "* pack" : "pack_start,true,true,0",
            "xtype" : "ScrolledWindow",
+           "* pack" : "pack_start,true,true,0",
            "$ xns" : "Gtk",
            "items" : [
             {
        "items" : [
         {
          "Gtk.ToolbarStyle toolbar_style" : "Gtk.ToolbarStyle.BOTH_HORIZ",
-         "* pack" : "add",
          "xtype" : "Toolbar",
+         "* pack" : "add",
          "$ xns" : "Gtk",
          "items" : [
           {
index d6b34d1..7a2500a 100644 (file)
@@ -195,7 +195,7 @@ public class StatusIconA : StatusIcon {
                        this.remove(m);
                }
                foreach(var r in GitRepo.singleton().cache.values ) {
-                       GLib.debug("checking %s for branch = %s", r.name, r.currentBranch.name);
+                       GLib.debug("checking %s for branch = %s", r.name, r.getCurrentBranch().name);
                        if (r.is_master_branch()) {
                                continue;
                                }
@@ -306,47 +306,7 @@ public class StatusIconA : StatusIcon {
                 this.activate.connect( () => {
                     
                     this.pullAll();
-                    /*
-                    GitMonitor.gitmonitor.stop();
-                    var tr = GitRepo.list();
-                    
-                    
-                    
-                    for (var i= 0; i< tr.length;i++) {
-                        statusicon.set_from_stock( 
-                               i%2 == 0 ?  Gtk.Stock.FULLSCREEN : Gtk.Stock.LEAVE_FULLSCREEN );
-                                
-                        var repo = tr.index(i);
-                        //if (!repo.autocommit()) {
-                            //??? should we ignore ones not on autocommit..
-                        //    continue;
-                        //}
-                        try {
-                            statusicon.set_tooltip_text("pull: " + repo.name);
-                            var str = repo.pull();
-                                    // do not care if it's already in sycn..
-                            if (Regex.match_simple ("Already up-to-date", str) ) {
-                                continue;
-                            }
-                            var notification = new Notify.Notification( 
-                                     "Updated " + repo.name,
-                                     str,
-                                       "dialog-information"
-                                   
-                            );
-                        
-                            notification.set_timeout(20);
-                            notification.show();
-                                     
-                        } catch(Error e) {
-                            print("notification or push errror- probably to many in queue..");
-                            statusicon.set_from_stock( Gtk.Stock.MEDIA_RECORD );
-                            print(e.message);
-                            
-                        }        
-
-                    } 
-                    */
+                   
                            
                            
                 });
index 23302dc..2993614 100644 (file)
@@ -17,7 +17,7 @@
    "title" : "Create a Ticket",
    "xtype" : "Dialog",
    "# GitRepo? repo" : "null",
-   "|   void show" : "( GitRepo? repo   ) \n{\n     // this.el.set_gravity(Gdk.Gravity.NORTH);\n    if (this.running) { // should not happen!!\n    \tGLib.error(\"new branch show called, when already being displayed?\");\n\t}\n \tthis.running  = true;\n \n \t_this.el.show_all();\n\t\n\t_this.table.el.hide();\n\n\t_this.spinner.el.show();\n\t_this.spinner.el.start();\t\n\tthis.el.set_keep_above(true);    \n\tthis.el.move((Gdk.Screen.width() / 2)- 250 ,0);\n\tthis.el.set_default_size( 500,200); // not sure why it grows..\n\t\n\tGLib.debug(\"Showing dialog?\"); \n    Timeout.add_seconds(1, () => {\n\t\t\n\t\t \n\t\t//GitMonitor.gitmonitor.stop();\n\t\t\n\t\tthis.repo = repo;\n\t\t\n\t\t \n\t\tRooProject? curproj = null;\n\t\tif (this.repo != null) {\n\t\t\tcurproj = RooProject.getProjectByRepo(this.repo);\n\t\t}\n\t\t_this.prmodel.loadProjects(curproj == null ? \"\" : curproj.id);\n\t\tif (curproj != null) {\n\t \n\t\t\t\n\t\t\tvar rt = RooTicket.singleton();\n\t\t\trt.loadProjectOptions(curproj.id);\n\t\t\t\n\t\t\t_this.msmodel.loadMilestones();\n\t\t\t_this.primodel.loadPriorities();\n\t\t\t_this.sevmodel.loadSeverities();\n\t\t\t_this.clmodel.loadClassifications();\t\n\t\t\t_this.devmodel.loadDevelopers();\t\n\t\t\t\n\t\t}\n\t\t_this.summary.el.set_text(\"\");\n\t\t_this.description.el.buffer.text = \"\"; \n\t\t_this.spinner.el.stop();\n\t\t_this.spinner.el.hide();\t\n\n\t\tthis.table.el.show();\n\t    _this.summary.el.grab_focus();\n \n\t \treturn false;\n \t});\n \tthis.el.run();\n \t\n\n}",
+   "|   void show" : "( GitRepo? repo   ) \n{\n     // this.el.set_gravity(Gdk.Gravity.NORTH);\n    if (this.running) { // should not happen!!\n    \tGLib.error(\"new branch show called, when already being displayed?\");\n\t}\n \tthis.running  = true;\n \n \t_this.el.show_all();\n\t\n\t_this.table.el.hide();\n\n\t_this.spinner.el.show();\n\t_this.spinner.el.start();\t\n\tthis.el.set_keep_above(true);    \n\tthis.el.move((Gdk.Screen.width() / 2)- 250 ,0);\n\tthis.el.set_default_size( 500,100); // not sure why it grows..\n\t\n\tGLib.debug(\"Showing dialog?\"); \n    Timeout.add_seconds(1, () => {\n\t\t\n\t\t \n\t\t//GitMonitor.gitmonitor.stop();\n\t\t\n\t\tthis.repo = repo;\n\t\t\n\t\t \n\t\tRooProject? curproj = null;\n\t\tif (this.repo != null) {\n\t\t\tcurproj = RooProject.getProjectByRepo(this.repo);\n\t\t}\n\t\t_this.prmodel.loadProjects(curproj == null ? \"\" : curproj.id);\n\t\tif (curproj != null) {\n\t \n\t\t\t\n\t\t\tvar rt = RooTicket.singleton();\n\t\t\trt.loadProjectOptions(curproj.id);\n\t\t\t\n\t\t\t_this.msmodel.loadMilestones();\n\t\t\t_this.primodel.loadPriorities();\n\t\t\t_this.sevmodel.loadSeverities();\n\t\t\t_this.clmodel.loadClassifications();\t\n\t\t\t_this.devmodel.loadDevelopers();\t\n\t\t\t\n\t\t}\n\t\t_this.summary.el.set_text(\"\");\n\t\t_this.description.el.buffer.text = \"\"; \n\t\t_this.spinner.el.stop();\n\t\t_this.spinner.el.hide();\t\n\n\t\tthis.table.el.show();\n\t    _this.summary.el.grab_focus();\n \n\t \treturn false;\n \t});\n \tthis.el.run();\n \t\n\n}",
    "default_height" : 200,
    "$ xns" : "Gtk",
    "# bool running" : false,
@@ -64,8 +64,8 @@
           "changed" : "() => {\n\tif (this.loading) {\n\t\treturn;\n\t}\n\tvar project_id = this.selectedProjectId();\n\t\n\tvar rt = RooTicket.singleton();\n\trt.loadProjectOptions(project_id);\n\t\n\t_this.msmodel.loadMilestones();\n\t_this.primodel.loadPriorities();\n\t_this.sevmodel.loadSeverities();\n\t_this.clmodel.loadClassifications();\t\n\t_this.devmodel.loadDevelopers();\t\n\t\n\t// affects projects and milestones..\n\t\n\t\n\t/*if (this.loading) {\n\t\treturn;\n\t}\n\tvar ticket_id = this.selectedTicketId();\n\t\n\tvar name = RooTicket.singleton().usernameLocal();\n\t\n\tif (ticket_id == \"\" || ticket_id == null) {\n\t\n\t\tvar dt = new  DateTime.now_local();\n\t\t_this.name.el.set_text(\"wip_%s_%s\".printf(name,dt.format(\"%Y_%b_%d\")));\n\t\treturn;\n\t}\n\t\n\t\n\tvar ticket = RooTicket.singleton().getById(ticket_id);\n   \n\t_this.name.el.set_text(\"wip_%s_T%s_%s\".printf(name,ticket.id, ticket.summaryToBranchName()));\n\t\n\t//GLib.debug (//\"Selection: %s, %s\\n\", (string) val1, (string) val2);\n\t*/\n}"
          },
          "* ctor" : "new Gtk.ComboBox.with_entry()",
-         "id" : "project_id",
          "| string selectedProjectId" : "() {\n\tGtk.TreeIter iter;\n\tValue val1;\n \n \n\tthis.el.get_active_iter (out iter);\n\t_this.prmodel.el.get_value (iter, 0, out val1);\n \n\n\treturn  (string) val1;\n\t\n\t\n\t\n\t\n}\n",
+         "id" : "project_id",
          "* init" : "this.el.set_entry_text_column(1);",
          "* pack" : "attach_defaults,0,1,1,2",
          "xtype" : "ComboBox",
@@ -74,8 +74,8 @@
          "items" : [
           {
            "id" : "prcellrenderer",
-           "xtype" : "CellRendererText",
            "* pack" : "pack_start,true",
+           "xtype" : "CellRendererText",
            "$ xns" : "Gtk"
           },
           {
          "items" : [
           {
            "id" : "msmodel",
-           "* pack" : "set_model",
            "xtype" : "ListStore",
+           "* pack" : "set_model",
            "| void loadMilestones" : "  ( ) {\n\n    var rt = RooTicket.singleton();\n   // rt.loadProjects();\n    \n    _this.milestone_id.loading = true;\n\n    this.el.clear();                                    \n    Gtk.TreeIter iter;\n    var el = this.el;\n    \n    el.append(out iter);\n\n    \n    el.set_value(iter, 0, \"\");\n    el.set_value(iter, 1, \"-- select a milestone --\");\n    _this.milestone_id.el.set_active_iter(iter);    \n     \n    var projects = rt.milestones;\n    foreach(var project in projects) {\n    \n        el.append(out iter);\n        \n        el.set_value(iter, 0, project.id);\n        el.set_value(iter, 1,  project.display_name );\n      //  if (id == project.id) {\n\t //\t   _this.milestone.el.set_active_iter(iter);\n\t //   }   \n        \n    }\n    \n    \n    _this.milestone_id.loading = false;\n     //this.el.set_sort_column_id(0, Gtk.SortType.ASCENDING);          \n                                     \n}\n",
            "$ columns" : "typeof(string),typeof(string)",
            "n_columns" : 2,
         },
         {
          "id" : "description",
-         "* pack" : "attach_defaults,1,4,3,12",
          "xtype" : "TextView",
+         "* pack" : "attach_defaults,1,4,3,12",
          "$ xns" : "Gtk",
          "uint border_width" : 1
         },
          "items" : [
           {
            "id" : "devmodel",
-           "* pack" : "set_model",
            "xtype" : "ListStore",
+           "* pack" : "set_model",
            "$ columns" : "typeof(string),typeof(string)",
            "n_columns" : 2,
            "$ xns" : "Gtk",
index 04d431c..8154ad7 100644 (file)
@@ -110,7 +110,7 @@ public class Ticket : Object
        _this.spinner.el.start();       
        this.el.set_keep_above(true);    
        this.el.move((Gdk.Screen.width() / 2)- 250 ,0);
-       this.el.set_default_size( 500,200); // not sure why it grows..
+       this.el.set_default_size( 500,100); // not sure why it grows..
        
        GLib.debug("Showing dialog?"); 
         Timeout.add_seconds(1, () => {
diff --git a/c/push.c.vala b/c/push.c.vala
new file mode 100644 (file)
index 0000000..e69de29
index 8c01d09..4e575df 100644 (file)
@@ -5,7 +5,6 @@
         "execute_args" : "-g",
         "target_bin" : "/tmp/gitlive",
         "sources" : [
-            "..//gitlive/Gitlive.vala",
             "..//gitlive/GitMonitor.vala",
             "..//gitlive/GitRepo.vala",
             "..//gitlive/Monitor.vala",
@@ -23,7 +22,9 @@
             "..//gitlive/Clone.vala",
             "..//gitlive/Ticket.vala",
             "..//gitlive/RooProject.vala",
-            "..//gitlive/RooRepo.vala"
+            "..//gitlive/RooRepo.vala",
+            "..//gitlive/Git.vala",
+            "..//gitlive/GitCallbacks.vala"
         ],
         "packages" : [
         ]
@@ -34,7 +35,8 @@
         "execute_args" : "",
         "target_bin" : "",
         "sources" : [
-            "..//gitlive"
+            "..//gitlive",
+            "/c"
         ],
         "packages" : [
             "libcanberra",
@@ -48,7 +50,8 @@
             "json-glib-1.0",
             "libsoup-2.4",
             "gtksourceview-3.0",
-            "webkit2gtk-4.0"
+            "webkit2gtk-4.0",
+            "libgit2-glib-1.0"
         ]
     }
 ]
\ No newline at end of file
index 935d4c0..9acf793 100644 (file)
@@ -32,7 +32,8 @@ PKG_CHECK_MODULES(GITLIVE, [
         webkit2gtk-4.0
          libcanberra
          libsoup-2.4 >= 2.56.0     
-                json-glib-1.0    
+         json-glib-1.0  
+           libgit2-glib-1.0 
 ])
 
 PKG_CHECK_MODULES([XSCRNSAVER], xscrnsaver)