1/* 2 * Copyright (C) 2013 Paolo Borelli <pborelli@gnome.org> 3 * Copyright (C) 2020 Bilal Elmoussaoui <bilal.elmoussaoui@gnome.org> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 */ 19 20namespace Clocks { 21namespace Timer { 22 23[GtkTemplate (ui = "/org/gnome/clocks/ui/timer-face.ui")] 24public class Face : Gtk.Stack, Clocks.Clock { 25 private Setup timer_setup; 26 [GtkChild] 27 private unowned Gtk.ListBox timers_list; 28 [GtkChild] 29 private unowned Gtk.Box no_timer_container; 30 [GtkChild] 31 private unowned Gtk.Button start_button; 32 33 public PanelId panel_id { get; construct set; } 34 public ButtonMode button_mode { get; set; default = NONE; } 35 public bool is_running { get; set; default = false; } 36 // Translators: Tooltip for the + button 37 public string? new_label { get; default = _("New Timer"); } 38 39 private ContentStore timers; 40 private GLib.Settings settings; 41 private Utils.Bell bell; 42 private GLib.Notification notification; 43 44 construct { 45 panel_id = TIMER; 46 transition_type = CROSSFADE; 47 timer_setup = new Setup (); 48 49 settings = new GLib.Settings ("org.gnome.clocks"); 50 timers = new ContentStore (); 51 52 timers_list.bind_model (timers, (timer) => { 53 var row = new Row ((Item) timer); 54 row.deleted.connect (() => remove_timer ((Item) timer)); 55 row.edited.connect (() => save ()); 56 ((Item)timer).ring.connect (() => ring ()); 57 ((Item)timer).notify["state"].connect (() => { 58 this.is_running = this.get_total_active_timers () != 0; 59 }); 60 return row; 61 }); 62 63 timers.items_changed.connect ( (added, removed, position) => { 64 if (this.timers.get_n_items () > 0) { 65 this.visible_child_name = "timers"; 66 this.button_mode = NEW; 67 } else { 68 this.visible_child_name = "empty"; 69 this.button_mode = NONE; 70 } 71 save (); 72 }); 73 74 bell = new Utils.Bell ("complete"); 75 notification = new GLib.Notification (_("Time is up!")); 76 notification.set_body (_("Timer countdown finished")); 77 notification.set_priority (HIGH); 78 79 no_timer_container.add (timer_setup); 80 no_timer_container.reorder_child (timer_setup, 1); 81 set_visible_child_name ("empty"); 82 83 start_button.set_sensitive (false); 84 timer_setup.duration_changed.connect ((duration) => { 85 start_button.set_sensitive (duration != 0); 86 }); 87 start_button.clicked.connect (() => { 88 var timer = this.timer_setup.get_timer (); 89 this.timers.add (timer); 90 91 timer.start (); 92 }); 93 load (); 94 } 95 96 private int get_total_active_timers () { 97 var total_items = 0; 98 this.timers.foreach ((timer) => { 99 if (((Item)timer).state == Item.State.RUNNING) { 100 total_items += 1; 101 } 102 }); 103 return total_items; 104 } 105 106 private void remove_timer (Item item) { 107 timers.remove (item); 108 } 109 110 public void activate_new () { 111 var dialog = new SetupDialog ((Gtk.Window) get_toplevel ()); 112 dialog.response.connect ((dialog, response) => { 113 if (response == Gtk.ResponseType.ACCEPT) { 114 var timer = ((SetupDialog) dialog).timer_setup.get_timer (); 115 this.timers.add (timer); 116 timer.start (); 117 } 118 dialog.destroy (); 119 }); 120 dialog.show (); 121 } 122 123 private void load () { 124 timers.deserialize (settings.get_value ("timers"), Item.deserialize); 125 } 126 127 private void save () { 128 settings.set_value ("timers", timers.serialize ()); 129 } 130 131 public virtual signal void ring () { 132 var app = (Clocks.Application) GLib.Application.get_default (); 133 app.send_notification ("timer-is-up", notification); 134 bell.ring_once (); 135 } 136 137 public override void grab_focus () { 138 if (timers.get_n_items () == 0) { 139 start_button.grab_focus (); 140 } 141 } 142} 143 144} // namespace Timer 145} // namespace Clocks 146