[gnome-calendar/wip/gbsneto/alarms: 4/6] edit-dialog: show available alarms



commit f36d574b7c7aaa027d5117fa328a3be4da33e0d2
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Jul 6 01:36:36 2016 -0300

    edit-dialog: show available alarms
    
    This commit introduces the ability in Edit dialog to
    display the currently available alarms, as well as basic
    editing of these alarms.
    
    Currently, only removing the alarms and modifying it to
    play a sound or not is available. The following up commit
    will add the ability to add new alarms.

 data/Makefile.am            |    1 +
 data/calendar.gresource.xml |    1 +
 data/ui/alarm-row.ui        |   73 +++++++++++++++++
 data/ui/edit-dialog.ui      |   79 +++++++++++++++++-
 src/gcal-edit-dialog.c      |  190 +++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 339 insertions(+), 5 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 8f24732..54b4c98 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -49,6 +49,7 @@ EXTRA_DIST=                     \
   org.gnome.Calendar.desktop    \
   calendar.gresource.xml        \
   shell-search-provider-dbus-interfaces.xml \
+  ui/alarm-row.ui               \
   ui/calendar-row.ui            \
   ui/date-selector.ui           \
   ui/edit-dialog.ui             \
diff --git a/data/calendar.gresource.xml b/data/calendar.gresource.xml
index bae71e8..f083f3f 100644
--- a/data/calendar.gresource.xml
+++ b/data/calendar.gresource.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/calendar">
+    <file alias="alarm-row.ui" compressed="true" preprocess="xml-stripblanks">ui/alarm-row.ui</file>
     <file alias="calendar-row.ui" compressed="true" preprocess="xml-stripblanks">ui/calendar-row.ui</file>
     <file alias="date-selector.ui" compressed="true" preprocess="xml-stripblanks">ui/date-selector.ui</file>
     <file alias="edit-dialog.ui" compressed="true" preprocess="xml-stripblanks">ui/edit-dialog.ui</file>
diff --git a/data/ui/alarm-row.ui b/data/ui/alarm-row.ui
new file mode 100644
index 0000000..acf8bd9
--- /dev/null
+++ b/data/ui/alarm-row.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkBox" id="main_box">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkButton">
+        <property name="visible">True</property>
+        <property name="sensitive">False</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="hexpand">True</property>
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="ellipsize">end</property>
+            <property name="xalign">0</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkToggleButton" id="volume_button">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="tooltip-text" translatable="yes">Toggles the sound of the alarm</property>
+        <child>
+          <object class="GtkImage" id="volume_icon">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="icon_name">audio-volume-high-symbolic</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkButton" id="remove_button">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="receives_default">True</property>
+        <property name="tooltip-text" translatable="yes">Remove the alarm</property>
+        <child>
+          <object class="GtkImage">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="icon_name">window-close-symbolic</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">2</property>
+      </packing>
+    </child>
+    <style>
+      <class name="linked"/>
+    </style>
+  </object>
+</interface>
diff --git a/data/ui/edit-dialog.ui b/data/ui/edit-dialog.ui
index f1e59db..4bdc2fb 100644
--- a/data/ui/edit-dialog.ui
+++ b/data/ui/edit-dialog.ui
@@ -102,6 +102,21 @@
               </packing>
             </child>
             <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Reminders</property>
+                <property name="ellipsize">end</property>
+                <style>
+                  <class name="dim-label"/>
+                </style>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkLabel" id="notes_label">
                 <property name="visible">True</property>
                 <property name="halign">end</property>
@@ -113,7 +128,7 @@
               </object>
               <packing>
                 <property name="left_attach">0</property>
-                <property name="top_attach">4</property>
+                <property name="top_attach">5</property>
               </packing>
             </child>
             <child>
@@ -127,7 +142,7 @@
               </object>
               <packing>
                 <property name="left_attach">0</property>
-                <property name="top_attach">3</property>
+                <property name="top_attach">4</property>
               </packing>
             </child>
             <child>
@@ -188,7 +203,7 @@
               </object>
               <packing>
                 <property name="left_attach">1</property>
-                <property name="top_attach">3</property>
+                <property name="top_attach">4</property>
                 <property name="width">4</property>
               </packing>
             </child>
@@ -213,7 +228,7 @@
               </object>
               <packing>
                 <property name="left_attach">1</property>
-                <property name="top_attach">4</property>
+                <property name="top_attach">5</property>
                 <property name="width">4</property>
               </packing>
             </child>
