2 * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "evolution-config.h"
21 #include <glib/gi18n-lib.h>
24 #include <libedataserver/libedataserver.h>
25 #include <camel/camel.h>
26 #include <e-util/e-util.h>
28 #include "comp-util.h"
29 #include "e-comp-editor.h"
30 #include "e-comp-editor-page.h"
31 #include "e-meeting-list-view.h"
32 #include "itip-utils.h"
34 #include "e-comp-editor-page-general.h"
36 struct _ECompEditorPageGeneralPrivate
{
37 GtkWidget
*source_label
;
38 GtkWidget
*source_combo_box
;
39 GtkWidget
*organizer_label
;
40 GtkWidget
*organizer_combo_box
;
41 GtkWidget
*organizer_hbox
;
42 GtkWidget
*attendees_button
;
43 GtkWidget
*attendees_hbox
;
44 GtkWidget
*attendees_list_view
;
45 GtkWidget
*attendees_button_box
;
46 GtkWidget
*attendees_button_add
;
47 GtkWidget
*attendees_button_edit
;
48 GtkWidget
*attendees_button_remove
;
50 gint data_column_width
;
51 gchar
*source_label_text
;
52 gchar
*source_extension_name
;
53 ESource
*select_source
;
54 gboolean show_attendees
;
56 EMeetingStore
*meeting_store
;
57 GSList
*orig_attendees
; /* gchar *mail_addresses */
58 gchar
*user_delegator
;
63 PROP_DATA_COLUMN_WIDTH
,
65 PROP_SOURCE_EXTENSION_NAME
,
70 G_DEFINE_TYPE (ECompEditorPageGeneral
, e_comp_editor_page_general
, E_TYPE_COMP_EDITOR_PAGE
)
72 static void ecep_general_sensitize_widgets (ECompEditorPage
*page
,
73 gboolean force_insensitive
);
76 ecep_general_set_column_visible (ECompEditorPageGeneral
*page_general
,
77 EMeetingStoreColumns column
,
80 EMeetingListView
*meeting_list_view
;
82 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
84 meeting_list_view
= E_MEETING_LIST_VIEW (page_general
->priv
->attendees_list_view
);
85 e_meeting_list_view_column_set_visible (meeting_list_view
, column
, visible
);
89 action_view_role_cb (GtkToggleAction
*action
,
90 ECompEditorPageGeneral
*page_general
)
92 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
94 ecep_general_set_column_visible (page_general
, E_MEETING_STORE_ROLE_COL
,
95 gtk_toggle_action_get_active (action
));
99 action_view_rsvp_cb (GtkToggleAction
*action
,
100 ECompEditorPageGeneral
*page_general
)
102 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
104 ecep_general_set_column_visible (page_general
, E_MEETING_STORE_RSVP_COL
,
105 gtk_toggle_action_get_active (action
));
109 action_view_status_cb (GtkToggleAction
*action
,
110 ECompEditorPageGeneral
*page_general
)
112 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
114 ecep_general_set_column_visible (page_general
, E_MEETING_STORE_STATUS_COL
,
115 gtk_toggle_action_get_active (action
));
119 action_view_type_cb (GtkToggleAction
*action
,
120 ECompEditorPageGeneral
*page_general
)
122 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
124 ecep_general_set_column_visible (page_general
, E_MEETING_STORE_TYPE_COL
,
125 gtk_toggle_action_get_active (action
));
129 ecep_general_fill_organizer_combo_box (ECompEditorPageGeneral
*page_general
)
131 GtkComboBoxText
*combo_box_text
;
132 ECompEditor
*comp_editor
;
134 ESourceRegistry
*registry
;
135 gchar
**address_strings
;
138 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
139 g_return_if_fail (GTK_IS_COMBO_BOX_TEXT (page_general
->priv
->organizer_combo_box
));
141 combo_box_text
= GTK_COMBO_BOX_TEXT (page_general
->priv
->organizer_combo_box
);
142 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
143 shell
= e_comp_editor_get_shell (comp_editor
);
144 registry
= e_shell_get_registry (shell
);
145 address_strings
= itip_get_user_identities (registry
);
147 for (ii
= 0; address_strings
&& address_strings
[ii
]; ii
++) {
148 gtk_combo_box_text_append_text (combo_box_text
, address_strings
[ii
]);
151 gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box_text
), 0);
153 g_strfreev (address_strings
);
154 g_clear_object (&comp_editor
);
158 ecep_general_source_combo_box_changed_cb (ESourceComboBox
*source_combo_box
,
159 ECompEditorPageGeneral
*page_general
)
163 g_return_if_fail (E_IS_SOURCE_COMBO_BOX (source_combo_box
));
164 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
166 source
= e_source_combo_box_ref_active (source_combo_box
);
167 e_comp_editor_page_general_set_selected_source (page_general
, source
);
168 g_clear_object (&source
);
172 ecep_general_attendees_clicked_cb (GtkWidget
*widget
,
173 ECompEditorPageGeneral
*page_general
)
175 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
177 e_meeting_list_view_invite_others_dialog (E_MEETING_LIST_VIEW (page_general
->priv
->attendees_list_view
));
181 ecep_general_attendees_add_clicked_cb (GtkButton
*button
,
182 ECompEditorPageGeneral
*page_general
)
184 ECompEditor
*comp_editor
;
185 EMeetingAttendee
*attendee
;
188 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
190 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
191 flags
= e_comp_editor_get_flags (comp_editor
);
193 attendee
= e_meeting_store_add_attendee_with_defaults (page_general
->priv
->meeting_store
);
195 if ((flags
& E_COMP_EDITOR_FLAG_DELEGATE
) != 0)
196 e_meeting_attendee_set_delfrom (attendee
, g_strdup_printf ("MAILTO:%s",
197 page_general
->priv
->user_delegator
? page_general
->priv
->user_delegator
: ""));
199 e_meeting_list_view_edit (E_MEETING_LIST_VIEW (page_general
->priv
->attendees_list_view
), attendee
);
201 g_clear_object (&comp_editor
);
205 ecep_general_attendees_edit_clicked_cb (GtkButton
*button
,
206 ECompEditorPageGeneral
*page_general
)
208 GtkTreeView
*tree_view
;
209 GtkTreePath
*path
= NULL
;
210 GtkTreeViewColumn
*focus_col
;
212 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
214 tree_view
= GTK_TREE_VIEW (page_general
->priv
->attendees_list_view
);
216 gtk_tree_view_get_cursor (tree_view
, &path
, NULL
);
217 g_return_if_fail (path
!= NULL
);
219 gtk_tree_view_get_cursor (tree_view
, &path
, &focus_col
);
220 gtk_tree_view_set_cursor (tree_view
, path
, focus_col
, TRUE
);
221 gtk_tree_path_free (path
);
225 ecep_general_remove_attendee (ECompEditorPageGeneral
*page_general
,
226 EMeetingAttendee
*attendee
)
228 ECompEditor
*comp_editor
;
231 /* If this was a delegatee, no longer delegate */
232 if (e_meeting_attendee_is_set_delfrom (attendee
)) {
233 EMeetingAttendee
*ib
;
235 ib
= e_meeting_store_find_attendee (page_general
->priv
->meeting_store
, e_meeting_attendee_get_delfrom (attendee
), &pos
);
237 ECompEditor
*comp_editor
;
238 ECompEditorFlags flags
;
240 e_meeting_attendee_set_delto (ib
, NULL
);
242 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
243 flags
= e_comp_editor_get_flags (comp_editor
);
245 if (!(flags
& E_COMP_EDITOR_FLAG_DELEGATE
))
246 e_meeting_attendee_set_edit_level (ib
, E_MEETING_ATTENDEE_EDIT_FULL
);
248 g_clear_object (&comp_editor
);
252 /* Handle deleting all attendees in the delegation chain */
254 EMeetingAttendee
*ib
= NULL
;
256 if (e_meeting_attendee_get_delto (attendee
)) {
257 ib
= e_meeting_store_find_attendee (page_general
->priv
->meeting_store
,
258 e_meeting_attendee_get_delto (attendee
), NULL
);
261 e_meeting_list_view_remove_attendee_from_name_selector (
262 E_MEETING_LIST_VIEW (page_general
->priv
->attendees_list_view
), attendee
);
263 e_meeting_store_remove_attendee (page_general
->priv
->meeting_store
, attendee
);
268 ecep_general_sensitize_widgets (E_COMP_EDITOR_PAGE (page_general
), FALSE
);
270 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
271 e_comp_editor_set_changed (comp_editor
, TRUE
);
272 g_clear_object (&comp_editor
);
276 ecep_general_attendees_remove_clicked_cb (GtkButton
*button
,
277 ECompEditorPageGeneral
*page_general
)
279 EMeetingAttendee
*attendee
;
280 GtkTreeSelection
*selection
;
281 GList
*paths
= NULL
, *tmp
;
283 GtkTreePath
*path
= NULL
;
284 GtkTreeModel
*model
= NULL
;
288 GString
*errors
= NULL
;
290 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
292 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (page_general
->priv
->attendees_list_view
));
293 paths
= gtk_tree_selection_get_selected_rows (selection
, &model
);
294 g_return_if_fail (paths
!= NULL
);
296 paths
= g_list_reverse (paths
);
298 for (tmp
= paths
; tmp
; tmp
= tmp
->next
) {
301 gtk_tree_model_get_iter (model
, &iter
, path
);
303 gtk_tree_model_get (model
, &iter
, E_MEETING_STORE_ADDRESS_COL
, &address
, -1);
304 attendee
= e_meeting_store_find_attendee (E_MEETING_STORE (model
), address
, NULL
);
308 errors
= g_string_new ("");
310 g_string_append (errors
, "\n");
311 g_string_append_printf (errors
, _("Cannot find attendee “%s” in the list of attendees"), address
);
313 } else if (e_meeting_attendee_get_edit_level (attendee
) != E_MEETING_ATTENDEE_EDIT_FULL
) {
315 errors
= g_string_new ("");
317 g_string_append (errors
, "\n");
318 g_string_append_printf (errors
, _("Not enough rights to delete attendee “%s”"), e_meeting_attendee_get_address (attendee
));
321 ecep_general_remove_attendee (page_general
, attendee
);
327 /* Select closest item after removal */
328 valid_iter
= gtk_tree_model_get_iter (model
, &iter
, path
);
330 gtk_tree_path_prev (path
);
331 valid_iter
= gtk_tree_model_get_iter (model
, &iter
, path
);
335 gtk_tree_selection_unselect_all (selection
);
336 gtk_tree_selection_select_iter (selection
, &iter
);
339 g_list_free_full (paths
, (GDestroyNotify
) gtk_tree_path_free
);
342 ECompEditor
*comp_editor
;
345 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
347 alert
= e_comp_editor_add_error (comp_editor
, g_dngettext (GETTEXT_PACKAGE
,
348 "Failed to delete selected attendee",
349 "Failed to delete selected attendees",
350 failures
), errors
->str
);
352 g_string_free (errors
, TRUE
);
353 g_clear_object (&alert
);
354 g_clear_object (&comp_editor
);
359 ecep_general_attendees_selection_changed_cb (GtkTreeSelection
*selection
,
360 ECompEditorPageGeneral
*page_general
)
362 g_return_if_fail (GTK_IS_TREE_SELECTION (selection
));
363 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
365 ecep_general_sensitize_widgets (E_COMP_EDITOR_PAGE (page_general
), FALSE
);
369 ecep_general_attendee_added_cb (EMeetingListView
*meeting_list_view
,
370 EMeetingAttendee
*attendee
,
371 ECompEditorPageGeneral
*page_general
)
373 ECompEditor
*comp_editor
;
374 ECompEditorFlags flags
;
377 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
378 flags
= e_comp_editor_get_flags (comp_editor
);
380 e_comp_editor_set_changed (comp_editor
, TRUE
);
382 if (!(flags
& E_COMP_EDITOR_FLAG_DELEGATE
)) {
383 g_clear_object (&comp_editor
);
387 client
= e_comp_editor_get_target_client (comp_editor
);
389 /* do not remove here, it did EMeetingListView already */
390 e_meeting_attendee_set_delfrom (attendee
, g_strdup_printf ("MAILTO:%s",
391 page_general
->priv
->user_delegator
? page_general
->priv
->user_delegator
: ""));
393 if (client
&& !e_client_check_capability (E_CLIENT (client
), CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY
)) {
394 EMeetingAttendee
*delegator
;
396 delegator
= e_meeting_store_find_attendee (page_general
->priv
->meeting_store
,
397 page_general
->priv
->user_delegator
, NULL
);
398 g_return_if_fail (delegator
!= NULL
);
400 e_meeting_attendee_set_delto (delegator
, g_strdup (e_meeting_attendee_get_address (attendee
)));
403 ecep_general_sensitize_widgets (E_COMP_EDITOR_PAGE (page_general
), FALSE
);
405 g_clear_object (&comp_editor
);
409 ecep_general_get_organizer (ECompEditorPageGeneral
*page_general
,
412 const gchar
**out_error_message
)
414 gchar
*organizer_text
;
415 gboolean valid
= FALSE
;
417 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), FALSE
);
419 organizer_text
= gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (page_general
->priv
->organizer_combo_box
));
420 if (organizer_text
) {
421 CamelInternetAddress
*address
;
422 const gchar
*str_name
, *str_address
;
424 address
= camel_internet_address_new ();
425 if (camel_address_unformat (CAMEL_ADDRESS (address
), organizer_text
) == 1 &&
426 camel_internet_address_get (address
, 0, &str_name
, &str_address
)) {
430 *out_name
= g_strdup (str_name
);
432 *out_mailto
= g_strconcat ("MAILTO:", itip_strip_mailto (str_address
), NULL
);
433 } else if (out_error_message
) {
434 *out_error_message
= _("Organizer address is not a valid user mail address");
437 g_object_unref (address
);
438 g_free (organizer_text
);
445 ecep_general_pick_organizer_for_email_address (ECompEditorPageGeneral
*page_general
,
446 const gchar
*email_address
)
450 GtkComboBox
*combo_box
;
451 gint ii
, entry_text_column
;
453 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), FALSE
);
455 email_address
= itip_strip_mailto (email_address
);
457 if (!email_address
|| !*email_address
)
460 combo_box
= GTK_COMBO_BOX (page_general
->priv
->organizer_combo_box
);
461 model
= gtk_combo_box_get_model (combo_box
);
462 entry_text_column
= gtk_combo_box_get_entry_text_column (combo_box
);
464 if (!gtk_tree_model_get_iter_first (model
, &iter
))
472 gtk_tree_model_get (model
, &iter
, entry_text_column
, &value
, -1);
474 if (value
&& g_strrstr (value
, email_address
)) {
476 gtk_combo_box_set_active (combo_box
, ii
);
483 } while (gtk_tree_model_iter_next (model
, &iter
));
489 ecep_general_target_client_notify_cb (ECompEditor
*comp_editor
,
491 ECompEditorPageGeneral
*page_general
)
493 const gchar
*cal_email_address
;
495 g_return_if_fail (E_IS_COMP_EDITOR (comp_editor
));
496 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
498 cal_email_address
= e_comp_editor_get_cal_email_address (comp_editor
);
499 ecep_general_pick_organizer_for_email_address (page_general
, cal_email_address
);
503 ecep_general_list_view_event_cb (EMeetingListView
*list_view
,
505 ECompEditorPageGeneral
*page_general
)
507 g_return_val_if_fail (E_IS_MEETING_LIST_VIEW (list_view
), FALSE
);
508 g_return_val_if_fail (event
!= NULL
, FALSE
);
509 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), FALSE
);
511 if (event
->type
== GDK_2BUTTON_PRESS
&& gtk_widget_get_sensitive (GTK_WIDGET (list_view
)) &&
512 gtk_widget_get_sensitive (page_general
->priv
->attendees_button_add
)) {
513 EMeetingAttendee
*attendee
;
514 ECompEditor
*comp_editor
;
517 attendee
= e_meeting_store_add_attendee_with_defaults (page_general
->priv
->meeting_store
);
519 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
520 flags
= e_comp_editor_get_flags (comp_editor
);
522 if ((flags
& E_COMP_EDITOR_FLAG_DELEGATE
) != 0) {
523 e_meeting_attendee_set_delfrom (attendee
, g_strdup_printf ("MAILTO:%s", page_general
->priv
->user_delegator
));
526 g_clear_object (&comp_editor
);
527 e_meeting_list_view_edit (list_view
, attendee
);
536 ecep_general_list_view_key_press_cb (EMeetingListView
*list_view
,
538 ECompEditorPageGeneral
*page_general
)
540 g_return_val_if_fail (E_IS_MEETING_LIST_VIEW (list_view
), FALSE
);
541 g_return_val_if_fail (event
!= NULL
, FALSE
);
542 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), FALSE
);
544 if (event
->keyval
== GDK_KEY_Delete
) {
545 if (gtk_widget_get_sensitive (page_general
->priv
->attendees_button_remove
))
546 ecep_general_attendees_remove_clicked_cb (NULL
, page_general
);
548 } else if (event
->keyval
== GDK_KEY_Insert
) {
549 if (gtk_widget_get_sensitive (page_general
->priv
->attendees_button_add
))
550 ecep_general_attendees_add_clicked_cb (NULL
, page_general
);
558 ecep_general_init_ui (ECompEditorPageGeneral
*page_general
,
559 ECompEditor
*comp_editor
)
563 " <menubar action='main-menu'>"
564 " <menu action='view-menu'>"
565 " <placeholder name='columns'>"
566 " <menuitem action='view-role'/>"
567 " <menuitem action='view-rsvp'/>"
568 " <menuitem action='view-status'/>"
569 " <menuitem action='view-type'/>"
572 " <menu action='options-menu'>"
573 " <placeholder name='toggles'>"
574 " <menuitem action='option-attendees'/>"
580 const GtkToggleActionEntry attendees_toggle_entry
[] = {
582 { "option-attendees",
586 N_("Toggles whether the Attendees are displayed"),
591 const GtkToggleActionEntry columns_toggle_entries
[] = {
597 N_("Toggles whether the Role field is displayed"),
598 G_CALLBACK (action_view_role_cb
),
605 N_("Toggles whether the RSVP field is displayed"),
606 G_CALLBACK (action_view_rsvp_cb
),
613 N_("Toggles whether the Status field is displayed"),
614 G_CALLBACK (action_view_status_cb
),
621 N_("Toggles whether the Attendee Type is displayed"),
622 G_CALLBACK (action_view_type_cb
),
626 GtkUIManager
*ui_manager
;
627 GtkActionGroup
*action_group
;
630 GError
*error
= NULL
;
632 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
633 g_return_if_fail (E_IS_COMP_EDITOR (comp_editor
));
635 settings
= e_comp_editor_get_settings (comp_editor
);
636 ui_manager
= e_comp_editor_get_ui_manager (comp_editor
);
638 action_group
= gtk_action_group_new ("columns");
639 gtk_action_group_set_translation_domain (
640 action_group
, GETTEXT_PACKAGE
);
641 gtk_action_group_add_toggle_actions (
642 action_group
, columns_toggle_entries
,
643 G_N_ELEMENTS (columns_toggle_entries
), page_general
);
644 gtk_ui_manager_insert_action_group (
645 ui_manager
, action_group
, 0);
647 e_binding_bind_property (
648 page_general
, "show-attendees",
649 action_group
, "sensitive",
650 G_BINDING_SYNC_CREATE
);
652 g_object_unref (action_group
);
654 action_group
= e_comp_editor_get_action_group (comp_editor
, "individual");
655 gtk_action_group_add_toggle_actions (
656 action_group
, attendees_toggle_entry
,
657 G_N_ELEMENTS (attendees_toggle_entry
), page_general
);
659 gtk_ui_manager_add_ui_from_string (ui_manager
, ui
, -1, &error
);
662 g_critical ("%s: %s", G_STRFUNC
, error
->message
);
663 g_error_free (error
);
666 action
= e_comp_editor_get_action (comp_editor
, "option-attendees");
667 e_binding_bind_property (
668 page_general
, "show-attendees",
670 G_BINDING_SYNC_CREATE
| G_BINDING_BIDIRECTIONAL
);
672 action
= e_comp_editor_get_action (comp_editor
, "view-role");
674 settings
, "editor-show-role",
676 G_SETTINGS_BIND_DEFAULT
);
678 action
= e_comp_editor_get_action (comp_editor
, "view-rsvp");
680 settings
, "editor-show-rsvp",
682 G_SETTINGS_BIND_DEFAULT
);
684 action
= e_comp_editor_get_action (comp_editor
, "view-status");
686 settings
, "editor-show-status",
688 G_SETTINGS_BIND_DEFAULT
);
690 action
= e_comp_editor_get_action (comp_editor
, "view-type");
692 settings
, "editor-show-type",
694 G_SETTINGS_BIND_DEFAULT
);
698 ecep_general_sensitize_widgets (ECompEditorPage
*page
,
699 gboolean force_insensitive
)
701 ECompEditorPageGeneral
*page_general
;
702 GtkTreeSelection
*selection
;
704 gboolean sensitive
, organizer_is_user
, delegate
, delegate_to_many
= FALSE
, read_only
= TRUE
, any_selected
= FALSE
;
705 ECompEditor
*comp_editor
;
709 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page
));
711 E_COMP_EDITOR_PAGE_CLASS (e_comp_editor_page_general_parent_class
)->sensitize_widgets (page
, force_insensitive
);
713 page_general
= E_COMP_EDITOR_PAGE_GENERAL (page
);
715 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
716 flags
= e_comp_editor_get_flags (comp_editor
);
717 client
= e_comp_editor_get_target_client (comp_editor
);
720 EClient
*cl
= E_CLIENT (client
);
722 read_only
= e_client_is_readonly (cl
);
723 delegate_to_many
= e_client_check_capability (cl
, CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY
);
725 force_insensitive
= TRUE
;
728 delegate
= (flags
& E_COMP_EDITOR_FLAG_DELEGATE
) != 0;
729 organizer_is_user
= (flags
& (E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
| E_COMP_EDITOR_FLAG_IS_NEW
)) != 0 ||
730 !e_comp_editor_page_general_get_show_attendees (page_general
);
731 sensitive
= (!read_only
&& organizer_is_user
) || delegate
;
734 delegate_to_many
= TRUE
;
736 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (page_general
->priv
->attendees_list_view
));
737 any_selected
= selection
&& gtk_tree_selection_count_selected_rows (selection
) > 0;
739 gtk_widget_set_sensitive (page_general
->priv
->organizer_label
, !force_insensitive
);
740 gtk_widget_set_sensitive (page_general
->priv
->organizer_combo_box
, !read_only
&& !force_insensitive
);
741 gtk_widget_set_sensitive (page_general
->priv
->attendees_button
, sensitive
&& delegate_to_many
&& !force_insensitive
);
742 gtk_widget_set_sensitive (page_general
->priv
->attendees_hbox
, !force_insensitive
);
743 gtk_widget_set_sensitive (page_general
->priv
->attendees_button_add
, sensitive
&& delegate_to_many
&& !force_insensitive
);
744 gtk_widget_set_sensitive (page_general
->priv
->attendees_button_edit
, sensitive
&& delegate_to_many
&& !force_insensitive
&& any_selected
);
745 gtk_widget_set_sensitive (page_general
->priv
->attendees_button_remove
, sensitive
&& !force_insensitive
&& any_selected
);
746 e_meeting_list_view_set_editable (E_MEETING_LIST_VIEW (page_general
->priv
->attendees_list_view
), sensitive
&& !force_insensitive
);
747 gtk_widget_set_sensitive (page_general
->priv
->attendees_list_view
, !read_only
&& !force_insensitive
);
749 action
= e_comp_editor_get_action (comp_editor
, "option-attendees");
750 gtk_action_set_sensitive (action
, !force_insensitive
&& !read_only
&& organizer_is_user
);
752 g_clear_object (&comp_editor
);
756 ecep_general_fill_widgets (ECompEditorPage
*page
,
757 icalcomponent
*component
)
759 ECompEditorPageGeneral
*page_general
;
762 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page
));
763 g_return_if_fail (component
!= NULL
);
765 E_COMP_EDITOR_PAGE_CLASS (e_comp_editor_page_general_parent_class
)->fill_widgets (page
, component
);
767 page_general
= E_COMP_EDITOR_PAGE_GENERAL (page
);
769 g_slist_free_full (page_general
->priv
->orig_attendees
, g_free
);
770 page_general
->priv
->orig_attendees
= NULL
;
772 for (prop
= icalcomponent_get_first_property (component
, ICAL_ATTENDEE_PROPERTY
);
774 prop
= icalcomponent_get_next_property (component
, ICAL_ATTENDEE_PROPERTY
)) {
775 const gchar
*address
;
777 address
= itip_strip_mailto (icalproperty_get_attendee (prop
));
779 page_general
->priv
->orig_attendees
= g_slist_prepend (page_general
->priv
->orig_attendees
, g_strdup (address
));
782 page_general
->priv
->orig_attendees
= g_slist_reverse (page_general
->priv
->orig_attendees
);
784 prop
= icalcomponent_get_first_property (component
, ICAL_ORGANIZER_PROPERTY
);
786 icalparameter
*param
;
787 const gchar
*organizer
;
789 organizer
= icalproperty_get_organizer (prop
);
791 if (organizer
&& *organizer
) {
792 ECompEditor
*comp_editor
;
793 ESourceRegistry
*registry
;
794 GtkEntry
*combo_box_entry
;
798 comp_editor
= e_comp_editor_page_ref_editor (page
);
799 flags
= e_comp_editor_get_flags (comp_editor
);
800 registry
= e_shell_get_registry (e_comp_editor_get_shell (comp_editor
));
802 flags
= flags
& E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
;
804 if (itip_address_is_user (registry
, itip_strip_mailto (organizer
))) {
805 flags
= flags
| E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
;
807 param
= icalproperty_get_first_parameter (prop
, ICAL_SENTBY_PARAMETER
);
809 const gchar
*sentby
= icalparameter_get_sentby (param
);
811 if (sentby
&& *sentby
&&
812 itip_address_is_user (registry
, itip_strip_mailto (organizer
))) {
813 flags
= flags
| E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
;
818 e_comp_editor_page_general_set_show_attendees (page_general
, TRUE
);
820 param
= icalproperty_get_first_parameter (prop
, ICAL_CN_PARAMETER
);
824 cn
= icalparameter_get_cn (param
);
826 value
= camel_internet_address_format_address (cn
, itip_strip_mailto (organizer
));
831 value
= g_strdup (itip_strip_mailto (organizer
));
833 combo_box_entry
= GTK_ENTRY (gtk_bin_get_child (GTK_BIN (page_general
->priv
->organizer_combo_box
)));
835 if (!(flags
& E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
)) {
836 GtkComboBoxText
*combo_box_text
;
838 combo_box_text
= GTK_COMBO_BOX_TEXT (page_general
->priv
->organizer_combo_box
);
839 gtk_combo_box_text_remove_all (combo_box_text
);
840 gtk_combo_box_text_append_text (combo_box_text
, value
);
841 gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box_text
), 0);
842 gtk_editable_set_editable (GTK_EDITABLE (combo_box_entry
), FALSE
);
843 } else if (!ecep_general_pick_organizer_for_email_address (page_general
, organizer
)) {
844 gtk_entry_set_text (combo_box_entry
, value
);
847 e_comp_editor_set_flags (comp_editor
, flags
);
849 g_clear_object (&comp_editor
);
854 e_meeting_store_remove_all_attendees (page_general
->priv
->meeting_store
);
856 for (prop
= icalcomponent_get_first_property (component
, ICAL_ATTENDEE_PROPERTY
);
858 prop
= icalcomponent_get_next_property (component
, ICAL_ATTENDEE_PROPERTY
)) {
859 const gchar
*address
;
861 address
= itip_strip_mailto (icalproperty_get_attendee (prop
));
863 EMeetingAttendee
*attendee
;
864 icalparameter
*param
;
866 attendee
= E_MEETING_ATTENDEE (e_meeting_attendee_new ());
868 e_meeting_attendee_set_address (attendee
, g_strdup (address
));
870 param
= icalproperty_get_first_parameter (prop
, ICAL_MEMBER_PARAMETER
);
872 e_meeting_attendee_set_member (attendee
, g_strdup (icalparameter_get_member (param
)));
874 param
= icalproperty_get_first_parameter (prop
, ICAL_CUTYPE_PARAMETER
);
876 e_meeting_attendee_set_cutype (attendee
, icalparameter_get_cutype (param
));
878 param
= icalproperty_get_first_parameter (prop
, ICAL_ROLE_PARAMETER
);
880 e_meeting_attendee_set_role (attendee
, icalparameter_get_role (param
));
882 param
= icalproperty_get_first_parameter (prop
, ICAL_RSVP_PARAMETER
);
884 e_meeting_attendee_set_rsvp (attendee
, icalparameter_get_rsvp (param
) == ICAL_RSVP_TRUE
);
886 param
= icalproperty_get_first_parameter (prop
, ICAL_DELEGATEDTO_PARAMETER
);
888 e_meeting_attendee_set_delto (attendee
, g_strdup (icalparameter_get_delegatedto (param
)));
890 param
= icalproperty_get_first_parameter (prop
, ICAL_DELEGATEDFROM_PARAMETER
);
892 e_meeting_attendee_set_delfrom (attendee
, g_strdup (icalparameter_get_delegatedfrom (param
)));
894 param
= icalproperty_get_first_parameter (prop
, ICAL_PARTSTAT_PARAMETER
);
896 e_meeting_attendee_set_status (attendee
, icalparameter_get_partstat (param
));
898 param
= icalproperty_get_first_parameter (prop
, ICAL_SENTBY_PARAMETER
);
900 e_meeting_attendee_set_sentby (attendee
, g_strdup (icalparameter_get_sentby (param
)));
902 param
= icalproperty_get_first_parameter (prop
, ICAL_CN_PARAMETER
);
904 e_meeting_attendee_set_cn (attendee
, g_strdup (icalparameter_get_cn (param
)));
906 param
= icalproperty_get_first_parameter (prop
, ICAL_LANGUAGE_PARAMETER
);
908 e_meeting_attendee_set_language (attendee
, g_strdup (icalparameter_get_language (param
)));
910 e_meeting_store_add_attendee (page_general
->priv
->meeting_store
, attendee
);
912 g_object_unref (attendee
);
918 ecep_general_fill_component (ECompEditorPage
*page
,
919 icalcomponent
*component
)
921 ECompEditorPageGeneral
*page_general
;
924 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page
), FALSE
);
925 g_return_val_if_fail (component
!= NULL
, FALSE
);
927 page_general
= E_COMP_EDITOR_PAGE_GENERAL (page
);
929 cal_comp_util_remove_all_properties (component
, ICAL_ATTENDEE_PROPERTY
);
931 if (e_comp_editor_page_general_get_show_attendees (page_general
)) {
932 const GPtrArray
*attendees
;
933 GHashTable
*known_attendees
;
934 ECompEditor
*comp_editor
;
935 gchar
*organizer_name
= NULL
, *organizer_mailto
= NULL
;
937 gint ii
, added_attendees
= 0;
938 const gchar
*error_message
= NULL
;
940 comp_editor
= e_comp_editor_page_ref_editor (page
);
941 flags
= e_comp_editor_get_flags (comp_editor
);
943 if ((flags
& (E_COMP_EDITOR_FLAG_IS_NEW
| E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
)) != 0 &&
944 !ecep_general_get_organizer (page_general
, NULL
, NULL
, &error_message
)) {
945 e_comp_editor_set_validation_error (comp_editor
, page
,
946 page_general
->priv
->organizer_combo_box
,
947 error_message
? error_message
: _("An organizer is required."));
949 g_clear_object (&comp_editor
);
954 if (e_meeting_store_count_actual_attendees (page_general
->priv
->meeting_store
) < 1) {
955 e_comp_editor_set_validation_error (comp_editor
, page
,
956 page_general
->priv
->attendees_list_view
,
957 _("At least one attendee is required."));
959 g_clear_object (&comp_editor
);
965 if ((flags
& (E_COMP_EDITOR_FLAG_IS_NEW
| E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
)) != 0 &&
966 ecep_general_get_organizer (page_general
, &organizer_name
, &organizer_mailto
, NULL
)) {
967 const gchar
*cal_email_address
;
968 icalparameter
*param
;
970 prop
= icalcomponent_get_first_property (component
, ICAL_ORGANIZER_PROPERTY
);
972 prop
= icalproperty_new_organizer (organizer_mailto
? organizer_mailto
: organizer_name
);
973 icalcomponent_add_property (component
, prop
);
975 icalproperty_set_organizer (prop
, organizer_mailto
? organizer_mailto
: organizer_name
);
978 param
= icalproperty_get_first_parameter (prop
, ICAL_CN_PARAMETER
);
979 if (organizer_name
&& *organizer_name
) {
981 param
= icalparameter_new_cn (organizer_name
);
982 icalproperty_add_parameter (prop
, param
);
984 icalparameter_set_cn (param
, organizer_name
);
987 icalproperty_remove_parameter_by_kind (prop
, ICAL_CN_PARAMETER
);
990 param
= icalproperty_get_first_parameter (prop
, ICAL_SENTBY_PARAMETER
);
991 cal_email_address
= e_comp_editor_get_cal_email_address (comp_editor
);
992 if (cal_email_address
&& *cal_email_address
) {
996 sentby
= g_strconcat ("MAILTO:", cal_email_address
, NULL
);
997 differs
= !organizer_mailto
|| g_ascii_strcasecmp (sentby
, organizer_mailto
) != 0;
1001 param
= icalparameter_new_sentby (sentby
);
1002 icalproperty_add_parameter (prop
, param
);
1004 icalparameter_set_sentby (param
, sentby
);
1007 icalproperty_remove_parameter_by_kind (prop
, ICAL_SENTBY_PARAMETER
);
1012 icalproperty_remove_parameter_by_kind (prop
, ICAL_SENTBY_PARAMETER
);
1017 known_attendees
= g_hash_table_new (camel_strcase_hash
, camel_strcase_equal
);
1018 attendees
= e_meeting_store_get_attendees (page_general
->priv
->meeting_store
);
1020 for (ii
= 0; ii
< attendees
->len
; ii
++) {
1021 EMeetingAttendee
*attendee
= g_ptr_array_index (attendees
, ii
);
1022 const gchar
*address
;
1024 address
= itip_strip_mailto (e_meeting_attendee_get_address (attendee
));
1026 icalparameter
*param
;
1028 if ((flags
& E_COMP_EDITOR_FLAG_DELEGATE
) != 0 &&
1029 (e_meeting_attendee_is_set_delfrom (attendee
) || e_meeting_attendee_is_set_delto (attendee
)) &&
1030 g_hash_table_contains (known_attendees
, address
))
1033 g_hash_table_insert (known_attendees
, (gpointer
) address
, GINT_TO_POINTER (1));
1035 prop
= icalproperty_new_attendee (e_meeting_attendee_get_address (attendee
));
1036 icalcomponent_add_property (component
, prop
);
1040 if (e_meeting_attendee_is_set_member (attendee
)) {
1041 param
= icalparameter_new_member (e_meeting_attendee_get_member (attendee
));
1042 icalproperty_add_parameter (prop
, param
);
1045 param
= icalparameter_new_cutype (e_meeting_attendee_get_cutype (attendee
));
1046 icalproperty_add_parameter (prop
, param
);
1048 param
= icalparameter_new_role (e_meeting_attendee_get_role (attendee
));
1049 icalproperty_add_parameter (prop
, param
);
1051 param
= icalparameter_new_partstat (e_meeting_attendee_get_status (attendee
));
1052 icalproperty_add_parameter (prop
, param
);
1054 param
= icalparameter_new_rsvp (e_meeting_attendee_get_rsvp (attendee
) ? ICAL_RSVP_TRUE
: ICAL_RSVP_FALSE
);
1055 icalproperty_add_parameter (prop
, param
);
1057 if (e_meeting_attendee_is_set_delfrom (attendee
)) {
1058 param
= icalparameter_new_delegatedfrom (e_meeting_attendee_get_delfrom (attendee
));
1059 icalproperty_add_parameter (prop
, param
);
1061 if (e_meeting_attendee_is_set_delto (attendee
)) {
1062 param
= icalparameter_new_delegatedto (e_meeting_attendee_get_delto (attendee
));
1063 icalproperty_add_parameter (prop
, param
);
1065 if (e_meeting_attendee_is_set_sentby (attendee
)) {
1066 param
= icalparameter_new_sentby (e_meeting_attendee_get_sentby (attendee
));
1067 icalproperty_add_parameter (prop
, param
);
1069 if (e_meeting_attendee_is_set_cn (attendee
)) {
1070 param
= icalparameter_new_cn (e_meeting_attendee_get_cn (attendee
));
1071 icalproperty_add_parameter (prop
, param
);
1073 if (e_meeting_attendee_is_set_language (attendee
)) {
1074 param
= icalparameter_new_language (e_meeting_attendee_get_language (attendee
));
1075 icalproperty_add_parameter (prop
, param
);
1080 g_hash_table_destroy (known_attendees
);
1082 g_free (organizer_name
);
1083 g_free (organizer_mailto
);
1085 if (!added_attendees
) {
1086 e_comp_editor_set_validation_error (comp_editor
, page
,
1087 page_general
->priv
->attendees_list_view
,
1088 _("At least one attendee is required."));
1090 g_clear_object (&comp_editor
);
1095 g_clear_object (&comp_editor
);
1097 cal_comp_util_remove_all_properties (component
, ICAL_ORGANIZER_PROPERTY
);
1100 return E_COMP_EDITOR_PAGE_CLASS (e_comp_editor_page_general_parent_class
)->fill_component (page
, component
);
1104 ecep_general_set_property (GObject
*object
,
1106 const GValue
*value
,
1109 switch (property_id
) {
1110 case PROP_DATA_COLUMN_WIDTH
:
1111 e_comp_editor_page_general_set_data_column_width (
1112 E_COMP_EDITOR_PAGE_GENERAL (object
),
1113 g_value_get_int (value
));
1116 case PROP_SOURCE_LABEL
:
1117 e_comp_editor_page_general_set_source_label (
1118 E_COMP_EDITOR_PAGE_GENERAL (object
),
1119 g_value_get_string (value
));
1122 case PROP_SOURCE_EXTENSION_NAME
:
1123 e_comp_editor_page_general_set_source_extension_name (
1124 E_COMP_EDITOR_PAGE_GENERAL (object
),
1125 g_value_get_string (value
));
1128 case PROP_SELECTED_SOURCE
:
1129 e_comp_editor_page_general_set_selected_source (
1130 E_COMP_EDITOR_PAGE_GENERAL (object
),
1131 g_value_get_object (value
));
1134 case PROP_SHOW_ATTENDEES
:
1135 e_comp_editor_page_general_set_show_attendees (
1136 E_COMP_EDITOR_PAGE_GENERAL (object
),
1137 g_value_get_boolean (value
));
1141 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1145 ecep_general_get_property (GObject
*object
,
1150 switch (property_id
) {
1151 case PROP_DATA_COLUMN_WIDTH
:
1154 e_comp_editor_page_general_get_data_column_width (
1155 E_COMP_EDITOR_PAGE_GENERAL (object
)));
1158 case PROP_SOURCE_LABEL
:
1159 g_value_set_string (
1161 e_comp_editor_page_general_get_source_label (
1162 E_COMP_EDITOR_PAGE_GENERAL (object
)));
1165 case PROP_SOURCE_EXTENSION_NAME
:
1166 g_value_set_string (
1168 e_comp_editor_page_general_get_source_extension_name (
1169 E_COMP_EDITOR_PAGE_GENERAL (object
)));
1172 case PROP_SELECTED_SOURCE
:
1173 g_value_take_object (
1175 e_comp_editor_page_general_ref_selected_source (
1176 E_COMP_EDITOR_PAGE_GENERAL (object
)));
1179 case PROP_SHOW_ATTENDEES
:
1180 g_value_set_boolean (
1182 e_comp_editor_page_general_get_show_attendees (
1183 E_COMP_EDITOR_PAGE_GENERAL (object
)));
1187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1191 ecep_general_constructed (GObject
*object
)
1193 ECompEditor
*comp_editor
;
1194 ECompEditorPageGeneral
*page_general
;
1195 GtkWidget
*widget
, *scrolled_window
;
1196 GtkTreeSelection
*selection
;
1200 page_general
= E_COMP_EDITOR_PAGE_GENERAL (object
);
1202 G_OBJECT_CLASS (e_comp_editor_page_general_parent_class
)->constructed (object
);
1204 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
1205 g_return_if_fail (comp_editor
!= NULL
);
1207 page_general
->priv
->meeting_store
= E_MEETING_STORE (e_meeting_store_new ());
1209 grid
= GTK_GRID (page_general
);
1211 widget
= gtk_label_new_with_mnemonic (_("Or_ganizer:"));
1212 g_object_set (G_OBJECT (widget
),
1214 "halign", GTK_ALIGN_END
,
1216 "valign", GTK_ALIGN_CENTER
,
1218 gtk_grid_attach (grid
, widget
, 0, 0, 1, 1);
1219 gtk_widget_hide (widget
);
1221 page_general
->priv
->organizer_label
= widget
;
1223 widget
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 4);
1224 g_object_set (G_OBJECT (widget
),
1226 "halign", GTK_ALIGN_FILL
,
1228 "valign", GTK_ALIGN_FILL
,
1230 gtk_grid_attach (grid
, widget
, 1, 0, page_general
->priv
->data_column_width
, 1);
1231 gtk_widget_hide (widget
);
1233 page_general
->priv
->organizer_hbox
= widget
;
1235 widget
= gtk_combo_box_text_new_with_entry ();
1236 g_object_set (G_OBJECT (widget
),
1238 "halign", GTK_ALIGN_FILL
,
1240 "valign", GTK_ALIGN_START
,
1242 gtk_box_pack_start (GTK_BOX (page_general
->priv
->organizer_hbox
), widget
, TRUE
, TRUE
, 0);
1243 gtk_widget_show (widget
);
1245 page_general
->priv
->organizer_combo_box
= widget
;
1247 /* The list of organizers is set to be non-editable. Otherwise any
1248 * change in the displayed list causes an 'Account not found' error.
1250 gtk_editable_set_editable (GTK_EDITABLE (gtk_bin_get_child (GTK_BIN (widget
))), FALSE
);
1252 ecep_general_fill_organizer_combo_box (page_general
);
1254 g_signal_connect_swapped (page_general
->priv
->organizer_combo_box
, "changed",
1255 G_CALLBACK (e_comp_editor_ensure_changed
), comp_editor
);
1257 widget
= gtk_label_new_with_mnemonic (page_general
->priv
->source_label_text
);
1258 g_object_set (G_OBJECT (widget
),
1260 "halign", GTK_ALIGN_END
,
1262 "valign", GTK_ALIGN_CENTER
,
1264 gtk_box_pack_start (GTK_BOX (page_general
->priv
->organizer_hbox
), widget
, FALSE
, FALSE
, 0);
1265 gtk_widget_show (widget
);
1267 page_general
->priv
->source_label
= widget
;
1269 shell
= e_comp_editor_get_shell (comp_editor
);
1270 widget
= e_source_combo_box_new (
1271 e_shell_get_registry (shell
),
1272 page_general
->priv
->source_extension_name
);
1273 e_source_combo_box_set_show_colors (E_SOURCE_COMBO_BOX (widget
), TRUE
);
1274 g_object_set (G_OBJECT (widget
),
1276 "halign", GTK_ALIGN_FILL
,
1278 "valign", GTK_ALIGN_START
,
1280 gtk_box_pack_start (GTK_BOX (page_general
->priv
->organizer_hbox
), widget
, TRUE
, TRUE
, 0);
1281 gtk_widget_show (widget
);
1283 page_general
->priv
->source_combo_box
= widget
;
1285 gtk_label_set_mnemonic_widget (GTK_LABEL (page_general
->priv
->source_label
),
1286 page_general
->priv
->source_combo_box
);
1287 g_signal_connect (page_general
->priv
->source_combo_box
, "changed",
1288 G_CALLBACK (ecep_general_source_combo_box_changed_cb
), page_general
);
1290 widget
= gtk_button_new_with_mnemonic (C_("ECompEditor", "Atte_ndees..."));
1291 g_object_set (G_OBJECT (widget
),
1293 "halign", GTK_ALIGN_END
,
1295 "valign", GTK_ALIGN_START
,
1297 gtk_grid_attach (grid
, widget
, 0, 1, 1, 1);
1298 gtk_widget_hide (widget
);
1300 page_general
->priv
->attendees_button
= widget
;
1302 g_signal_connect (widget
, "clicked", G_CALLBACK (ecep_general_attendees_clicked_cb
), page_general
);
1304 widget
= gtk_box_new (GTK_ORIENTATION_HORIZONTAL
, 2);
1305 g_object_set (G_OBJECT (widget
),
1307 "halign", GTK_ALIGN_FILL
,
1309 "valign", GTK_ALIGN_FILL
,
1311 gtk_grid_attach (grid
, widget
, 1, 1, page_general
->priv
->data_column_width
, 1);
1312 gtk_widget_hide (widget
);
1314 page_general
->priv
->attendees_hbox
= widget
;
1316 widget
= GTK_WIDGET (e_meeting_list_view_new (page_general
->priv
->meeting_store
));
1317 g_object_set (G_OBJECT (widget
),
1319 "halign", GTK_ALIGN_FILL
,
1321 "valign", GTK_ALIGN_FILL
,
1323 gtk_widget_show (widget
);
1325 scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
1326 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window
), GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1327 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window
), GTK_SHADOW_IN
);
1328 gtk_widget_show (scrolled_window
);
1330 gtk_container_add (GTK_CONTAINER (scrolled_window
), widget
);
1331 gtk_box_pack_start (GTK_BOX (page_general
->priv
->attendees_hbox
), scrolled_window
, TRUE
, TRUE
, 0);
1333 page_general
->priv
->attendees_list_view
= widget
;
1335 g_signal_connect (page_general
->priv
->attendees_list_view
, "attendee-added",
1336 G_CALLBACK (ecep_general_attendee_added_cb
), page_general
);
1338 g_signal_connect (page_general
->priv
->attendees_list_view
, "event",
1339 G_CALLBACK (ecep_general_list_view_event_cb
), page_general
);
1341 g_signal_connect (page_general
->priv
->attendees_list_view
, "key_press_event",
1342 G_CALLBACK (ecep_general_list_view_key_press_cb
), page_general
);
1344 widget
= gtk_button_box_new (GTK_ORIENTATION_VERTICAL
);
1345 g_object_set (G_OBJECT (widget
),
1347 "halign", GTK_ALIGN_START
,
1349 "valign", GTK_ALIGN_START
,
1351 gtk_box_pack_start (GTK_BOX (page_general
->priv
->attendees_hbox
), widget
, FALSE
, FALSE
, 0);
1352 gtk_widget_show (widget
);
1354 page_general
->priv
->attendees_button_box
= widget
;
1356 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (page_general
->priv
->attendees_list_view
));
1357 g_signal_connect (selection
, "changed", G_CALLBACK (ecep_general_attendees_selection_changed_cb
), page_general
);
1359 widget
= gtk_button_new_with_mnemonic (_("_Add"));
1360 gtk_box_pack_start (GTK_BOX (page_general
->priv
->attendees_button_box
), widget
, FALSE
, FALSE
, 0);
1361 gtk_widget_show (widget
);
1363 page_general
->priv
->attendees_button_add
= widget
;
1365 g_signal_connect (widget
, "clicked", G_CALLBACK (ecep_general_attendees_add_clicked_cb
), page_general
);
1367 widget
= gtk_button_new_with_mnemonic (_("_Edit"));
1368 gtk_box_pack_start (GTK_BOX (page_general
->priv
->attendees_button_box
), widget
, FALSE
, FALSE
, 0);
1369 gtk_widget_show (widget
);
1371 page_general
->priv
->attendees_button_edit
= widget
;
1373 g_signal_connect (widget
, "clicked", G_CALLBACK (ecep_general_attendees_edit_clicked_cb
), page_general
);
1375 widget
= gtk_button_new_with_mnemonic (_("_Remove"));
1376 gtk_box_pack_start (GTK_BOX (page_general
->priv
->attendees_button_box
), widget
, FALSE
, FALSE
, 0);
1377 gtk_widget_show (widget
);
1379 page_general
->priv
->attendees_button_remove
= widget
;
1381 g_signal_connect (widget
, "clicked", G_CALLBACK (ecep_general_attendees_remove_clicked_cb
), page_general
);
1383 e_signal_connect_notify (comp_editor
, "notify::target-client", G_CALLBACK (ecep_general_target_client_notify_cb
), page_general
);
1385 ecep_general_init_ui (page_general
, comp_editor
);
1387 g_clear_object (&comp_editor
);
1391 ecep_general_finalize (GObject
*object
)
1393 ECompEditorPageGeneral
*page_general
;
1395 page_general
= E_COMP_EDITOR_PAGE_GENERAL (object
);
1397 g_free (page_general
->priv
->source_label_text
);
1398 page_general
->priv
->source_label_text
= NULL
;
1400 g_free (page_general
->priv
->source_extension_name
);
1401 page_general
->priv
->source_extension_name
= NULL
;
1403 g_free (page_general
->priv
->user_delegator
);
1404 page_general
->priv
->user_delegator
= NULL
;
1406 g_clear_object (&page_general
->priv
->select_source
);
1407 g_clear_object (&page_general
->priv
->meeting_store
);
1409 g_slist_free_full (page_general
->priv
->orig_attendees
, g_free
);
1410 page_general
->priv
->orig_attendees
= NULL
;
1412 G_OBJECT_CLASS (e_comp_editor_page_general_parent_class
)->finalize (object
);
1416 e_comp_editor_page_general_init (ECompEditorPageGeneral
*page_general
)
1418 page_general
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (page_general
,
1419 E_TYPE_COMP_EDITOR_PAGE_GENERAL
,
1420 ECompEditorPageGeneralPrivate
);
1424 e_comp_editor_page_general_class_init (ECompEditorPageGeneralClass
*klass
)
1426 ECompEditorPageClass
*page_class
;
1427 GObjectClass
*object_class
;
1429 g_type_class_add_private (klass
, sizeof (ECompEditorPageGeneralPrivate
));
1431 page_class
= E_COMP_EDITOR_PAGE_CLASS (klass
);
1432 page_class
->sensitize_widgets
= ecep_general_sensitize_widgets
;
1433 page_class
->fill_widgets
= ecep_general_fill_widgets
;
1434 page_class
->fill_component
= ecep_general_fill_component
;
1436 object_class
= G_OBJECT_CLASS (klass
);
1437 object_class
->set_property
= ecep_general_set_property
;
1438 object_class
->get_property
= ecep_general_get_property
;
1439 object_class
->constructed
= ecep_general_constructed
;
1440 object_class
->finalize
= ecep_general_finalize
;
1442 g_object_class_install_property (
1444 PROP_DATA_COLUMN_WIDTH
,
1446 "data-column-width",
1447 "Data Column Width",
1448 "How many columns should the data column occupy",
1452 G_PARAM_STATIC_STRINGS
));
1454 g_object_class_install_property (
1457 g_param_spec_string (
1460 "Label to use for the source selector",
1463 G_PARAM_CONSTRUCT_ONLY
|
1464 G_PARAM_STATIC_STRINGS
));
1466 g_object_class_install_property (
1468 PROP_SOURCE_EXTENSION_NAME
,
1469 g_param_spec_string (
1470 "source-extension-name",
1471 "Source Extension Name",
1472 "Extension name to use for the source selector",
1475 G_PARAM_CONSTRUCT_ONLY
|
1476 G_PARAM_STATIC_STRINGS
));
1478 g_object_class_install_property (
1480 PROP_SELECTED_SOURCE
,
1481 g_param_spec_object (
1484 "Which source is currently selected in the source selector",
1487 G_PARAM_STATIC_STRINGS
));
1489 g_object_class_install_property (
1491 PROP_SHOW_ATTENDEES
,
1492 g_param_spec_boolean (
1495 "Whether to show also attendees",
1499 G_PARAM_STATIC_STRINGS
));
1503 e_comp_editor_page_general_new (ECompEditor
*editor
,
1504 const gchar
*source_label
,
1505 const gchar
*source_extension_name
,
1506 ESource
*select_source
,
1507 gboolean show_attendees
,
1508 gint data_column_width
)
1510 g_return_val_if_fail (E_IS_COMP_EDITOR (editor
), NULL
);
1511 g_return_val_if_fail (source_label
!= NULL
, NULL
);
1512 g_return_val_if_fail (source_extension_name
!= NULL
, NULL
);
1515 g_return_val_if_fail (E_IS_SOURCE (select_source
), NULL
);
1517 return g_object_new (E_TYPE_COMP_EDITOR_PAGE_GENERAL
,
1519 "source-label", source_label
,
1520 "source-extension-name", source_extension_name
,
1521 "selected-source", select_source
,
1522 "show-attendees", show_attendees
,
1523 "data-column-width", data_column_width
,
1528 e_comp_editor_page_general_get_source_label (ECompEditorPageGeneral
*page_general
)
1530 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), NULL
);
1532 if (page_general
->priv
->source_label
)
1533 return gtk_label_get_text (GTK_LABEL (page_general
->priv
->source_label
));
1535 return page_general
->priv
->source_label_text
;
1539 e_comp_editor_page_general_set_source_label (ECompEditorPageGeneral
*page_general
,
1540 const gchar
*source_label
)
1542 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
1543 g_return_if_fail (source_label
!= NULL
);
1545 if (page_general
->priv
->source_label
) {
1546 if (g_strcmp0 (source_label
, gtk_label_get_text (GTK_LABEL (page_general
->priv
->source_label
))) != 0) {
1547 gtk_label_set_text (GTK_LABEL (page_general
->priv
->source_label
), source_label
);
1549 g_object_notify (G_OBJECT (page_general
), "source-label");
1552 g_free (page_general
->priv
->source_label_text
);
1553 page_general
->priv
->source_label_text
= g_strdup (source_label
);
1555 g_object_notify (G_OBJECT (page_general
), "source-label");
1560 e_comp_editor_page_general_get_source_extension_name (ECompEditorPageGeneral
*page_general
)
1562 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), NULL
);
1564 if (page_general
->priv
->source_combo_box
)
1565 return e_source_combo_box_get_extension_name (E_SOURCE_COMBO_BOX (page_general
->priv
->source_combo_box
));
1567 return page_general
->priv
->source_extension_name
;
1571 e_comp_editor_page_general_set_source_extension_name (ECompEditorPageGeneral
*page_general
,
1572 const gchar
*source_extension_name
)
1574 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
1576 if (g_strcmp0 (page_general
->priv
->source_extension_name
, source_extension_name
) == 0)
1579 g_free (page_general
->priv
->source_extension_name
);
1580 page_general
->priv
->source_extension_name
= g_strdup (source_extension_name
);
1582 g_object_notify (G_OBJECT (page_general
), "source-extension-name");
1584 if (page_general
->priv
->source_combo_box
) {
1585 e_source_combo_box_set_extension_name (
1586 E_SOURCE_COMBO_BOX (page_general
->priv
->source_combo_box
),
1587 source_extension_name
);
1592 e_comp_editor_page_general_ref_selected_source (ECompEditorPageGeneral
*page_general
)
1594 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), NULL
);
1595 g_return_val_if_fail (page_general
->priv
->source_combo_box
!= NULL
, NULL
);
1597 return e_source_combo_box_ref_active (E_SOURCE_COMBO_BOX (page_general
->priv
->source_combo_box
));
1601 e_comp_editor_page_general_set_selected_source (ECompEditorPageGeneral
*page_general
,
1604 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
1606 g_return_if_fail (E_IS_SOURCE (source
));
1608 if (!page_general
->priv
->source_combo_box
) {
1609 g_clear_object (&page_general
->priv
->select_source
);
1610 page_general
->priv
->select_source
= g_object_ref (source
);
1612 g_object_notify (G_OBJECT (page_general
), "selected-source");
1618 e_source_combo_box_set_active (E_SOURCE_COMBO_BOX (page_general
->priv
->source_combo_box
), source
);
1620 g_object_notify (G_OBJECT (page_general
), "selected-source");
1624 e_comp_editor_page_general_get_show_attendees (ECompEditorPageGeneral
*page_general
)
1626 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), FALSE
);
1628 return page_general
->priv
->show_attendees
;
1632 e_comp_editor_page_general_set_show_attendees (ECompEditorPageGeneral
*page_general
,
1633 gboolean show_attendees
)
1635 ECompEditor
*comp_editor
;
1637 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
1639 if ((show_attendees
? 1 : 0) == (page_general
->priv
->show_attendees
? 1 : 0))
1642 page_general
->priv
->show_attendees
= show_attendees
;
1644 g_object_notify (G_OBJECT (page_general
), "show-attendees");
1646 e_comp_editor_page_general_update_view (page_general
);
1648 comp_editor
= e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_general
));
1650 e_comp_editor_set_changed (comp_editor
, TRUE
);
1651 g_clear_object (&comp_editor
);
1655 e_comp_editor_page_general_get_data_column_width (ECompEditorPageGeneral
*page_general
)
1657 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), 0);
1659 return page_general
->priv
->data_column_width
;
1663 e_comp_editor_page_general_set_data_column_width (ECompEditorPageGeneral
*page_general
,
1664 gint data_column_width
)
1666 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
1668 if (data_column_width
== page_general
->priv
->data_column_width
)
1671 page_general
->priv
->data_column_width
= data_column_width
;
1673 g_object_notify (G_OBJECT (page_general
), "data-column-width");
1675 e_comp_editor_page_general_update_view (page_general
);
1679 e_comp_editor_page_general_update_view (ECompEditorPageGeneral
*page_general
)
1683 g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
));
1685 if (!page_general
->priv
->source_label
)
1688 grid
= GTK_CONTAINER (page_general
);
1690 gtk_container_child_set (grid
, page_general
->priv
->organizer_hbox
,
1691 "left-attach", 1, "width", page_general
->priv
->data_column_width
, NULL
);
1692 gtk_container_child_set (grid
, page_general
->priv
->attendees_hbox
,
1693 "width", page_general
->priv
->data_column_width
, NULL
);
1695 if (page_general
->priv
->show_attendees
) {
1696 if (gtk_widget_get_parent (page_general
->priv
->source_label
) == GTK_WIDGET (grid
)) {
1697 g_object_ref (page_general
->priv
->source_label
);
1698 g_object_ref (page_general
->priv
->source_combo_box
);
1700 gtk_container_remove (grid
, page_general
->priv
->source_label
);
1701 gtk_container_remove (grid
, page_general
->priv
->source_combo_box
);
1703 gtk_box_pack_start (GTK_BOX (page_general
->priv
->organizer_hbox
),
1704 page_general
->priv
->source_label
, FALSE
, FALSE
, 0);
1705 gtk_box_pack_start (GTK_BOX (page_general
->priv
->organizer_hbox
),
1706 page_general
->priv
->source_combo_box
, TRUE
, TRUE
, 0);
1708 g_object_unref (page_general
->priv
->source_label
);
1709 g_object_unref (page_general
->priv
->source_combo_box
);
1712 gtk_container_child_set (grid
, page_general
->priv
->organizer_label
,
1713 "left-attach", 0, NULL
);
1715 gtk_widget_show (page_general
->priv
->organizer_label
);
1716 gtk_widget_show (page_general
->priv
->organizer_hbox
);
1717 gtk_widget_show (page_general
->priv
->attendees_button
);
1718 gtk_widget_show (page_general
->priv
->attendees_hbox
);
1719 gtk_widget_show (page_general
->priv
->attendees_list_view
);
1720 gtk_widget_show (page_general
->priv
->attendees_button_box
);
1722 if (gtk_widget_get_parent (page_general
->priv
->source_label
) != GTK_WIDGET (grid
)) {
1723 GtkContainer
*container
;
1726 container
= GTK_CONTAINER (page_general
->priv
->organizer_hbox
);
1727 ggrid
= GTK_GRID (grid
);
1729 g_object_ref (page_general
->priv
->source_label
);
1730 g_object_ref (page_general
->priv
->source_combo_box
);
1732 gtk_container_remove (container
, page_general
->priv
->source_label
);
1733 gtk_container_remove (container
, page_general
->priv
->source_combo_box
);
1735 gtk_grid_attach (ggrid
, page_general
->priv
->source_label
, 0, 0, 1, 1);
1736 gtk_grid_attach (ggrid
, page_general
->priv
->source_combo_box
, 1, 0, 1, 1);
1738 g_object_unref (page_general
->priv
->source_label
);
1739 g_object_unref (page_general
->priv
->source_combo_box
);
1742 gtk_container_child_set (grid
, page_general
->priv
->source_label
,
1743 "left-attach", 0, NULL
);
1744 gtk_container_child_set (grid
, page_general
->priv
->source_combo_box
,
1745 "left-attach", 1, "width", page_general
->priv
->data_column_width
, NULL
);
1747 gtk_widget_hide (page_general
->priv
->organizer_label
);
1748 gtk_widget_hide (page_general
->priv
->organizer_hbox
);
1749 gtk_widget_hide (page_general
->priv
->attendees_button
);
1750 gtk_widget_hide (page_general
->priv
->attendees_hbox
);
1751 gtk_widget_hide (page_general
->priv
->attendees_list_view
);
1752 gtk_widget_hide (page_general
->priv
->attendees_button_box
);
1757 e_comp_editor_page_general_get_meeting_store (ECompEditorPageGeneral
*page_general
)
1759 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), NULL
);
1761 return page_general
->priv
->meeting_store
;
1764 /* Element is a string, an email address; free with g_slist_free_full (slist, g_free); */
1766 e_comp_editor_page_general_get_added_attendees (ECompEditorPageGeneral
*page_general
)
1768 const GPtrArray
*attendees
;
1769 GHashTable
*orig_attendees
= NULL
;
1770 GSList
*added_attendees
= NULL
, *link
;
1773 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), NULL
);
1775 if (!page_general
->priv
->show_attendees
)
1778 if (page_general
->priv
->orig_attendees
) {
1779 for (link
= page_general
->priv
->orig_attendees
; link
; link
= g_slist_next (link
)) {
1780 const gchar
*address
= link
->data
;
1783 if (!orig_attendees
)
1784 orig_attendees
= g_hash_table_new (camel_strcase_hash
, camel_strcase_equal
);
1785 g_hash_table_insert (orig_attendees
, (gpointer
) address
, GINT_TO_POINTER (1));
1790 attendees
= e_meeting_store_get_attendees (page_general
->priv
->meeting_store
);
1792 for (ii
= 0; ii
< attendees
->len
; ii
++) {
1793 EMeetingAttendee
*attendee
= g_ptr_array_index (attendees
, ii
);
1794 const gchar
*address
;
1796 address
= itip_strip_mailto (e_meeting_attendee_get_address (attendee
));
1798 if (address
&& (!orig_attendees
|| !g_hash_table_contains (orig_attendees
, address
)))
1799 added_attendees
= g_slist_prepend (added_attendees
, g_strdup (address
));
1803 g_hash_table_destroy (orig_attendees
);
1805 return g_slist_reverse (added_attendees
);
1808 /* Element is a string, an email address; free with g_slist_free_full (slist, g_free); */
1810 e_comp_editor_page_general_get_removed_attendees (ECompEditorPageGeneral
*page_general
)
1812 const GPtrArray
*attendees
;
1813 GHashTable
*new_attendees
;
1814 GSList
*removed_attendees
= NULL
, *link
;
1817 g_return_val_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general
), NULL
);
1819 if (!page_general
->priv
->orig_attendees
)
1822 if (!page_general
->priv
->show_attendees
) {
1823 GSList
*copy
, *link
;
1825 copy
= g_slist_copy (page_general
->priv
->orig_attendees
);
1826 for (link
= copy
; link
; link
= g_slist_next (link
)) {
1827 link
->data
= g_strdup (link
->data
);
1833 new_attendees
= g_hash_table_new (camel_strcase_hash
, camel_strcase_equal
);
1834 attendees
= e_meeting_store_get_attendees (page_general
->priv
->meeting_store
);
1836 for (ii
= 0; ii
< attendees
->len
; ii
++) {
1837 EMeetingAttendee
*attendee
= g_ptr_array_index (attendees
, ii
);
1838 const gchar
*address
;
1840 address
= itip_strip_mailto (e_meeting_attendee_get_address (attendee
));
1842 g_hash_table_insert (new_attendees
, (gpointer
) address
, GINT_TO_POINTER (1));
1845 for (link
= page_general
->priv
->orig_attendees
; link
; link
= g_slist_next (link
)) {
1846 const gchar
*address
= link
->data
;
1848 if (address
&& !g_hash_table_contains (new_attendees
, address
)) {
1849 removed_attendees
= g_slist_prepend (removed_attendees
, g_strdup (address
));
1853 g_hash_table_destroy (new_attendees
);
1855 return g_slist_reverse (removed_attendees
);