diff options
-rw-r--r-- | calendar/ChangeLog | 19 | ||||
-rw-r--r-- | calendar/cal-util/cal-component.c | 13 | ||||
-rw-r--r-- | calendar/gui/Makefile.am | 8 | ||||
-rw-r--r-- | calendar/gui/event-editor-dialog.glade | 713 | ||||
-rw-r--r-- | calendar/gui/event-editor-dialog.glade.h | 88 | ||||
-rw-r--r-- | calendar/gui/event-editor.c | 883 | ||||
-rw-r--r-- | calendar/gui/event-editor.h | 5 | ||||
-rw-r--r-- | calendar/gui/weekday-picker.c | 4 |
8 files changed, 1478 insertions, 255 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 19b40874da..22fdd7ac7a 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,22 @@ +2000-10-26 Federico Mena Quintero <federico@helixcode.com> + + * gui/event-editor.c (EventEditorPrivate): Integrate Anna's new + recurrence page. Replace the old widget pointers with the new + ones. Modified the relevant functions accordingly and added + plenty of new ones. + (event_editor_get_cal_client): New function. + (fill_recurrence_widgets): This is *THE* tricky function for you. + It has to discriminate whether we get a recurrence we support for + editing or not. And this is not trivial. Sigh. + (event_editor_update_widgets): Added preconditions and API docs. + + * event-editor-dialog.glade: Fixed all the spacings/ + paddings/packing options so that the widgets will look right if + the dialog box is resized. Also fixes some misaligned widgets. + + * cal-util/cal-component.c (cal_component_set_rdate_list): Removed + incorrect assertion. + 2000-10-26 Michael Meeks <michael@helixcode.com> * pcs/cal-factory.c (str_tolower): unsigned chars to isalpha diff --git a/calendar/cal-util/cal-component.c b/calendar/cal-util/cal-component.c index 35ec603dd2..4f813cbdee 100644 --- a/calendar/cal-util/cal-component.c +++ b/calendar/cal-util/cal-component.c @@ -2252,9 +2252,10 @@ cal_component_has_exrules (CalComponent *comp) * cal_component_has_exceptions: * @comp: A calendar component object * - * Queries whether a calendar component object has any exceptions defined + * Queries whether a calendar component object has any exception dates + * or exception rules. * - * Return value: TRUE if the component has exceptions, FALSE otherwise + * Return value: TRUE if the component has exceptions, FALSE otherwise. **/ gboolean cal_component_has_exceptions (CalComponent *comp) @@ -2542,7 +2543,6 @@ cal_component_set_rdate_list (CalComponent *comp, GSList *period_list) g_return_if_fail (comp != NULL); g_return_if_fail (IS_CAL_COMPONENT (comp)); - g_return_if_fail (period_list != NULL); priv = comp->priv; g_return_if_fail (priv->icalcomp != NULL); @@ -2670,12 +2670,13 @@ cal_component_has_rrules (CalComponent *comp) } /** - * cal_component_has_recurrence: + * cal_component_has_recurrences: * @comp: A calendar component object * - * Queries whether a calendar component object has any recurrences defined + * Queries whether a calendar component object has any recurrence dates or + * recurrence rules. * - * Return value: TRUE if the component has recurrences, FALSE otherwise + * Return value: TRUE if the component has recurrences, FALSE otherwise. **/ gboolean cal_component_has_recurrences (CalComponent *comp) diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 8ab648e90e..67a257f0dd 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -13,9 +13,6 @@ $(IDL_GENERATED): $(IDLS) $(ORBIT_IDL) -I $(datadir)/idl `$(GNOME_CONFIG) --cflags idl` \ -I . $(srcdir)/../../composer/Evolution-Composer.idl -## - - SUBDIRS = dialogs help_base = $(datadir)/gnome/help/cal @@ -114,7 +111,9 @@ evolution_calendar_SOURCES = \ popup-menu.h \ print.c \ print.h \ - prop.c + prop.c \ + weekday-picker.c \ + weekday-picker.h evolution_calendar_LDADD = \ $(top_builddir)/shell/libeshell.a \ @@ -147,7 +146,6 @@ EXTRA_DIST = \ calendar-control.oafinfo \ evolution-calendar.oafinfo - install-data-local: $(mkinstalldirs) $(DESTDIR)$(help_base)/C $(mkinstalldirs) $(Conduitsdir) diff --git a/calendar/gui/event-editor-dialog.glade b/calendar/gui/event-editor-dialog.glade index 3a81c0d1de..7f675f87ea 100644 --- a/calendar/gui/event-editor-dialog.glade +++ b/calendar/gui/event-editor-dialog.glade @@ -79,7 +79,7 @@ <widget> <class>GtkLabel</class> <name>label13</name> - <label>_Summary:</label> + <label>Su_mmary:</label> <justify>GTK_JUSTIFY_CENTER</justify> <wrap>False</wrap> <xalign>7.45058e-09</xalign> @@ -137,7 +137,7 @@ <child> <padding>0</padding> <expand>False</expand> - <fill>True</fill> + <fill>False</fill> </child> <widget> @@ -151,12 +151,37 @@ <column_spacing>4</column_spacing> <widget> + <class>Custom</class> + <name>start-time</name> + <creation_function>make_date_edit_with_time</creation_function> + <string1></string1> + <string2></string2> + <int1>0</int1> + <int2>0</int2> + <last_modification_time>Tue, 16 May 2000 19:11:05 GMT</last_modification_time> + <child> + <left_attach>1</left_attach> + <right_attach>2</right_attach> + <top_attach>0</top_attach> + <bottom_attach>1</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>True</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> <class>GtkLabel</class> <name>label15</name> - <label>Start time:</label> + <label>_Start time:</label> <justify>GTK_JUSTIFY_CENTER</justify> <wrap>False</wrap> - <xalign>0.5</xalign> + <xalign>0</xalign> <yalign>0.5</yalign> <xpad>0</xpad> <ypad>0</ypad> @@ -171,7 +196,7 @@ <yexpand>False</yexpand> <xshrink>False</xshrink> <yshrink>False</yshrink> - <xfill>False</xfill> + <xfill>True</xfill> <yfill>False</yfill> </child> </widget> @@ -179,10 +204,10 @@ <widget> <class>GtkLabel</class> <name>label16</name> - <label>End time:</label> + <label>_End time:</label> <justify>GTK_JUSTIFY_CENTER</justify> <wrap>False</wrap> - <xalign>0.5</xalign> + <xalign>0</xalign> <yalign>0.5</yalign> <xpad>0</xpad> <ypad>0</ypad> @@ -197,48 +222,23 @@ <yexpand>False</yexpand> <xshrink>False</xshrink> <yshrink>False</yshrink> - <xfill>False</xfill> - <yfill>False</yfill> - </child> - </widget> - - <widget> - <class>GtkCheckButton</class> - <name>all-day-event</name> - <can_focus>True</can_focus> - <label>A_ll day event</label> - <active>False</active> - <draw_indicator>True</draw_indicator> - <child> - <left_attach>2</left_attach> - <right_attach>3</right_attach> - <top_attach>0</top_attach> - <bottom_attach>1</bottom_attach> - <xpad>0</xpad> - <ypad>0</ypad> - <xexpand>False</xexpand> - <yexpand>False</yexpand> - <xshrink>False</xshrink> - <yshrink>False</yshrink> - <xfill>False</xfill> + <xfill>True</xfill> <yfill>False</yfill> </child> </widget> <widget> <class>Custom</class> - <name>start-time</name> + <name>end-time</name> <creation_function>make_date_edit_with_time</creation_function> - <string1></string1> - <string2></string2> <int1>0</int1> <int2>0</int2> - <last_modification_time>Tue, 16 May 2000 19:11:05 GMT</last_modification_time> + <last_modification_time>Tue, 16 May 2000 19:11:10 GMT</last_modification_time> <child> <left_attach>1</left_attach> <right_attach>2</right_attach> - <top_attach>0</top_attach> - <bottom_attach>1</bottom_attach> + <top_attach>1</top_attach> + <bottom_attach>2</bottom_attach> <xpad>0</xpad> <ypad>0</ypad> <xexpand>True</xexpand> @@ -251,17 +251,17 @@ </widget> <widget> - <class>Custom</class> - <name>end-time</name> - <creation_function>make_date_edit_with_time</creation_function> - <int1>0</int1> - <int2>0</int2> - <last_modification_time>Tue, 16 May 2000 19:11:10 GMT</last_modification_time> + <class>GtkCheckButton</class> + <name>all-day-event</name> + <can_focus>True</can_focus> + <label>A_ll day event</label> + <active>False</active> + <draw_indicator>True</draw_indicator> <child> - <left_attach>1</left_attach> - <right_attach>2</right_attach> - <top_attach>1</top_attach> - <bottom_attach>2</bottom_attach> + <left_attach>2</left_attach> + <right_attach>3</right_attach> + <top_attach>0</top_attach> + <bottom_attach>1</bottom_attach> <xpad>0</xpad> <ypad>0</ypad> <xexpand>False</xexpand> @@ -279,7 +279,7 @@ <class>GtkScrolledWindow</class> <name>scrolledwindow3</name> <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy> - <vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy> + <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy> <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy> <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy> <child> @@ -306,13 +306,13 @@ <child> <padding>0</padding> <expand>False</expand> - <fill>True</fill> + <fill>False</fill> </child> <widget> <class>GtkHBox</class> <name>hbox6</name> - <border_width>4</border_width> + <border_width>2</border_width> <homogeneous>False</homogeneous> <spacing>4</spacing> @@ -1826,17 +1826,7 @@ Sunday <spacing>4</spacing> <widget> - <class>Custom</class> - <name>recurrence-exceptions-date</name> - <creation_function>make_date_edit</creation_function> - <int1>0</int1> - <int2>0</int2> - <last_modification_time>Tue, 16 May 2000 01:42:29 GMT</last_modification_time> - <child> - <padding>0</padding> - <expand>True</expand> - <fill>True</fill> - </child> + <class>Placeholder</class> </widget> <widget> @@ -1862,22 +1852,15 @@ Sunday </child> <widget> - <class>GtkButton</class> - <name>recurrence-exceptions-add</name> - <can_focus>True</can_focus> - <label>Add</label> - <child> - <padding>0</padding> - <expand>False</expand> - <fill>False</fill> - </child> + <class>Placeholder</class> </widget> <widget> <class>GtkButton</class> <name>recurrence-exceptions-change</name> <can_focus>True</can_focus> - <label>Change</label> + <label></label> + <relief>GTK_RELIEF_NORMAL</relief> <child> <padding>0</padding> <expand>False</expand> @@ -1886,15 +1869,7 @@ Sunday </widget> <widget> - <class>GtkButton</class> - <name>recurrence-exceptions-delete</name> - <can_focus>True</can_focus> - <label>Delete</label> - <child> - <padding>0</padding> - <expand>False</expand> - <fill>False</fill> - </child> + <class>Placeholder</class> </widget> </widget> @@ -1953,6 +1928,584 @@ Sunday <xpad>0</xpad> <ypad>0</ypad> </widget> + + <widget> + <class>GtkVBox</class> + <name>vbox41</name> + <border_width>4</border_width> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + + <widget> + <class>GtkFrame</class> + <name>frame26</name> + <label>Appointment Basics</label> + <label_xalign>0</label_xalign> + <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>GtkTable</class> + <name>table9</name> + <border_width>4</border_width> + <rows>2</rows> + <columns>2</columns> + <homogeneous>False</homogeneous> + <row_spacing>2</row_spacing> + <column_spacing>2</column_spacing> + + <widget> + <class>GtkLabel</class> + <name>label44</name> + <label>Su_mmary:</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <default_focus_target>recurrence-summary</default_focus_target> + <child> + <left_attach>0</left_attach> + <right_attach>1</right_attach> + <top_attach>0</top_attach> + <bottom_attach>1</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>False</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkLabel</class> + <name>label45</name> + <label>_Starting date:</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <child> + <left_attach>0</left_attach> + <right_attach>1</right_attach> + <top_attach>1</top_attach> + <bottom_attach>2</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>False</xexpand> + <yexpand>False</yexpand> + <xshrink>False</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkEntry</class> + <name>recurrence-summary</name> + <can_focus>True</can_focus> + <editable>True</editable> + <text_visible>True</text_visible> + <text_max_length>0</text_max_length> + <text></text> + <child> + <left_attach>1</left_attach> + <right_attach>2</right_attach> + <top_attach>0</top_attach> + <bottom_attach>1</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>True</xexpand> + <yexpand>False</yexpand> + <xshrink>True</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + </widget> + + <widget> + <class>GtkAlignment</class> + <name>alignment37</name> + <xalign>7.45058e-09</xalign> + <yalign>0.5</yalign> + <xscale>0</xscale> + <yscale>1</yscale> + <child> + <left_attach>1</left_attach> + <right_attach>2</right_attach> + <top_attach>1</top_attach> + <bottom_attach>2</bottom_attach> + <xpad>0</xpad> + <ypad>0</ypad> + <xexpand>True</xexpand> + <yexpand>False</yexpand> + <xshrink>True</xshrink> + <yshrink>False</yshrink> + <xfill>True</xfill> + <yfill>False</yfill> + </child> + + <widget> + <class>Custom</class> + <name>recurrence-starting-date</name> + <creation_function>make_date_edit</creation_function> + <int1>0</int1> + <int2>0</int2> + <last_modification_time>Fri, 22 Sep 2000 20:51:38 GMT</last_modification_time> + </widget> + </widget> + </widget> + </widget> + + <widget> + <class>GtkVBox</class> + <name>vbox43</name> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GtkFrame</class> + <name>frame28</name> + <label>Recurrence Rule</label> + <label_xalign>0</label_xalign> + <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>GtkVBox</class> + <name>vbox47</name> + <border_width>4</border_width> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + + <widget> + <class>GtkRadioButton</class> + <name>recurrence-none</name> + <can_focus>True</can_focus> + <label>No recurrence</label> + <active>False</active> + <draw_indicator>True</draw_indicator> + <group>recurrence-radio</group> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkRadioButton</class> + <name>recurrence-simple</name> + <can_focus>True</can_focus> + <label>Simple recurrence</label> + <active>False</active> + <draw_indicator>True</draw_indicator> + <group>recurrence-radio</group> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkHBox</class> + <name>recurrence-params</name> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>GtkLabel</class> + <name>label46</name> + <label>Every</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkSpinButton</class> + <name>recurrence-interval-value</name> + <can_focus>True</can_focus> + <climb_rate>1</climb_rate> + <digits>0</digits> + <numeric>True</numeric> + <update_policy>GTK_UPDATE_ALWAYS</update_policy> + <snap>False</snap> + <wrap>False</wrap> + <value>3</value> + <lower>0</lower> + <upper>1000</upper> + <step>1</step> + <page>10</page> + <page_size>10</page_size> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkOptionMenu</class> + <name>recurrence-interval-unit</name> + <can_focus>True</can_focus> + <items>day(s) +week(s) +month(s) +year(s) +</items> + <initial_choice>0</initial_choice> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkAlignment</class> + <name>recurrence-special</name> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xscale>0</xscale> + <yscale>0</yscale> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>Placeholder</class> + </widget> + </widget> + + <widget> + <class>GtkLabel</class> + <name>label47</name> + <label></label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xpad>2</xpad> + <ypad>0</ypad> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkOptionMenu</class> + <name>recurrence-ending-menu</name> + <can_focus>True</can_focus> + <items>for +until +forever +</items> + <initial_choice>0</initial_choice> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkAlignment</class> + <name>recurrence-ending-special</name> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xscale>0</xscale> + <yscale>0</yscale> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>Placeholder</class> + </widget> + </widget> + + <widget> + <class>GtkSpinButton</class> + <name>spinbutton25</name> + <can_focus>True</can_focus> + <climb_rate>1</climb_rate> + <digits>0</digits> + <numeric>False</numeric> + <update_policy>GTK_UPDATE_ALWAYS</update_policy> + <snap>False</snap> + <wrap>False</wrap> + <value>3</value> + <lower>0</lower> + <upper>100</upper> + <step>1</step> + <page>10</page> + <page_size>10</page_size> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkOptionMenu</class> + <name>optionmenu29</name> + <can_focus>True</can_focus> + <items>days +weeks +months +years +iterations +</items> + <initial_choice>3</initial_choice> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + </widget> + + <widget> + <class>GtkRadioButton</class> + <name>recurrence-custom</name> + <can_focus>True</can_focus> + <label>Custom recurrence</label> + <active>False</active> + <draw_indicator>True</draw_indicator> + <group>recurrence-radio</group> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + </widget> + </widget> + + <widget> + <class>GtkHBox</class> + <name>hbox45</name> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GtkFrame</class> + <name>frame24</name> + <label>Exceptions</label> + <label_xalign>0</label_xalign> + <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GtkHBox</class> + <name>hbox46</name> + <border_width>4</border_width> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + + <widget> + <class>GtkVBox</class> + <name>vbox44</name> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + + <widget> + <class>GtkButton</class> + <name>recurrence-exception-add</name> + <can_focus>True</can_focus> + <label>Add</label> + <relief>GTK_RELIEF_NORMAL</relief> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkButton</class> + <name>recurrence-exception-modify</name> + <can_focus>True</can_focus> + <label>Modify</label> + <relief>GTK_RELIEF_NORMAL</relief> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkButton</class> + <name>recurrence-exception-delete</name> + <can_focus>True</can_focus> + <label>Delete</label> + <relief>GTK_RELIEF_NORMAL</relief> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + </widget> + + <widget> + <class>GtkVBox</class> + <name>vbox45</name> + <homogeneous>False</homogeneous> + <spacing>4</spacing> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>Custom</class> + <name>recurrence-exception-date</name> + <creation_function>make_date_edit</creation_function> + <int1>0</int1> + <int2>0</int2> + <last_modification_time>Tue, 16 May 2000 01:42:29 GMT</last_modification_time> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + + <widget> + <class>GtkScrolledWindow</class> + <name>scrolledwindow10</name> + <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy> + <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy> + <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy> + <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy> + <child> + <padding>0</padding> + <expand>True</expand> + <fill>True</fill> + </child> + + <widget> + <class>GtkCList</class> + <name>recurrence-exception-list</name> + <can_focus>True</can_focus> + <columns>1</columns> + <column_widths>80</column_widths> + <selection_mode>GTK_SELECTION_BROWSE</selection_mode> + <show_titles>False</show_titles> + <shadow_type>GTK_SHADOW_IN</shadow_type> + + <widget> + <class>GtkLabel</class> + <child_name>CList:title</child_name> + <name>label49</name> + <label>label21</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + </widget> + </widget> + </widget> + </widget> + </widget> + </widget> + + <widget> + <class>GtkLabel</class> + <name>recurrence-custom-warning</name> + <label>This appointment has custom recurrence rules that cannot be edited by Evolution. + +However, the appointment will recur at the appropriate time and be displayed in the calendar views.</label> + <justify>GTK_JUSTIFY_LEFT</justify> + <wrap>True</wrap> + <xalign>0</xalign> + <yalign>0</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + <child> + <padding>0</padding> + <expand>False</expand> + <fill>False</fill> + </child> + </widget> + </widget> + </widget> + </widget> + + <widget> + <class>GtkLabel</class> + <child_name>Notebook:tab</child_name> + <name>label43</name> + <label>Recurrence</label> + <justify>GTK_JUSTIFY_CENTER</justify> + <wrap>False</wrap> + <xalign>0.5</xalign> + <yalign>0.5</yalign> + <xpad>0</xpad> + <ypad>0</ypad> + </widget> </widget> </widget> </widget> diff --git a/calendar/gui/event-editor-dialog.glade.h b/calendar/gui/event-editor-dialog.glade.h index 57638f7f78..4ac32e4643 100644 --- a/calendar/gui/event-editor-dialog.glade.h +++ b/calendar/gui/event-editor-dialog.glade.h @@ -5,32 +5,28 @@ */ gchar *s = N_("event-editor-dialog"); -gchar *s = N_("_Summary:"); +gchar *s = N_("Su_mmary:"); gchar *s = N_("Time"); -gchar *s = N_("Start time:"); -gchar *s = N_("End time:"); +gchar *s = N_("_Start time:"); +gchar *s = N_("_End time:"); gchar *s = N_("A_ll day event"); gchar *s = N_("Classification"); gchar *s = N_("Pu_blic"); gchar *s = N_("Pri_vate"); gchar *s = N_("_Confidential"); gchar *s = N_("General"); -gchar *s = N_("Minutes\n" - "Hours\n" - "Days\n" - ""); -gchar *s = N_("Minutes\n" - "Hours\n" - "Days\n" - ""); -gchar *s = N_("Minutes\n" - "Hours\n" - "Days\n" - ""); -gchar *s = N_("Minutes\n" - "Hours\n" - "Days\n" - ""); +gchar *s = N_("Minutes"); +gchar *s = N_("Hours"); +gchar *s = N_("Days"); +gchar *s = N_("Minutes"); +gchar *s = N_("Hours"); +gchar *s = N_("Days"); +gchar *s = N_("Minutes"); +gchar *s = N_("Hours"); +gchar *s = N_("Days"); +gchar *s = N_("Minutes"); +gchar *s = N_("Hours"); +gchar *s = N_("Days"); gchar *s = N_("_Display"); gchar *s = N_("_Audio"); gchar *s = N_("_Program"); @@ -61,20 +57,18 @@ gchar *s = N_("label25"); gchar *s = N_("Recur on the"); gchar *s = N_("Recur on the"); gchar *s = N_("th day of the month"); -gchar *s = N_("1st\n" - "2nd\n" - "3rd\n" - "4th\n" - "5th\n" - ""); -gchar *s = N_("Monday\n" - "Tuesday\n" - "Wednesday\n" - "Thursday\n" - "Friday\n" - "Saturday\n" - "Sunday\n" - ""); +gchar *s = N_("1st"); +gchar *s = N_("2nd"); +gchar *s = N_("3rd"); +gchar *s = N_("4th"); +gchar *s = N_("5th"); +gchar *s = N_("Monday"); +gchar *s = N_("Tuesday"); +gchar *s = N_("Wednesday"); +gchar *s = N_("Thursday"); +gchar *s = N_("Friday"); +gchar *s = N_("Saturday"); +gchar *s = N_("Sunday"); gchar *s = N_("Every"); gchar *s = N_("month(s)"); gchar *s = N_("label26"); @@ -87,7 +81,33 @@ gchar *s = N_("End on "); gchar *s = N_("End after"); gchar *s = N_("occurrence(s)"); gchar *s = N_("Exceptions"); +gchar *s = N_("Recurrence"); +gchar *s = N_("Appointment Basics"); +gchar *s = N_("Su_mmary:"); +gchar *s = N_("_Starting date:"); +gchar *s = N_("Recurrence Rule"); +gchar *s = N_("No recurrence"); +gchar *s = N_("Simple recurrence"); +gchar *s = N_("Every"); +gchar *s = N_("day(s)"); +gchar *s = N_("week(s)"); +gchar *s = N_("month(s)"); +gchar *s = N_("year(s)"); +gchar *s = N_("for"); +gchar *s = N_("until"); +gchar *s = N_("forever"); +gchar *s = N_("days"); +gchar *s = N_("weeks"); +gchar *s = N_("months"); +gchar *s = N_("years"); +gchar *s = N_("iterations"); +gchar *s = N_("Custom recurrence"); +gchar *s = N_("Exceptions"); gchar *s = N_("Add"); -gchar *s = N_("Change"); +gchar *s = N_("Modify"); gchar *s = N_("Delete"); +gchar *s = N_("label21"); +gchar *s = N_("This appointment has custom recurrence rules that cannot be edited by Evolution.\n" + "\n" + "However, the appointment will recur at the appropriate time and be displayed in the calendar views."); gchar *s = N_("Recurrence"); diff --git a/calendar/gui/event-editor.c b/calendar/gui/event-editor.c index dc90309fe5..e817ebcdf2 100644 --- a/calendar/gui/event-editor.c +++ b/calendar/gui/event-editor.c @@ -30,11 +30,11 @@ #include <cal-util/timeutil.h> #include "event-editor.h" #include "e-meeting-edit.h" - +#include "weekday-picker.h" -typedef struct { +struct _EventEditorPrivate { /* Glade XML data */ GladeXML *xml; @@ -77,6 +77,25 @@ typedef struct { GtkWidget *classification_radio; + GtkWidget *recurrence_summary; + GtkWidget *recurrence_starting_date; + + GtkWidget *recurrence_none; + GtkWidget *recurrence_simple; + GtkWidget *recurrence_custom; + GtkWidget *recurrence_custom_warning; + + GtkWidget *recurrence_params; + GtkWidget *recurrence_interval_value; + GtkWidget *recurrence_interval_unit; + GtkWidget *recurrence_special; + GtkWidget *recurrence_ending_menu; + GtkWidget *recurrence_ending_special; + + /* For weekly recurrences, created by hand */ + GtkWidget *recurrence_weekday_picker; + guint8 recurrence_weekday_day_mask; + GtkWidget *recurrence_rule_notebook; GtkWidget *recurrence_rule_none; GtkWidget *recurrence_rule_daily; @@ -109,15 +128,14 @@ typedef struct { GtkWidget *recurrence_ending_date_end_after; GtkWidget *recurrence_ending_date_end_after_count; - GtkWidget *recurrence_exceptions_date; - GtkWidget *recurrence_exceptions_list; + /* Widgets from the Glade file */ + + GtkWidget *recurrence_exception_date; + GtkWidget *recurrence_exception_list; GtkWidget *recurrence_exception_add; + GtkWidget *recurrence_exception_modify; GtkWidget *recurrence_exception_delete; - GtkWidget *recurrence_exception_change; - - GtkWidget *exception_list; - GtkWidget *exception_date; -} EventEditorPrivate; +}; @@ -140,15 +158,14 @@ static void alarm_toggle (GtkWidget *toggle, EventEditor *ee); static void check_dates (EDateEdit *dedit, EventEditor *ee); static void check_times (EDateEdit *dedit, EventEditor *ee); static void recurrence_toggled (GtkWidget *radio, EventEditor *ee); -static void recurrence_exception_added (GtkWidget *widget, EventEditor *ee); -static void recurrence_exception_deleted (GtkWidget *widget, EventEditor *ee); -static void recurrence_exception_changed (GtkWidget *widget, EventEditor *ee); +static void recurrence_exception_add_cb (GtkWidget *widget, EventEditor *ee); +static void recurrence_exception_modify_cb (GtkWidget *widget, EventEditor *ee); +static void recurrence_exception_delete_cb (GtkWidget *widget, EventEditor *ee); /** * event_editor_get_type: - * @void: * * Registers the #EventEditor class if necessary, and returns the type ID * associated to it. @@ -236,7 +253,7 @@ event_editor_destroy (GtkObject *object) priv->uic = NULL; } - free_exception_clist_data (GTK_CLIST (priv->recurrence_exceptions_list)); + free_exception_clist_data (GTK_CLIST (priv->recurrence_exception_list)); if (priv->app) { gtk_signal_disconnect_by_data (GTK_OBJECT (priv->app), ee); @@ -302,6 +319,189 @@ make_title_from_comp (CalComponent *comp) } } +/* Creates the special contents for weekly recurrences */ +static void +make_recur_weekly_special (EventEditor *ee) +{ + EventEditorPrivate *priv; + GtkWidget *hbox; + GtkWidget *label; + WeekdayPicker *wp; + + priv = ee->priv; + + g_assert (GTK_BIN (priv->recurrence_special)->child == NULL); + g_assert (priv->recurrence_weekday_picker == NULL); + + /* Create the widgets */ + + hbox = gtk_hbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (priv->recurrence_special), hbox); + + label = gtk_label_new (_("on")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + wp = WEEKDAY_PICKER (weekday_picker_new ()); + + priv->recurrence_weekday_picker = GTK_WIDGET (wp); + gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (wp), FALSE, FALSE, 0); + + gtk_widget_show_all (hbox); + + /* Set the weekdays */ + + weekday_picker_set_week_starts_on_monday (wp, week_starts_on_monday); + weekday_picker_set_days (wp, priv->recurrence_weekday_day_mask); +} + +/* Creates the special contents for monthly recurrences */ +static void +make_recur_monthly_special (EventEditor *ee) +{ + /* FIXME: create the "on the" <nth> [day, Weekday, last Weekday] */ +} + +static const int recur_freq_map[] = { + ICAL_DAILY_RECURRENCE, + ICAL_WEEKLY_RECURRENCE, + ICAL_MONTHLY_RECURRENCE, + ICAL_YEARLY_RECURRENCE, + -1 +}; + +/* Changes the recurrence-special widget to match the interval units. + * + * For daily recurrences: nothing. + * For weekly recurrences: weekday selector. + * For monthly recurrences: "on the" <nth> [day, Weekday, last Weekday] + * For yearly recurrences: nothing. + */ +static void +make_recurrence_special (EventEditor *ee) +{ + EventEditorPrivate *priv; + icalrecurrencetype_frequency frequency; + + priv = ee->priv; + + if (GTK_BIN (priv->recurrence_special)->child != NULL) { + gtk_widget_destroy (GTK_BIN (priv->recurrence_special)->child); + + priv->recurrence_weekday_picker = NULL; + } + + frequency = e_dialog_option_menu_get (priv->recurrence_interval_unit, recur_freq_map); + + switch (frequency) { + case ICAL_DAILY_RECURRENCE: + gtk_widget_hide (priv->recurrence_special); + break; + + case ICAL_WEEKLY_RECURRENCE: + make_recur_weekly_special (ee); + gtk_widget_show (priv->recurrence_special); + break; + + case ICAL_MONTHLY_RECURRENCE: + make_recur_monthly_special (ee); + gtk_widget_show (priv->recurrence_special); + break; + + case ICAL_YEARLY_RECURRENCE: + gtk_widget_hide (priv->recurrence_special); + break; + + default: + g_assert_not_reached (); + } +} + +enum ending_type { + ENDING_FOR, + ENDING_UNTIL, + ENDING_FOREVER +}; + +static const int ending_types_map[] = { + ENDING_FOR, + ENDING_UNTIL, + ENDING_FOREVER, + -1 +}; + +/* Changes the recurrence-ending-special widget to match the ending date option. + * + * For: <n> [days, weeks, months, years, occurrences] + * Until: <date selector> + * Forever: nothing. + */ +static void +make_recurrence_ending_special (EventEditor *ee) +{ + /* FIXME */ +} + +enum recur_type { + RECUR_NONE, + RECUR_SIMPLE, + RECUR_CUSTOM +}; + +static const int recur_type_map[] = { + RECUR_NONE, + RECUR_SIMPLE, + RECUR_CUSTOM, + -1 +}; + +/* Callback used when one of the recurrence type radio buttons is toggled. We + * enable or the recurrence parameters. + */ +static void +recurrence_type_toggled_cb (GtkWidget *widget, gpointer data) +{ + EventEditor *ee; + EventEditorPrivate *priv; + enum recur_type type; + + ee = EVENT_EDITOR (data); + priv = ee->priv; + + type = e_dialog_radio_get (widget, recur_type_map); + + switch (type) { + case RECUR_NONE: + gtk_widget_set_sensitive (priv->recurrence_params, FALSE); + gtk_widget_hide (priv->recurrence_custom_warning); + break; + + case RECUR_SIMPLE: + gtk_widget_set_sensitive (priv->recurrence_params, TRUE); + gtk_widget_hide (priv->recurrence_custom_warning); + break; + + case RECUR_CUSTOM: + gtk_widget_set_sensitive (priv->recurrence_params, FALSE); + gtk_widget_show (priv->recurrence_custom_warning); + break; + + default: + g_assert_not_reached (); + } +} + +/* Callback used when the recurrence interval option menu changes. We need to + * change the contents of the recurrence special widget. + */ +static void +recur_interval_selection_done_cb (GtkMenuShell *menu_shell, gpointer data) +{ + EventEditor *ee; + + ee = EVENT_EDITOR (data); + make_recurrence_special (ee); +} + /* Gets the widgets from the XML file and returns if they are all available. * For the widgets whose values can be simply set with e-dialog-utils, it does * that as well. @@ -343,6 +543,21 @@ get_widgets (EventEditor *ee) priv->classification_radio = GW ("classification-radio"); + priv->recurrence_summary = GW ("recurrence-summary"); + priv->recurrence_starting_date = GW ("recurrence-starting-date"); + + priv->recurrence_none = GW ("recurrence-none"); + priv->recurrence_simple = GW ("recurrence-simple"); + priv->recurrence_custom = GW ("recurrence-custom"); + priv->recurrence_custom_warning = GW ("recurrence-custom-warning"); + priv->recurrence_params = GW ("recurrence-params"); + + priv->recurrence_interval_value = GW ("recurrence-interval-value"); + priv->recurrence_interval_unit = GW ("recurrence-interval-unit"); + priv->recurrence_special = GW ("recurrence-special"); + priv->recurrence_ending_menu = GW ("recurrence-ending-menu"); + priv->recurrence_ending_special = GW ("recurrence-ending-special"); + priv->recurrence_rule_notebook = GW ("recurrence-rule-notebook"); priv->recurrence_rule_none = GW ("recurrence-rule-none"); priv->recurrence_rule_daily = GW ("recurrence-rule-daily"); @@ -375,14 +590,11 @@ get_widgets (EventEditor *ee) priv->recurrence_ending_date_end_after = GW ("recurrence-ending-date-end-after"); priv->recurrence_ending_date_end_after_count = GW ("recurrence-ending-date-end-after-count"); - priv->recurrence_exceptions_date = GW ("recurrence-exceptions-date"); - priv->recurrence_exceptions_list = GW ("recurrence-exceptions-list"); - priv->recurrence_exception_add = GW ("recurrence-exceptions-add"); - priv->recurrence_exception_delete = GW ("recurrence-exceptions-delete"); - priv->recurrence_exception_change = GW ("recurrence-exceptions-change"); - - priv->exception_list = GW ("recurrence-exceptions-list"); - priv->exception_date = GW ("recurrence-exceptions-date"); + priv->recurrence_exception_date = GW ("recurrence-exception-date"); + priv->recurrence_exception_list = GW ("recurrence-exception-list"); + priv->recurrence_exception_add = GW ("recurrence-exception-add"); + priv->recurrence_exception_modify = GW ("recurrence-exception-modify"); + priv->recurrence_exception_delete = GW ("recurrence-exception-delete"); #undef GW @@ -407,6 +619,19 @@ get_widgets (EventEditor *ee) && priv->alarm_mail_unit && priv->alarm_mail_mail_to && priv->classification_radio + && priv->recurrence_summary + && priv->recurrence_starting_date + && priv->recurrence_none + && priv->recurrence_simple + && priv->recurrence_custom + && priv->recurrence_custom_warning + && priv->recurrence_params + && priv->recurrence_interval_value + && priv->recurrence_interval_unit + && priv->recurrence_special + && priv->recurrence_ending_menu + && priv->recurrence_ending_special + && priv->recurrence_rule_notebook && priv->recurrence_rule_none && priv->recurrence_rule_daily @@ -427,69 +652,20 @@ get_widgets (EventEditor *ee) && priv->recurrence_ending_date_end_on_date && priv->recurrence_ending_date_end_after && priv->recurrence_ending_date_end_after_count - && priv->recurrence_exceptions_date - && priv->recurrence_exceptions_list - && priv->recurrence_exception_add - && priv->recurrence_exception_delete - && priv->recurrence_exception_change - && priv->exception_list - && priv->exception_date); -} - - - -static const int classification_map[] = { - CAL_COMPONENT_CLASS_PUBLIC, - CAL_COMPONENT_CLASS_PRIVATE, - CAL_COMPONENT_CLASS_CONFIDENTIAL, - -1 -}; - -#if 0 -static const int alarm_unit_map[] = { - ALARM_MINUTES, - ALARM_HOURS, - ALARM_DAYS, - -1 -}; - -static void -alarm_unit_set (GtkWidget *widget, enum AlarmUnit unit) -{ - e_dialog_option_menu_set (widget, unit, alarm_unit_map); -} - -static enum AlarmUnit -alarm_unit_get (GtkWidget *widget) -{ - return e_dialog_option_menu_get (widget, alarm_unit_map); -} -#endif -/* Recurrence types for mapping them to radio buttons */ -static const int recur_options_map[] = { - ICAL_NO_RECURRENCE, - ICAL_DAILY_RECURRENCE, - ICAL_WEEKLY_RECURRENCE, - ICAL_MONTHLY_RECURRENCE, - ICAL_YEARLY_RECURRENCE, - -1 -}; - -static icalrecurrencetype_frequency -recur_options_get (GtkWidget *widget) -{ - return e_dialog_radio_get (widget, recur_options_map); + && priv->recurrence_exception_date + && priv->recurrence_exception_list + && priv->recurrence_exception_add + && priv->recurrence_exception_modify + && priv->recurrence_exception_delete); } -static const int month_pos_map[] = { 0, 1, 2, 3, 4, -1 }; -static const int weekday_map[] = { 0, 1, 2, 3, 4, 5, 6, -1 }; - /* Hooks the widget signals */ static void init_widgets (EventEditor *ee) { EventEditorPrivate *priv; + GtkWidget *menu; priv = ee->priv; @@ -521,6 +697,23 @@ init_widgets (EventEditor *ee) /* Recurrence types */ + gtk_signal_connect (GTK_OBJECT (priv->recurrence_none), "toggled", + GTK_SIGNAL_FUNC (recurrence_type_toggled_cb), ee); + gtk_signal_connect (GTK_OBJECT (priv->recurrence_simple), "toggled", + GTK_SIGNAL_FUNC (recurrence_type_toggled_cb), ee); + gtk_signal_connect (GTK_OBJECT (priv->recurrence_custom), "toggled", + GTK_SIGNAL_FUNC (recurrence_type_toggled_cb), ee); + + /* Recurrence units */ + + menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->recurrence_interval_unit)); + g_assert (menu != NULL); + + gtk_signal_connect (GTK_OBJECT (menu), "selection_done", + GTK_SIGNAL_FUNC (recur_interval_selection_done_cb), ee); + + /* Recurrence types */ + gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_none), "toggled", GTK_SIGNAL_FUNC (recurrence_toggled), ee); gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_daily), "toggled", @@ -535,12 +728,59 @@ init_widgets (EventEditor *ee) /* Exception buttons */ gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_add), "clicked", - GTK_SIGNAL_FUNC (recurrence_exception_added), ee); + GTK_SIGNAL_FUNC (recurrence_exception_add_cb), ee); + gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_modify), "clicked", + GTK_SIGNAL_FUNC (recurrence_exception_modify_cb), ee); gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_delete), "clicked", - GTK_SIGNAL_FUNC (recurrence_exception_deleted), ee); - gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_change), "clicked", - GTK_SIGNAL_FUNC (recurrence_exception_changed), ee); + GTK_SIGNAL_FUNC (recurrence_exception_delete_cb), ee); +} + +static const int classification_map[] = { + CAL_COMPONENT_CLASS_PUBLIC, + CAL_COMPONENT_CLASS_PRIVATE, + CAL_COMPONENT_CLASS_CONFIDENTIAL, + -1 +}; + +#if 0 +static const int alarm_unit_map[] = { + ALARM_MINUTES, + ALARM_HOURS, + ALARM_DAYS, + -1 +}; + +static void +alarm_unit_set (GtkWidget *widget, enum AlarmUnit unit) +{ + e_dialog_option_menu_set (widget, unit, alarm_unit_map); +} + +static enum AlarmUnit +alarm_unit_get (GtkWidget *widget) +{ + return e_dialog_option_menu_get (widget, alarm_unit_map); } +#endif + +/* Recurrence types for mapping them to radio buttons */ +static const int recur_options_map[] = { + ICAL_NO_RECURRENCE, + ICAL_DAILY_RECURRENCE, + ICAL_WEEKLY_RECURRENCE, + ICAL_MONTHLY_RECURRENCE, + ICAL_YEARLY_RECURRENCE, + -1 +}; + +static icalrecurrencetype_frequency +recur_options_get (GtkWidget *widget) +{ + return e_dialog_radio_get (widget, recur_options_map); +} + +static const int month_pos_map[] = { 0, 1, 2, 3, 4, -1 }; +static const int weekday_map[] = { 0, 1, 2, 3, 4, 5, 6, -1 }; /* Fills the widgets with default values */ static void @@ -573,7 +813,7 @@ clear_widgets (EventEditor *ee) /* Alarms */ - /* FIXMe: these should use configurable defaults */ + /* FIXME: these should use configurable defaults */ e_dialog_toggle_set (priv->alarm_display, FALSE); e_dialog_toggle_set (priv->alarm_program, FALSE); @@ -597,11 +837,24 @@ clear_widgets (EventEditor *ee) /* Classification */ - e_dialog_radio_set (priv->classification_radio, + e_dialog_radio_set (priv->classification_radio, CAL_COMPONENT_CLASS_PRIVATE, classification_map); /* Recurrences */ + priv->recurrence_weekday_day_mask = 0; + + e_dialog_radio_set (priv->recurrence_none, RECUR_NONE, recur_type_map); + + e_dialog_spin_set (priv->recurrence_interval_value, 1); + e_dialog_option_menu_set (priv->recurrence_interval_unit, ICAL_DAILY_RECURRENCE, + recur_freq_map); + + e_dialog_option_menu_set (priv->recurrence_ending_menu, ENDING_FOREVER, + ending_types_map); + + /* Old recurrences */ + e_dialog_radio_set (priv->recurrence_rule_none, ICAL_NO_RECURRENCE, recur_options_map); e_dialog_spin_set (priv->recurrence_rule_daily_days, 1); @@ -630,10 +883,197 @@ clear_widgets (EventEditor *ee) /* Exceptions list */ - free_exception_clist_data (GTK_CLIST (priv->recurrence_exceptions_list)); + free_exception_clist_data (GTK_CLIST (priv->recurrence_exception_list)); +} + +/* Counts the number of elements in the by_xxx fields of an icalrecurrencetype */ +static int +count_by_xxx (short *field, int max_elements) +{ + int i; + + for (i = 0; i < max_elements; i++) + if (field[i] == SHRT_MAX) + break; + + return i; +} + +/* Fills in the recurrence widgets with the values from the calendar component. + * This function is particularly tricky because it has to discriminate between + * recurrences we support for editing and the ones we don't. We only support at + * most one recurrence rule; no rdates or exrules (exdates are handled just fine + * elsewhere). + */ +static void +fill_recurrence_widgets (EventEditor *ee) +{ + EventEditorPrivate *priv; + GSList *rrule_list; + int len; + struct icalrecurrencetype *r; + int n_by_second, n_by_minute, n_by_hour; + int n_by_day, n_by_month_day, n_by_year_day; + int n_by_week_no, n_by_month, n_by_set_pos; + + priv = ee->priv; + g_assert (priv->comp != NULL); + + /* No recurrences? */ + + if (!cal_component_has_rdates (priv->comp) + && !cal_component_has_rrules (priv->comp) + && !cal_component_has_exrules (priv->comp)) { + e_dialog_radio_set (priv->recurrence_none, RECUR_NONE, recur_type_map); + return; + } + + /* See if it is a custom set we don't support */ + + cal_component_get_rrule_list (priv->comp, &rrule_list); + len = g_slist_length (rrule_list); + + if (len > 1 + || cal_component_has_rdates (priv->comp) + || cal_component_has_exrules (priv->comp)) + goto custom; + + /* Down to one rule, so test that one */ + + g_assert (len == 1); + r = rrule_list->data; + + /* Any funky frequency? */ + + if (r->freq == ICAL_SECONDLY_RECURRENCE + || r->freq == ICAL_MINUTELY_RECURRENCE + || r->freq == ICAL_HOURLY_RECURRENCE) + goto custom; + + /* Any funky shit? */ + +#define N_HAS_BY(field) (count_by_xxx (field, sizeof (field) / sizeof (field[0]))) + + n_by_second = N_HAS_BY (r->by_second); + n_by_minute = N_HAS_BY (r->by_minute); + n_by_hour = N_HAS_BY (r->by_hour); + n_by_day = N_HAS_BY (r->by_day); + n_by_month_day = N_HAS_BY (r->by_month_day); + n_by_year_day = N_HAS_BY (r->by_year_day); + n_by_week_no = N_HAS_BY (r->by_week_no); + n_by_month = N_HAS_BY (r->by_month); + n_by_set_pos = N_HAS_BY (r->by_set_pos); + + if (n_by_second != 0 + || n_by_minute != 0 + || n_by_hour != 0) + goto custom; + + /* Filter the funky shit based on the frequency; if there is nothing + * weird we can actually set the widgets. + */ + + switch (r->freq) { + case ICAL_DAILY_RECURRENCE: + if (n_by_day != 0 + || n_by_month_day != 0 + || n_by_year_day != 0 + || n_by_week_no != 0 + || n_by_month != 0 + || n_by_set_pos != 0) + goto custom; + + e_dialog_option_menu_set (priv->recurrence_interval_unit, ICAL_DAILY_RECURRENCE, + recur_freq_map); + break; + + case ICAL_WEEKLY_RECURRENCE: { + int i; + guint8 day_mask; + + if (n_by_month_day != 0 + || n_by_year_day != 0 + || n_by_week_no != 0 + || n_by_month != 0 + || n_by_set_pos != 0) + goto custom; + + day_mask = 0; + + for (i = 0; i < 8 && r->by_day[i] != SHRT_MAX; i++) { + enum icalrecurrencetype_weekday weekday; + int pos; + + weekday = icalrecurrencetype_day_day_of_week (r->by_day[i]); + pos = icalrecurrencetype_day_position (r->by_day[i]); + + if (pos != 0) + goto custom; + + switch (weekday) { + case ICAL_SUNDAY_WEEKDAY: + day_mask |= 1 << 0; + break; + + case ICAL_MONDAY_WEEKDAY: + day_mask |= 1 << 1; + break; + + case ICAL_TUESDAY_WEEKDAY: + day_mask |= 1 << 2; + break; + + case ICAL_WEDNESDAY_WEEKDAY: + day_mask |= 1 << 3; + break; + + case ICAL_THURSDAY_WEEKDAY: + day_mask |= 1 << 4; + break; + + case ICAL_FRIDAY_WEEKDAY: + day_mask |= 1 << 5; + break; + + case ICAL_SATURDAY_WEEKDAY: + day_mask |= 1 << 6; + break; + + default: + break; + } + } + + priv->recurrence_weekday_day_mask = day_mask; + + e_dialog_option_menu_set (priv->recurrence_interval_unit, ICAL_WEEKLY_RECURRENCE, + recur_freq_map); + break; + } + + case ICAL_MONTHLY_RECURRENCE: + + default: + goto custom; + } + + /* If we got here it means it is a simple recurrence */ + + e_dialog_radio_set (priv->recurrence_simple, RECUR_SIMPLE, recur_type_map); + e_dialog_spin_set (priv->recurrence_interval_value, r->interval); + + goto out; + + custom: + + e_dialog_radio_set (priv->recurrence_custom, RECUR_CUSTOM, recur_type_map); + + out: + + cal_component_free_recur_list (rrule_list); } -/* Fills in the widgets with the proper values */ +/* Fills in the widgets with the value from the calendar component */ static void fill_widgets (EventEditor *ee) { @@ -728,6 +1168,11 @@ fill_widgets (EventEditor *ee) } /* Recurrences */ + + fill_recurrence_widgets (ee); + +#if 0 + #ifndef NO_WARNINGS #warning "FIX ME" #endif @@ -843,12 +1288,12 @@ fill_widgets (EventEditor *ee) cal_component_free_recur_list (list); } - /* Exceptions list */ -#ifndef NO_WARNINGS -#warning "FIX ME" #endif - /* Need to handle exception rules as well as dates */ + + /* Exceptions list */ + cal_component_get_exdate_list (priv->comp, &list); + for (l = list; l; l = l->next) { struct icaltimetype *t; time_t ext; @@ -857,16 +1302,25 @@ fill_widgets (EventEditor *ee) ext = icaltime_as_timet (*t); append_exception (ee, ext); } + cal_component_free_exdate_list (list); } -/* Tell the event editor to reread its widget values from the associated - CalComponent object. If one changes the CalComponent through a means other - than the GUI, one should call this function. */ +/** + * event_editor_update_widgets: + * @ee: An event editor. + * + * Causes an event editor dialog to re-read the values of its calendar component + * object. This function should be used if the #CalComponent is changed by + * external means while it is open in the editor. + **/ void event_editor_update_widgets (EventEditor *ee) { + g_return_if_fail (ee != NULL); + g_return_if_fail (IS_EVENT_EDITOR (ee)); + fill_widgets (ee); } @@ -879,7 +1333,141 @@ classification_get (GtkWidget *widget) return e_dialog_radio_get (widget, classification_map); } -/* Get the values of the widgets in the event editor and put them in the iCalObject */ +/* Gets the simple recurrence data from the recurrence widgets and stores it in + * the calendar component object. + */ +static void +simple_recur_to_comp_object (EventEditor *ee) +{ + EventEditorPrivate *priv; + struct icalrecurrencetype r; + guint8 day_mask; + int i; + GSList l; + enum ending_type ending_type; + + priv = ee->priv; + + icalrecurrencetype_clear (&r); + + /* Frequency and interval */ + + r.freq = e_dialog_option_menu_get (priv->recurrence_interval_unit, recur_freq_map); + r.interval = e_dialog_spin_get_int (priv->recurrence_interval_value); + + /* Frequency-specific data */ + + switch (r.freq) { + case ICAL_DAILY_RECURRENCE: + break; + + case ICAL_WEEKLY_RECURRENCE: + g_assert (GTK_BIN (priv->recurrence_special)->child != NULL); + g_assert (GTK_BIN (priv->recurrence_special)->child + == priv->recurrence_weekday_picker); + g_assert (IS_WEEKDAY_PICKER (priv->recurrence_weekday_picker)); + + day_mask = weekday_picker_get_days (WEEKDAY_PICKER (priv->recurrence_weekday_picker)); + + i = 0; + + if (day_mask & (1 << 0)) + r.by_day[i++] = ICAL_SUNDAY_WEEKDAY; + + if (day_mask & (1 << 1)) + r.by_day[i++] = ICAL_MONDAY_WEEKDAY; + + if (day_mask & (1 << 2)) + r.by_day[i++] = ICAL_TUESDAY_WEEKDAY; + + if (day_mask & (1 << 3)) + r.by_day[i++] = ICAL_WEDNESDAY_WEEKDAY; + + if (day_mask & (1 << 4)) + r.by_day[i++] = ICAL_THURSDAY_WEEKDAY; + + if (day_mask & (1 << 5)) + r.by_day[i++] = ICAL_FRIDAY_WEEKDAY; + + if (day_mask & (1 << 6)) + r.by_day[i++] = ICAL_SATURDAY_WEEKDAY; + + break; + + case ICAL_MONTHLY_RECURRENCE: + /* FIXME */ + break; + + case ICAL_YEARLY_RECURRENCE: + break; + + default: + g_assert_not_reached (); + } + + /* Ending date */ + + ending_type = e_dialog_option_menu_get (priv->recurrence_ending_menu, ending_types_map); + + switch (ending_type) { + case ENDING_FOR: + /* FIXME */ + break; + + case ENDING_UNTIL: + /* FIXME */ + break; + + case ENDING_FOREVER: + break; + + default: + g_assert_not_reached (); + } + + /* Set the recurrence */ + + l.data = &r; + l.next = NULL; + + cal_component_set_rrule_list (priv->comp, &l); +} + +/* Gets the data from the recurrence widgets and stores it in the calendar + * component object. + */ +static void +recur_to_comp_object (EventEditor *ee) +{ + EventEditorPrivate *priv; + enum recur_type recur_type; + + priv = ee->priv; + g_assert (priv->comp != NULL); + + recur_type = e_dialog_radio_get (priv->recurrence_none, recur_type_map); + + switch (recur_type) { + case RECUR_NONE: + cal_component_set_rdate_list (priv->comp, NULL); + cal_component_set_rrule_list (priv->comp, NULL); + cal_component_set_exrule_list (priv->comp, NULL); + break; + + case RECUR_SIMPLE: + simple_recur_to_comp_object (ee); + break; + + case RECUR_CUSTOM: + /* We just keep whatever the component has currently */ + break; + + default: + g_assert_not_reached (); + } +} + +/* Gets the data from the widgets and stores it in the calendar component object */ static void dialog_to_comp_object (EventEditor *ee) { @@ -887,14 +1475,15 @@ dialog_to_comp_object (EventEditor *ee) CalComponent *comp; CalComponentText *text; CalComponentDateTime date; - struct icalrecurrencetype recur; time_t t; gboolean all_day_event; GtkCList *exception_list; GSList *list; - int i, pos = 0; + int i; priv = ee->priv; + g_assert (priv->comp != NULL); + comp = priv->comp; text = g_new0 (CalComponentText, 1); @@ -953,6 +1542,10 @@ dialog_to_comp_object (EventEditor *ee) cal_component_set_classification (comp, classification_get (priv->classification_radio)); /* Recurrence information */ + + recur_to_comp_object (ee); + +#if 0 icalrecurrencetype_clear (&recur); recur.freq = recur_options_get (priv->recurrence_rule_none); @@ -967,7 +1560,9 @@ dialog_to_comp_object (EventEditor *ee) case ICAL_WEEKLY_RECURRENCE: recur.interval = e_dialog_spin_get_int (priv->recurrence_rule_weekly_weeks); - + + pos = 0; + if (e_dialog_toggle_get (priv->recurrence_rule_weekly_sun)) recur.by_day[pos++] = ICAL_SUNDAY_WEEKDAY; if (e_dialog_toggle_get (priv->recurrence_rule_weekly_mon)) @@ -1044,10 +1639,10 @@ dialog_to_comp_object (EventEditor *ee) list = NULL; cal_component_set_rrule_list (comp, list); } - +#endif /* Set exceptions */ list = NULL; - exception_list = GTK_CLIST (priv->recurrence_exceptions_list); + exception_list = GTK_CLIST (priv->recurrence_exception_list); for (i = 0; i < exception_list->rows; i++) { struct icaltimetype *tt; time_t *t; @@ -1065,6 +1660,9 @@ dialog_to_comp_object (EventEditor *ee) cal_component_commit_sequence (comp); } +/* Fills the calendar component object from the data in the widgets and commits + * the component to the storage. + */ static void save_event_object (EventEditor *ee) { @@ -1194,7 +1792,6 @@ schedule_meeting_cb (GtkWidget *widget, gpointer data) * this and the task-editor. */ static BonoboUIVerb verbs [] = { - BONOBO_UI_UNSAFE_VERB ("FileSave", file_save_cb), BONOBO_UI_UNSAFE_VERB ("FileDelete", file_delete_cb), BONOBO_UI_UNSAFE_VERB ("FileClose", file_close_cb), @@ -1292,8 +1889,7 @@ event_editor_construct (EventEditor *ee) priv->uic, bonobo_object_corba_objref (BONOBO_OBJECT (container))); } - bonobo_ui_component_add_verb_list_with_data ( - priv->uic, verbs, ee); + bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, ee); bonobo_ui_util_set_ui (priv->uic, EVOLUTION_DATADIR, "evolution-event-editor.xml", @@ -1421,6 +2017,14 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data) raise_and_focus (priv->app); } +/** + * event_editor_set_cal_client: + * @ee: An event editor. + * @client: Calendar client. + * + * Sets the calendar client than an event editor will use for updating its + * calendar components. + **/ void event_editor_set_cal_client (EventEditor *ee, CalClient *client) { @@ -1459,6 +2063,27 @@ event_editor_set_cal_client (EventEditor *ee, CalClient *client) } /** + * event_editor_get_cal_client: + * @ee: An event editor. + * + * Queries the calendar client that an event editor is using to update its + * calendar components. + * + * Return value: A calendar client object. + **/ +CalClient * +event_editor_get_cal_client (EventEditor *ee) +{ + EventEditorPrivate *priv; + + g_return_val_if_fail (ee != NULL, NULL); + g_return_val_if_fail (IS_EVENT_EDITOR (ee), NULL); + + priv = ee->priv; + return priv->client; +} + +/** * event_editor_set_event_object: * @ee: An event editor. * @comp: A calendar object. @@ -1736,11 +2361,11 @@ recurrence_toggled (GtkWidget *radio, EventEditor *ee) rf = e_dialog_radio_get (radio, recur_options_map); /* This is a hack to get things working */ - gtk_notebook_set_page (GTK_NOTEBOOK (priv->recurrence_rule_notebook), + gtk_notebook_set_page (GTK_NOTEBOOK (priv->recurrence_rule_notebook), (int) (rf - ICAL_HOURLY_RECURRENCE)); } - +/* Builds a static string out of an exception date */ static char * get_exception_string (time_t t) { @@ -1750,7 +2375,7 @@ get_exception_string (time_t t) return buf; } - +/* Appends an exception date to the list */ static void append_exception (EventEditor *ee, time_t t) { @@ -1765,7 +2390,7 @@ append_exception (EventEditor *ee, time_t t) tt = g_new (time_t, 1); *tt = t; - clist = GTK_CLIST (priv->recurrence_exceptions_list); + clist = GTK_CLIST (priv->recurrence_exception_list); c[0] = get_exception_string (t); i = e_utf8_gtk_clist_append (clist, c); @@ -1773,68 +2398,75 @@ append_exception (EventEditor *ee, time_t t) gtk_clist_set_row_data (clist, i, tt); gtk_clist_select_row (clist, i, 0); -/* gtk_widget_set_sensitive (ee->recur_ex_vbox, TRUE); */ + gtk_widget_set_sensitive (priv->recurrence_exception_modify, TRUE); + gtk_widget_set_sensitive (priv->recurrence_exception_delete, TRUE); } +/* Callback for the "add exception" button */ static void -recurrence_exception_added (GtkWidget *widget, EventEditor *ee) +recurrence_exception_add_cb (GtkWidget *widget, EventEditor *ee) { EventEditorPrivate *priv; time_t t; priv = ee->priv; - t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exceptions_date)); + t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exception_date)); append_exception (ee, t); } - +/* Callback for the "modify exception" button */ static void -recurrence_exception_deleted (GtkWidget *widget, EventEditor *ee) +recurrence_exception_modify_cb (GtkWidget *widget, EventEditor *ee) { EventEditorPrivate *priv; GtkCList *clist; + time_t *t; int sel; priv = ee->priv; - clist = GTK_CLIST (priv->recurrence_exceptions_list); + clist = GTK_CLIST (priv->recurrence_exception_list); if (!clist->selection) return; sel = GPOINTER_TO_INT (clist->selection->data); - g_free (gtk_clist_get_row_data (clist, sel)); /* free the time_t stored there */ - - gtk_clist_remove (clist, sel); - if (sel >= clist->rows) - sel--; + t = gtk_clist_get_row_data (clist, sel); + *t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exception_date)); - gtk_clist_select_row (clist, sel, 0); + e_utf8_gtk_clist_set_text (clist, sel, 0, get_exception_string (*t)); } - +/* Callback for the "delete exception" button */ static void -recurrence_exception_changed (GtkWidget *widget, EventEditor *ee) +recurrence_exception_delete_cb (GtkWidget *widget, EventEditor *ee) { EventEditorPrivate *priv; GtkCList *clist; - time_t *t; int sel; priv = ee->priv; - clist = GTK_CLIST (priv->recurrence_exceptions_list); + clist = GTK_CLIST (priv->recurrence_exception_list); if (!clist->selection) return; sel = GPOINTER_TO_INT (clist->selection->data); - t = gtk_clist_get_row_data (clist, sel); - *t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exceptions_date)); + g_free (gtk_clist_get_row_data (clist, sel)); /* free the time_t stored there */ - e_utf8_gtk_clist_set_text (clist, sel, 0, get_exception_string (*t)); + gtk_clist_remove (clist, sel); + if (sel >= clist->rows) + sel--; + + if (clist->rows > 0) + gtk_clist_select_row (clist, sel, 0); + else { + gtk_widget_set_sensitive (priv->recurrence_exception_modify, FALSE); + gtk_widget_set_sensitive (priv->recurrence_exception_delete, FALSE); + } } @@ -1882,9 +2514,6 @@ make_spin_button (int val, int low, int high) /* todo - build some of the recur stuff by hand to take into account - the start-on-monday preference? - get the apply button to work right make the properties stuff unglobal diff --git a/calendar/gui/event-editor.h b/calendar/gui/event-editor.h index b978eb8cd5..0c7e1f34c7 100644 --- a/calendar/gui/event-editor.h +++ b/calendar/gui/event-editor.h @@ -39,12 +39,13 @@ typedef struct _EventEditor EventEditor; typedef struct _EventEditorClass EventEditorClass; +typedef struct _EventEditorPrivate EventEditorPrivate; struct _EventEditor { GtkObject object; /* Private data */ - gpointer priv; + EventEditorPrivate *priv; }; struct _EventEditorClass { @@ -58,6 +59,8 @@ EventEditor *event_editor_construct (EventEditor *ee); EventEditor *event_editor_new (void); void event_editor_set_cal_client (EventEditor *ee, CalClient *client); +CalClient *event_editor_get_cal_client (EventEditor *ee); + void event_editor_set_event_object (EventEditor *ee, CalComponent *comp); void event_editor_focus (EventEditor *ee); diff --git a/calendar/gui/weekday-picker.c b/calendar/gui/weekday-picker.c index 1898ebc2b8..a9a0d50c7c 100644 --- a/calendar/gui/weekday-picker.c +++ b/calendar/gui/weekday-picker.c @@ -238,10 +238,10 @@ colorize_items (WeekdayPicker *wp) outline = >K_WIDGET (wp)->style->fg[GTK_WIDGET_STATE (wp)]; fill = >K_WIDGET (wp)->style->base[GTK_WIDGET_STATE (wp)]; - text_fill = >K_WIDGET (wp)->style->fg_gc[GTK_WIDGET_STATE (wp)]; + text_fill = >K_WIDGET (wp)->style->fg[GTK_WIDGET_STATE (wp)]; sel_fill = >K_WIDGET (wp)->style->bg[GTK_STATE_SELECTED]; - sel_text_fill = >K_WIDGET (wp)->style->fg_gc[GTK_STATE_SELECTED]; + sel_text_fill = >K_WIDGET (wp)->style->fg[GTK_STATE_SELECTED]; if (priv->week_starts_on_monday) { GdkColor *f, *t; |