d2154e0cd1d25495f261b7cb1d9f039da7110b27
[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                         menu.updateMerges();
90             //var menu = this.get('menu');
91             
92             menu.show_all();
93             
94             if (this.paused) {
95                 menu.resume.show();
96                 menu.pause.hide();
97             } else {
98                 menu.resume.hide();
99                 menu.pause.show();
100             }
101               //                public void popup (Gtk.Widget? parent_menu_shell, Gtk.Widget? parent_menu_item,
102                     // [CCode (scope = "async")] Gtk.MenuPositionFunc? func, uint button, uint32 activate_time);
103             //Gtk.get_current_event_device ()
104             menu.popup(
105
106                         null, null,
107                        this.position_menu,
108                        
109                     button,  time //   time
110             );
111                         
112             
113             //var g = { };
114             //var a = new Gdk.Rectangle();
115             //  needs direction=inout setting in gir to work (in bugzilla @present)
116             //this.el.get_geometry(g,a,null);
117              
118             // should check to see if @ top or bottom I guess..
119             //menu.el.get_toplevel().move(a.x, a.y +a.height);
120             //menu.el.get_toplevel().move(10,10);
121             //return false;
122               
123         }); 
124         
125     }
126     
127     public void pause()
128     {
129                 this.set_from_stock( Gtk.Stock.MEDIA_PAUSE );
130                 this.paused = true;
131     }
132     
133     public void resume()
134     {
135                 this.set_from_stock( Gtk.Stock.MEDIA_PLAY );
136                 this.paused = false;
137     }
138     
139     public void refreshing()
140     {
141                 this.set_from_stock( Gtk.Stock.REFRESH );
142     }
143     
144     public void pauseError()
145     {
146                  this.paused = true;
147                  var flag = true;
148                  Timeout.add_full(Priority.LOW, 500, () => {
149                  
150                         if (!this.paused) {
151                                 return false;
152                         }
153                         this.set_from_stock( flag == true ? Gtk.Stock.MEDIA_RECORD  
154                                         : Gtk.Stock.MEDIA_PAUSE);
155                         flag = !flag;
156                         return true;
157                 });
158                  
159     }
160     
161     class GitliveMenu : Gtk.Menu
162     {
163         public ImageMenuItem pause;
164         public ImageMenuItem resume;
165         public Gtk.MenuItem before_seperator;
166         public Gtk.MenuItem after_seperator;        
167         
168         
169         public GitliveMenu()
170         {
171             this.pause = new MenuItemPause();
172             this.append(this.pause);
173             this.resume = new MenuItemStartCommits();
174             this.append(this.resume);
175             this.append(new MenuItemPullAll());
176             this.before_seperator = new Gtk.SeparatorMenuItem();
177             this.append(this.before_seperator);
178
179             this.after_seperator = new Gtk.SeparatorMenuItem();
180             this.append(this.after_seperator);
181             //this.append(new MenuItemUpdateTimesheet());            
182             this.append(new MenuItemManageClones());
183             this.append(new MenuItemNewTicket());            
184             this.append(new MenuItemAbout());
185             this.append(new MenuItemQuit());
186             this.merge_items = new  Gee.ArrayList<Gtk.MenuItem>();
187         }
188         public Gee.ArrayList<Gtk.MenuItem> merge_items;
189         
190         
191         public void updateMerges()
192         {
193                 // show a list of possible merges on the menu.
194                 foreach (var m in this.merge_items) {
195                         this.remove(m);
196                 }
197                 foreach(var r in GitRepo.singleton().cache.values ) {
198                         GLib.debug("checking %s for branch = %s", r.name, r.currentBranch.name);
199                         if (!r.is_wip_branch()) {
200                                 continue;
201                                 }
202                         GLib.debug("checking  for activeTicket");                               
203                                 var t = r.activeTicket;
204                                 if (t == null) { 
205                                         continue;
206                                 }
207                                 var mi = new MergeMenuItem(r,t);
208                                 this.insert (mi,4); //backwards.
209                                 this.merge_items.add(mi);                       
210                                  
211                 }
212                 
213         }
214         
215        
216         class MergeMenuItem : Gtk.MenuItem {        
217         
218                 GitRepo repo;
219                 RooTicket ticket;
220         
221                 public MergeMenuItem(GitRepo r, RooTicket t)
222                 {
223                         this.repo = r;
224                         this.ticket = t;
225                         
226                         this.label = ("Merge [%s] #%s %s".printf(r.name, t.id , t.summary));
227
228                                 this.activate.connect(() => {
229                                         MergeBranch.singleton().show(this.ticket, null);
230                                         // show merge dialog..
231                                 });
232                 
233                 }
234                 
235         }
236         
237         
238         class MenuItemPause : ImageMenuItem {
239             
240             public MenuItemPause()
241             {
242                 //this.set_from_stock( Gtk.Stock.MEDIA_PAUSE );
243                 
244                 var  image = new Gtk.Image();
245                 image.set_from_stock(Gtk.Stock.MEDIA_PAUSE,Gtk.IconSize.MENU );
246                 this.set_image (image);
247                 
248                 this.label= "Pause Commits";
249                 this.always_show_image = true;
250                 this.accel_group = null;
251                 
252                 this.activate.connect( () => {
253                     statusicon.paused = true;
254                     GitMonitor.gitmonitor.stop();
255
256                    // this.el.label  = status ? 'Resume' : 'Pause';
257                     statusicon.set_from_stock( Gtk.Stock.MEDIA_PAUSE );
258                     
259                     
260                 });
261                 //    id : 'pause',
262             }
263             
264             
265         }
266         class MenuItemStartCommits : ImageMenuItem {
267             
268             public MenuItemStartCommits()
269             {
270                 
271                 var  image = new Gtk.Image();
272                 image.set_from_stock(Gtk.Stock.MEDIA_PLAY,Gtk.IconSize.MENU );
273                 this.set_image (image);
274                 this.label= "Start Commits";
275                 this.always_show_image = true;
276                 this.accel_group = null;
277                 
278                 this.activate.connect( () => {
279                     GitMonitor.gitmonitor.start();
280                     statusicon.paused = false;
281                     
282                     //
283                    // this.el.label  = status ? 'Resume' : 'Pause';
284                     statusicon.set_from_stock( Gtk.Stock.MEDIA_PLAY );
285                     
286                     
287                 });
288             }
289             
290             
291         }
292         
293         
294         class MenuItemPullAll : ImageMenuItem {
295             
296             public MenuItemPullAll()
297             {
298                 
299                 var  image = new Gtk.Image();
300                 image.set_from_stock(Gtk.Stock.FULLSCREEN,Gtk.IconSize.MENU );
301                 this.set_image (image);
302                 this.label= "Pull (Refresh) All";
303                 this.always_show_image = true;
304                 this.accel_group = null;
305                 
306                 this.activate.connect( () => {
307                     
308                     this.pullAll();
309                     /*
310                     GitMonitor.gitmonitor.stop();
311                     var tr = GitRepo.list();
312                     
313                     
314                     
315                     for (var i= 0; i< tr.length;i++) {
316                         statusicon.set_from_stock( 
317                                 i%2 == 0 ?  Gtk.Stock.FULLSCREEN : Gtk.Stock.LEAVE_FULLSCREEN );
318                                 
319                         var repo = tr.index(i);
320                         //if (!repo.autocommit()) {
321                             //??? should we ignore ones not on autocommit..
322                         //    continue;
323                         //}
324                         try {
325                             statusicon.set_tooltip_text("pull: " + repo.name);
326                             var str = repo.pull();
327                                     // do not care if it's already in sycn..
328                             if (Regex.match_simple ("Already up-to-date", str) ) {
329                                 continue;
330                             }
331                             var notification = new Notify.Notification( 
332                                      "Updated " + repo.name,
333                                      str,
334                                        "dialog-information"
335                                    
336                             );
337                         
338                             notification.set_timeout(20);
339                             notification.show();
340                                      
341                         } catch(Error e) {
342                             print("notification or push errror- probably to many in queue..");
343                             statusicon.set_from_stock( Gtk.Stock.MEDIA_RECORD );
344                             print(e.message);
345                             
346                         }        
347
348                     } 
349                     */
350                            
351                            
352                 });
353             }
354             void pullAll()
355             {
356                         var tr = GitRepo.list();
357                 
358                 GitMonitor.gitmonitor.stop();
359                     
360                 
361                this.total = tr.length;
362                 this.has_error = 0;
363                 this.pull_all_error_message = "";
364                 for (var i= 0; i< tr.length;i++) {
365                     statusicon.set_from_stock( 
366                                 i%2 == 0 ?  Gtk.Stock.FULLSCREEN : Gtk.Stock.LEAVE_FULLSCREEN );
367                             
368                     var repo = tr.index(i);
369                     //repo.ref();
370                     //this.ref();
371                     
372                     statusicon.set_tooltip_text("pull: " + repo.name);
373                                         
374                     repo.pull_async(this.pullAllCallback); 
375                                 // do not care if it's already in sycn..
376                         
377                      
378
379                 } 
380
381                   
382         
383         
384                 }
385                 uint total = 0; 
386                         uint has_error = 0;
387                         string pull_all_error_message = "";
388                 
389                 void pullAllCallback(GitRepo repo, int err, string res)
390                 {
391                         this.total--;
392                         
393                         if (err > 0) {
394                                 this.has_error = 1;
395                                 this.pull_all_error_message += this.pull_all_error_message.length > 0 ? "\n" : "";
396                                 this.pull_all_error_message += "Error Pulling " + repo.name +"\n" + res;
397                         }
398                         
399                         if (!Regex.match_simple ("Already up-to-date", res) ) {
400                         var notification = new Notify.Notification( 
401                          "Pull completed ",
402                           "Updated: " +repo.name + "\n" + res +"\n",
403                              "dialog-information"
404                     );
405                     notification.set_timeout(20);
406                                 notification.show();
407                         
408  
409  
410                         }
411                         if (this.total < 1) {
412                                 if (this.has_error > 0) {
413                                         GitMonitor.gitmonitor.pauseError(this.pull_all_error_message);
414                                         return;
415                                 }
416                         
417                         statusicon.set_tooltip_text("Gitlive");
418                   
419                                 GitMonitor.gitmonitor.start();
420                                 //this.unref();
421                                 //repo.unref();
422                         }
423                         
424                 }
425         
426             
427         }
428         
429         
430         class MenuItemUpdateTimesheet : ImageMenuItem {
431             
432             public MenuItemUpdateTimesheet()
433             {
434                 
435                 var  image = new Gtk.Image();
436                 image.set_from_stock(Gtk.Stock.SAVE,Gtk.IconSize.MENU );
437                                 this.set_image (image);
438                 this.label= "Update Timesheet";
439                 this.always_show_image = true;
440                 this.accel_group = null;
441                 
442                 this.activate.connect( () => {
443                  //var ret = imports.FixBug.FixBug.show();
444                 });
445             }
446             
447             
448         }
449         
450         class MenuItemManageClones : ImageMenuItem {
451             
452             public MenuItemManageClones()
453             {
454                 
455                 var  image = new Gtk.Image();
456                 image.set_from_stock(Gtk.Stock.FULLSCREEN,Gtk.IconSize.MENU );
457                 this.set_image (image);
458                 this.label= "Manage Clones";
459                 this.always_show_image = true;
460                 this.accel_group = null;
461                 
462                 this.activate.connect( () => {
463                         GitRepo.updateAll("show_clones");
464                 
465                      // Clones.singleton().show();
466                 });
467             }
468             
469             
470         }
471         
472         class MenuItemNewTicket : ImageMenuItem {
473             
474             public MenuItemNewTicket()
475             {
476                 
477                 var  image = new Gtk.Image();
478                 image.set_from_stock(Gtk.Stock.FULLSCREEN,Gtk.IconSize.MENU );
479                 this.set_image (image);
480                 this.label= "New Ticket";
481                 this.always_show_image = true;
482                 this.accel_group = null;
483                 
484                 this.activate.connect( () => {
485                         Ticket.singleton().show(null);
486
487                 
488                      // Clones.singleton().show();
489                 });
490             }
491             
492             
493         }
494         
495         
496         class MenuItemAbout : ImageMenuItem {
497             
498             public MenuItemAbout()
499             {
500                 
501                 var  image = new Gtk.Image();
502                 image.set_from_stock(Gtk.Stock.ABOUT,Gtk.IconSize.MENU );
503                 this.set_image (image);
504                 this.label= "About Gitlive";
505                 this.always_show_image = true;
506                 this.accel_group = null;
507                 
508                 this.activate.connect( () => {
509                  //var ret = imports.Clones.Clones.show();
510                  
511                     var msg = new Gtk.AboutDialog();
512                     msg.program_name = "Git Live";
513                     msg.version= "0.3";
514                     msg.website= "http://www.roojs.org/index.php/projects/gitlive.html";
515                     msg.website_label= "Roo J Solutions Ltd.";
516                     msg.license = "LGPL";
517                     msg.authors = { "Alan Knowles <alan@roojs.com>" };
518                     msg.run();
519                     msg.destroy();
520                 });
521             }
522             
523             
524         }
525         
526          class MenuItemQuit : ImageMenuItem {
527             
528             public MenuItemQuit()
529             {
530                 
531                 var  image = new Gtk.Image();
532                 image.set_from_stock(Gtk.Stock.QUIT,Gtk.IconSize.MENU );
533                 this.set_image (image);
534                 this.label= "Quit";
535                 this.always_show_image = true;
536                 this.accel_group = null;
537                 
538                 this.activate.connect( () => {
539                     // confirm?
540                     Gtk.main_quit();
541                  //var ret = imports.Clones.Clones.show();
542                  });
543             }
544             
545             
546         }
547         
548     }
549 }
550       
551                 
552