@@ -286,6 +301,60 @@
               </packing>
             </child>
             <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">6</property>
+                <property name="hexpand">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkListBox" id="alarms_listbox">
+                    <property name="visible">False</property>
+                    <property name="can_focus">False</property>
+                    <property name="selection_mode">none</property>
+                    <style>
+                      <class name="background" />
+                    </style>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="alarms_button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hexpand">True</property>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="orientation">horizontal</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="xalign">0.0</property>
+                            <property name="label">Add reminder…</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkImage">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">pan-down-symbolic</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">3</property>
+                <property name="width">4</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkButton" id="delete_button">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
@@ -303,7 +372,7 @@
               </object>
               <packing>
                 <property name="left_attach">0</property>
-                <property name="top_attach">5</property>
+                <property name="top_attach">6</property>
               </packing>
             </child>
           </object>
diff --git a/src/gcal-edit-dialog.c b/src/gcal-edit-dialog.c
index b2a510a..66f34c6 100644
--- a/src/gcal-edit-dialog.c
+++ b/src/gcal-edit-dialog.c
@@ -16,6 +16,7 @@
  * You should have received a copy of the GNU General Public License along
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include "config.h"
 
 #include "gcal-edit-dialog.h"
 #include "gcal-time-selector.h"
@@ -54,6 +55,8 @@ struct _GcalEditDialog
   GtkWidget        *location_entry;
   GtkWidget        *notes_text;
 
+  GtkWidget        *alarms_listbox;
+
   /* actions */
   GMenu              *sources_menu;
   GSimpleActionGroup *action_group;
@@ -356,6 +359,7 @@ gcal_edit_dialog_class_init (GcalEditDialogClass *klass)
   gtk_widget_class_bind_template_child (widget_class, GcalEditDialog, end_date_selector);
   gtk_widget_class_bind_template_child (widget_class, GcalEditDialog, location_entry);
   /* Other */
+  gtk_widget_class_bind_template_child (widget_class, GcalEditDialog, alarms_listbox);
   gtk_widget_class_bind_template_child (widget_class, GcalEditDialog, notes_text);
   gtk_widget_class_bind_template_child (widget_class, GcalEditDialog, all_day_check);
   gtk_widget_class_bind_template_child (widget_class, GcalEditDialog, titlebar);
@@ -544,6 +548,189 @@ gcal_edit_dialog_all_day_changed (GtkWidget *widget,
   gtk_widget_set_sensitive (dialog->end_time_selector, !active);
 }
 
