StatusIcon.vala
[gitlive] / StatusIcon.vala
1 /**
2  * Status icon and menu for component of gitlive.
3  * 
4  * Implements XObject - however we want to control initialization.
5  * 
6  * 
7  * 
8  * Currently only does a few things
9  * a) Quit
10  * 
11  * b) Pause!??!
12  */
13    
14 // Compile::
15 // valac --pkg gtk+-3.0 StatusIcon.vala -o /tmp/StatusIcon
16    
17 //var gitlive = imports.gitlive;
18
19
20 using Gtk;
21 /*
22
23 static int main (string[] args) {
24     // A reference to our file
25     Gtk.init (ref args);
26     new StatusIconA();
27  
28     Gtk.main ();
29     return 0;
30      
31
32 }
33  */
34
35
36 //public StatusIconA statusicon;
37  
38 public class StatusIconA : StatusIcon {
39
40     public bool paused = false;
41     public static StatusIconA statusicon;
42  
43     
44     public StatusIconA() {
45         
46         statusicon = this;
47         
48          //title : 'gitlive',
49         this.stock = Gtk.Stock.REFRESH;
50         this.tooltip_text = "GitLive";
51         this.title = "gitlive";
52         
53         this.set_name("gitlive");
54         this.set_visible(true);      
55         
56         var menu = new GitliveMenu();
57         menu.ref();       
58                 this.button_press_event.connect( ( ev ) =>{
59               print("button press event called\n");
60                         menu.updateMerges();
61             menu.show_all();
62             
63             if (this.paused) {
64                 menu.resume.show();
65                 menu.pause.hide();
66             } else {
67                 menu.resume.hide();
68                 menu.pause.show();
69             }
70               //                public void popup (Gtk.Widget? parent_menu_shell, Gtk.Widget? parent_menu_item,
71                     // [CCode (scope = "async")] Gtk.MenuPositionFunc? func, uint button, uint32 activate_time);
72             //Gtk.get_current_event_device ()
73             menu.popup(
74
75                         null, null,
76                        this.position_menu,
77                        
78                     ev.button,  ev.time //   time
79             );
80               
81               return true;
82             
83             });
84        this.popup_menu.connect( (  button,   time) =>{
85        //this.button_press_event.connect( (  ) =>{
86  
87             //print(Array.prototype.slice.call(arguments).join(','));
88             print("menu activiate called\n");
89             //var menu = this.get('menu');
90             
91             menu.show_all();
92             
93             if (this.paused) {
94                 menu.resume.show();
95                 menu.pause.hide();
96             } else {
97                 menu.resume.hide();
98                 menu.pause.show();
99             }
100               //                public void popup (Gtk.Widget? parent_menu_shell, Gtk.Widget? parent_menu_item,
101                     // [CCode (scope = "async")] Gtk.MenuPositionFunc? func, uint button, uint32 activate_time);
102             //Gtk.get_current_event_device ()
103             menu.popup(
104
105                         null, null,
106                        this.position_menu,
107                        
108                     button,  time //   time
109             );
110                         
111             
112             //var g = { };
113             //var a = new Gdk.Rectangle();
114             //  needs direction=inout setting in gir to work (in bugzilla @present)
115             //this.el.get_geometry(g,a,null);
116              
117             // should check to see if @ top or bottom I guess..
118             //menu.el.get_toplevel().move(a.x, a.y +a.height);
119             //menu.el.get_toplevel().move(10,10);
120             //return false;
121               
122         }); 
123         
124     }
125     
126     public void pause()
127     {
128                 this.set_from_stock( Gtk.Stock.MEDIA_PAUSE );
129                 this.paused = true;
130     }
131     
132     public void resume()
133     {
134                 this.set_from_stock( Gtk.Stock.MEDIA_PLAY );
135                 this.paused = false;
136     }
137     
138     public void refreshing()
139     {
140                 this.set_from_stock( Gtk.Stock.REFRESH );
141     }
142     
143     public void pauseError()
144     {
145                  this.paused = true;
146                  var flag = true;
147                  Timeout.add_full(Priority.LOW, 500, () => {
148                  
149                         if (!this.paused) {
150                                 return false;
151                         }
152                         this.set_from_stock( flag == true ? Gtk.Stock.MEDIA_RECORD  
153                                         : Gtk.Stock.MEDIA_PAUSE);
154                         flag = !flag;
155                         return true;
156                 });
157                  
158     }
159     
160     class GitliveMenu : Gtk.Menu
161     {
162         public ImageMenuItem pause;
163         public ImageMenuItem resume;
164         public Gtk.MenuItem before_seperator;
165         public Gtk.MenuItem after_seperator;        
166         
167         
168         public GitliveMenu()
169         {
170             this.pause = new MenuItemPause();
171             this.append(this.pause);
172             this.resume = new MenuItemStartCommits();
173             this.append(this.resume);
174             this.append(new MenuItemPullAll());
175             this.before_seperator = new Gtk.SeparatorMenuItem();
176             this.append(this.before_seperator);
177
178             this.after_seperator = new Gtk.SeparatorMenuItem();
179             this.append(this.after_seperator);
180             //this.append(new MenuItemUpdateTimesheet());            
181             this.append(new MenuItemManageClones());
182             this.append(new MenuItemAbout());
183             this.append(new MenuItemQuit());
184             this.merge_items = new  Gee.ArrayList<Gtk.MenuItem>();
185         }
186         public Gee.ArrayList<Gtk.MenuItem> merge_items;
187         
188         
189         public void updateMerges()
190         {
191                 // show a list of possible merges on the menu.
192                 foreach (var m in this.merge_items) {
193                         this.remove(m);
194                 }
195                 foreach(var r in GitRepo.singleton().cache.values ) {
196                         GLib.log("checking r.name for branches");
197                         if (!r.is_wip_branch()) {
198                                 continue;
199                                 }
200                         GLib.log("checking  for activeTicket");                         
201                                 var t = r.activeTicket;
202                                 if (t == null) { 
203                                         continue;
204                                 }
205                                 var mi = new MergeMenuItem(r,t);
206                                 this.insert (mi,4); //backwards..                               
207                                  
208                 }
209                 
210         }
211         
212         
213         class MergeMenuItem : Gtk.MenuItem {        
214         
215                 GitRepo repo;
216                 RooTicket ticket;
217         
218                 public MergeMenuItem(GitRepo r, RooTicket t)
219                 {
220                         this.repo = r;
221                         this.ticket = t;
222                         
223                         this.label = ("Merge [%s] #%s %s".printf(r.name, t.id , t.summary));
224
225                                 this.activate.connect(() => {
226                                         // show merge dialog..
227                                 });
228                 
229                 }
230                 
231         }
232         
233         
234         class MenuItemPause : ImageMenuItem {
235             
236             public MenuItemPause()
237             {
238                 //this.set_from_stock( Gtk.Stock.MEDIA_PAUSE );
239                 
240                 var  image = new Gtk.Image();
241                 image.set_from_stock(Gtk.Stock.MEDIA_PAUSE,Gtk.IconSize.MENU );
242                 this.set_image (image);
243                 
244                 this.label= "Pause Commits";
245                 this.always_show_image = true;
246                 this.accel_group = null;
247                 
248                 this.activate.connect( () => {
249                     statusicon.paused = true;
250                     GitMonitor.gitmonitor.stop();
251
252                    // this.el.label  = status ? 'Resume' : 'Pause';
253                     statusicon.set_from_stock( Gtk.Stock.MEDIA_PAUSE );
254                     
255                     
256                 });
257                 //    id : 'pause',
258             }
259             
260             
261         }
262         class MenuItemStartCommits : ImageMenuItem {
263             
264             public MenuItemStartCommits()
265             {
266                 
267                 var  image = new Gtk.Image();
268                 image.set_from_stock(Gtk.Stock.MEDIA_PLAY,Gtk.IconSize.MENU );
269                 this.set_image (image);
270                 this.label= "Start Commits";
271                 this.always_show_image = true;
272                 this.accel_group = null;
273                 
274                 this.activate.connect( () => {
275                     GitMonitor.gitmonitor.start();
276                     statusicon.paused = false;
277                     
278                     //
279                    // this.el.label  = status ? 'Resume' : 'Pause';
280                     statusicon.set_from_stock( Gtk.Stock.MEDIA_PLAY );
281                     
282                     
283                 });
284             }
285             
286             
287         }
288         
289         
290         class MenuItemPullAll : ImageMenuItem {
291             
292             public MenuItemPullAll()
293             {
294                 
295                 var  image = new Gtk.Image();
296                 image.set_from_stock(Gtk.Stock.FULLSCREEN,Gtk.IconSize.MENU );
297                 this.set_image (image);
298                 this.label= "Pull (Refresh) All";
299                 this.always_show_image = true;
300                 this.accel_group = null;
301                 
302                 this.activate.connect( () => {
303                     
304                     this.pullAll();
305                     /*
306                     GitMonitor.gitmonitor.stop();
307                     var tr = GitRepo.list();
308                     
309                     
310                     
311                     for (var i= 0; i< tr.length;i++) {
312                         statusicon.set_from_stock( 
313                                 i%2 == 0 ?  Gtk.Stock.FULLSCREEN : Gtk.Stock.LEAVE_FULLSCREEN );
314                                 
315                         var repo = tr.index(i);
316                         //if (!repo.autocommit()) {
317                             //??? should we ignore ones not on autocommit..
318                         //    continue;
319                         //}
320                         try {
321                             statusicon.set_tooltip_text("pull: " + repo.name);
322                             var str = repo.pull();
323                                     // do not care if it's already in sycn..
324                             if (Regex.match_simple ("Already up-to-date", str) ) {
325                                 continue;
326                             }
327                             var notification = new Notify.Notification( 
328                                      "Updated " + repo.name,
329                                      str,
330                                        "dialog-information"
331                                    
332                             );
333                         
334                             notification.set_timeout(20);
335                             notification.show();
336                                      
337                         } catch(Error e) {
338                             print("notification or push errror- probably to many in queue..");
339                             statusicon.set_from_stock( Gtk.Stock.MEDIA_RECORD );
340                             print(e.message);
341                             
342                         }        
343
344                     } 
345                     */
346                            
347                            
348                 });
349             }
350             void pullAll()
351             {
352                         var tr = GitRepo.list();
353                 
354                 GitMonitor.gitmonitor.stop();
355                     
356                 
357                this.total = tr.length;
358                 this.has_error = 0;
359                 this.pull_all_error_message = "";
360                 for (var i= 0; i< tr.length;i++) {
361                     statusicon.set_from_stock( 
362                                 i%2 == 0 ?  Gtk.Stock.FULLSCREEN : Gtk.Stock.LEAVE_FULLSCREEN );
363                             
364                     var repo = tr.index(i);
365                     //repo.ref();
366                     //this.ref();
367                     
368                     statusicon.set_tooltip_text("pull: " + repo.name);
369                                         
370                     repo.pull_async(this.pullAllCallback); 
371                                 // do not care if it's already in sycn..
372                         
373                      
374
375                 } 
376
377                   
378         
379         
380                 }
381                 uint total = 0; 
382                         uint has_error = 0;
383                         string pull_all_error_message = "";
384                 
385                 void pullAllCallback(GitRepo repo, int err, string res)
386                 {
387                         this.total--;
388                         
389                         if (err > 0) {
390                                 this.has_error = 1;
391                                 this.pull_all_error_message += this.pull_all_error_message.length > 0 ? "\n" : "";
392                                 this.pull_all_error_message += "Error Pulling " + repo.name +"\n" + res;
393                         }
394                         
395                         if (!Regex.match_simple ("Already up-to-date", res) ) {
396                         var notification = new Notify.Notification( 
397                          "Pull completed ",
398                           "Updated: " +repo.name + "\n" + res +"\n",
399                              "dialog-information"
400                     );
401                     notification.set_timeout(20);
402                                 notification.show();
403                         
404  
405  
406                         }
407                         if (this.total < 1) {
408                                 if (this.has_error > 0) {
409                                         GitMonitor.gitmonitor.pauseError(this.pull_all_error_message);
410                                         return;
411                                 }
412                         
413                         statusicon.set_tooltip_text("Gitlive");
414                   
415                                 GitMonitor.gitmonitor.start();
416                                 //this.unref();
417                                 //repo.unref();
418                         }
419                         
420                 }
421         
422             
423         }
424         
425         
426         class MenuItemUpdateTimesheet : ImageMenuItem {
427             
428             public MenuItemUpdateTimesheet()
429             {
430                 
431                 var  image = new Gtk.Image();
432                 image.set_from_stock(Gtk.Stock.SAVE,Gtk.IconSize.MENU );
433                 this.set_image (image);
434                 this.label= "Update Timesheet";
435                 this.always_show_image = true;
436                 this.accel_group = null;
437                 
438                 this.activate.connect( () => {
439                  //var ret = imports.FixBug.FixBug.show();
440                 });
441             }
442             
443             
444         }
445         
446         class MenuItemManageClones : ImageMenuItem {
447             
448             public MenuItemManageClones()
449             {
450                 
451                 var  image = new Gtk.Image();
452                 image.set_from_stock(Gtk.Stock.FULLSCREEN,Gtk.IconSize.MENU );
453                 this.set_image (image);
454                 this.label= "Manage Clones";
455                 this.always_show_image = true;
456                 this.accel_group = null;
457                 
458                 this.activate.connect( () => {
459                       Clones.singleton().show();
460                 });
461             }
462             
463             
464         }
465         
466         class MenuItemAbout : ImageMenuItem {
467             
468             public MenuItemAbout()
469             {
470                 
471                 var  image = new Gtk.Image();
472                 image.set_from_stock(Gtk.Stock.ABOUT,Gtk.IconSize.MENU );
473                 this.set_image (image);
474                 this.label= "About Gitlive";
475                 this.always_show_image = true;
476                 this.accel_group = null;
477                 
478                 this.activate.connect( () => {
479                  //var ret = imports.Clones.Clones.show();
480                  
481                     var msg = new Gtk.AboutDialog();
482                     msg.program_name = "Git Live";
483                     msg.version= "0.3";
484                     msg.website= "http://www.roojs.org/index.php/projects/gitlive.html";
485                     msg.website_label= "Roo J Solutions Ltd.";
486                     msg.license = "LGPL";
487                     msg.authors = { "Alan Knowles <alan@roojs.com>" };
488                     msg.run();
489                     msg.destroy();
490                 });
491             }
492             
493             
494         }
495         
496          class MenuItemQuit : ImageMenuItem {
497             
498             public MenuItemQuit()
499             {
500                 
501                 var  image = new Gtk.Image();
502                 image.set_from_stock(Gtk.Stock.QUIT,Gtk.IconSize.MENU );
503                 this.set_image (image);
504                 this.label= "Quit";
505                 this.always_show_image = true;
506                 this.accel_group = null;
507                 
508                 this.activate.connect( () => {
509                     // confirm?
510                     Gtk.main_quit();
511                  //var ret = imports.Clones.Clones.show();
512                  });
513             }
514             
515             
516         }
517         
518     }
519 }
520       
521                 
522