diff options
author | Federico Mena Quintero <federico@helixcode.com> | 2000-10-27 12:09:34 +0800 |
---|---|---|
committer | Federico Mena Quintero <federico@src.gnome.org> | 2000-10-27 12:09:34 +0800 |
commit | 0670283434a985fd13c381e3e5081cc8ec7555d1 (patch) | |
tree | 3f6fe6d9cc1802e7bf542f97c4347c89aa013689 /calendar/gui | |
parent | b234a3141bf6607ac8f4a980637d5f63e9b74511 (diff) | |
download | gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.tar gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.tar.gz gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.tar.bz2 gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.tar.lz gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.tar.xz gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.tar.zst gsoc2013-evolution-0670283434a985fd13c381e3e5081cc8ec7555d1.zip |
This is the new recurrence page, partially finished. I just want it on CVS
This is the new recurrence page, partially finished. I just want
it on CVS for if my laptop explodes.
This is highly disgusting code. It has to discriminate between the
recurrence types we support and the ones we do not.
I hate iCalendar. I hate it more than Hi-Fi\'s pizza.
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.
svn path=/trunk/; revision=6219
Diffstat (limited to 'calendar/gui')
-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 |
6 files changed, 1452 insertions, 249 deletions
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; |