+/*
+ * Alarm related functions
+ */
+static void
+remove_button_clicked (GtkButton *button,
+                       GtkWidget *row)
+{
+  ECalComponentAlarm *alarm;
+  GcalEditDialog *self;
+  GcalEvent *event;
+  gint trigger_minutes;
+
+  self = GCAL_EDIT_DIALOG (gtk_widget_get_toplevel (row));
+  alarm = g_object_get_data (G_OBJECT (row), "alarm");
+  event = g_object_get_data (G_OBJECT (row), "event");
+  trigger_minutes = get_alarm_trigger_minutes (event, alarm);
+
+  gcal_event_remove_alarm (event, trigger_minutes);
+
+  gcal_manager_update_event (self->manager, event);
+
+  gtk_widget_destroy (row);
+}
+
+static void
+sound_toggle_changed (GtkToggleButton *button,
+                      GtkWidget       *row)
+{
+  ECalComponentAlarmAction action;
+  ECalComponentAlarm *alarm;
+  GtkWidget *image;
+  gboolean has_sound;
+
+  alarm = g_object_get_data (G_OBJECT (row), "alarm");
+  image = gtk_bin_get_child (GTK_BIN (button));
+  has_sound = gtk_toggle_button_get_active (button);
+
+  /* Setup the alarm action */
+  action = has_sound ? E_CAL_COMPONENT_ALARM_AUDIO : E_CAL_COMPONENT_ALARM_DISPLAY;
+
+  e_cal_component_alarm_set_action (alarm, action);
+
+  /* Update the volume icon */
+  gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                has_sound ? "audio-volume-high-symbolic" : "audio-volume-muted-symbolic",
+                                GTK_ICON_SIZE_BUTTON);
+
+}
+
+static GtkWidget*
+create_row_for_alarm (GcalEvent          *event,
+                      ECalComponentAlarm *alarm)
+{
+  ECalComponentAlarmAction action;
+  GtkBuilder *builder;
+  GtkWidget *label, *main_box, *row, *remove_button;
+  GtkWidget *volume_button, *volume_icon;
+  gboolean has_sound;
+  gchar *text;
+  gint trigger_minutes;
+
+  trigger_minutes = get_alarm_trigger_minutes (event, alarm);
+
+  /* Something bad happened */
+  if (trigger_minutes < 0)
+    return NULL;
+
+  if (trigger_minutes < 60)
+    {
+      text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+                                           "%d minute before",
+                                           "%d minutes before",
+                                           trigger_minutes),
+                              trigger_minutes);
+    }
+  else if (trigger_minutes < 1440)
+    {
+      text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+                                           "%d hour before",
+                                           "%d hours before",
+                                           trigger_minutes / 60),
+                              trigger_minutes / 60);
+    }
+  else if (trigger_minutes < 10080)
+    {
+      text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+                                           "%d day before",
+                                           "%d days before",
+                                           trigger_minutes / 1440),
+                              trigger_minutes / 1440);
+    }
+  else
+    {
+      text = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
+                                           "%d week before",
+                                           "%d weeks before",
+                                           trigger_minutes / 10080),
+                              trigger_minutes / 10080);
+    }
+
+  /* The row */
+  row = gtk_list_box_row_new ();
+
+  g_object_set_data (G_OBJECT (row), "alarm", alarm);
+  g_object_set_data (G_OBJECT (row), "event", event);
+
+  /* Build the UI */
+  builder = gtk_builder_new_from_resource ("/org/gnome/calendar/alarm-row.ui");
+
+#define WID(x) (GTK_WIDGET (gtk_builder_get_object (builder, x)))
+
+  label = WID ("label");
+  gtk_label_set_label (GTK_LABEL (label), text);
+
+  /* Retrieves the actions associated to the alarm */
+  e_cal_component_alarm_get_action (alarm, &action);
+
+  /* Updates the volume button to match the action */
+  has_sound = action == E_CAL_COMPONENT_ALARM_AUDIO;
+
+  volume_button = WID ("volume_button");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (volume_button), has_sound);
+
+  volume_icon = WID ("volume_icon");
+  gtk_image_set_from_icon_name (GTK_IMAGE (volume_icon),
+                                has_sound ? "audio-volume-high-symbolic" : "audio-volume-muted-symbolic",
+                                GTK_ICON_SIZE_BUTTON);
+
+  g_signal_connect (volume_button,
+                    "toggled",
+                    G_CALLBACK (sound_toggle_changed),
+                    row);
+
+  /* Remove button */
+  remove_button = WID ("remove_button");
+
+  g_signal_connect (remove_button,
+                    "clicked",
+                    G_CALLBACK (remove_button_clicked),
+                    row);
+
+  main_box = WID ("main_box");
+  gtk_container_add (GTK_CONTAINER (row), main_box);
+
+  gtk_widget_show_all (row);
+
+  g_clear_object (&builder);
+  g_free (text);
+
+#undef WID
+
+  return row;
+}
+
+static void
+setup_alarms (GcalEditDialog *self)
+{
+  GList *alarms, *l;
+
+  gtk_widget_set_visible (self->alarms_listbox, gcal_event_has_alarms (self->event));
+
+  alarms = gcal_event_get_alarms (self->event);
+
+  /* Remove previous alarms */
+  gtk_container_foreach (GTK_CONTAINER (self->alarms_listbox),
+                         (GtkCallback) gtk_widget_destroy,
+                         NULL);
+
+  for (l = alarms; l != NULL; l = l->next)
+    {
+      GtkWidget *row;
+
+      row = create_row_for_alarm (self->event, l->data);
+
+      if (!row)
+        continue;
+
+      gtk_container_add (GTK_CONTAINER (self->alarms_listbox), row);
+    }
+
+  g_list_free (alarms);
+}
+
 /* Public API */
 GtkWidget*
 gcal_edit_dialog_new (void)
@@ -670,6 +857,9 @@ gcal_edit_dialog_set_event (GcalEditDialog *dialog,
       g_clear_pointer (&date_start, g_date_time_unref);
       g_clear_pointer (&date_end, g_date_time_unref);
 
+      /* Setup the alarms */
+      setup_alarms (dialog);
+
 out:
       g_object_notify (G_OBJECT (dialog), "event");
 


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