2 * e-mail-shell-sidebar.c
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
26 #include "e-mail-shell-sidebar.h"
28 #include "mail/e-mail-backend.h"
29 #include "mail/e-mail-sidebar.h"
30 #include "mail/em-folder-utils.h"
32 struct _EMailShellSidebarPrivate
{
33 GtkWidget
*folder_tree
;
41 static gpointer parent_class
;
42 static GType mail_shell_sidebar_type
;
45 mail_shell_sidebar_selection_changed_cb (EShellSidebar
*shell_sidebar
,
46 GtkTreeSelection
*selection
)
48 EShellView
*shell_view
;
49 EShellViewClass
*shell_view_class
;
52 const gchar
*icon_name
;
53 gchar
*display_name
= NULL
;
54 gboolean is_folder
= FALSE
;
57 shell_view
= e_shell_sidebar_get_shell_view (shell_sidebar
);
58 shell_view_class
= E_SHELL_VIEW_GET_CLASS (shell_view
);
60 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
63 COL_STRING_DISPLAY_NAME
, &display_name
,
64 COL_BOOL_IS_FOLDER
, &is_folder
,
65 COL_UINT_FLAGS
, &flags
, -1);
68 icon_name
= em_folder_utils_get_icon_name (flags
);
70 icon_name
= shell_view_class
->icon_name
;
71 display_name
= g_strdup (shell_view_class
->label
);
74 e_shell_sidebar_set_icon_name (shell_sidebar
, icon_name
);
75 e_shell_sidebar_set_primary_text (shell_sidebar
, display_name
);
77 g_free (display_name
);
81 mail_shell_sidebar_get_property (GObject
*object
,
86 switch (property_id
) {
87 case PROP_FOLDER_TREE
:
89 value
, e_mail_shell_sidebar_get_folder_tree (
90 E_MAIL_SHELL_SIDEBAR (object
)));
94 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
98 mail_shell_sidebar_dispose (GObject
*object
)
100 EMailShellSidebarPrivate
*priv
;
102 priv
= E_MAIL_SHELL_SIDEBAR (object
)->priv
;
104 if (priv
->folder_tree
!= NULL
) {
105 g_object_unref (priv
->folder_tree
);
106 priv
->folder_tree
= NULL
;
109 /* Chain up to parent's dispose() method. */
110 G_OBJECT_CLASS (parent_class
)->dispose (object
);
114 mail_shell_sidebar_constructed (GObject
*object
)
116 EMailShellSidebar
*mail_shell_sidebar
;
117 EShellSettings
*shell_settings
;
118 EShellBackend
*shell_backend
;
119 EShellSidebar
*shell_sidebar
;
120 EShellWindow
*shell_window
;
121 EShellView
*shell_view
;
123 GtkTreeSelection
*selection
;
124 GtkTreeView
*tree_view
;
125 GtkWidget
*container
;
128 /* Chain up to parent's constructed method. */
129 G_OBJECT_CLASS (parent_class
)->constructed (object
);
131 shell_sidebar
= E_SHELL_SIDEBAR (object
);
132 shell_view
= e_shell_sidebar_get_shell_view (shell_sidebar
);
133 shell_backend
= e_shell_view_get_shell_backend (shell_view
);
134 shell_window
= e_shell_view_get_shell_window (shell_view
);
136 shell
= e_shell_window_get_shell (shell_window
);
137 shell_settings
= e_shell_get_shell_settings (shell
);
139 mail_shell_sidebar
= E_MAIL_SHELL_SIDEBAR (object
);
141 /* Build sidebar widgets. */
143 container
= GTK_WIDGET (object
);
145 widget
= gtk_scrolled_window_new (NULL
, NULL
);
146 gtk_scrolled_window_set_policy (
147 GTK_SCROLLED_WINDOW (widget
),
148 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
149 gtk_scrolled_window_set_shadow_type (
150 GTK_SCROLLED_WINDOW (widget
), GTK_SHADOW_IN
);
151 gtk_container_add (GTK_CONTAINER (container
), widget
);
152 gtk_widget_show (widget
);
156 widget
= e_mail_sidebar_new (
157 E_MAIL_BACKEND (shell_backend
),
158 E_ALERT_SINK (shell_sidebar
));
159 gtk_container_add (GTK_CONTAINER (container
), widget
);
160 mail_shell_sidebar
->priv
->folder_tree
= g_object_ref (widget
);
161 gtk_widget_show (widget
);
163 g_object_bind_property (
164 shell_view
, "state-key-file",
166 G_BINDING_SYNC_CREATE
);
168 g_object_bind_property (
169 shell_settings
, "mail-sidebar-ellipsize",
171 G_BINDING_SYNC_CREATE
);
173 g_object_bind_property (
174 shell_settings
, "mail-sidebar-search",
175 widget
, "enable-search",
176 G_BINDING_SYNC_CREATE
);
178 g_signal_connect_swapped (
179 widget
, "key-file-changed",
180 G_CALLBACK (e_shell_view_set_state_dirty
), shell_view
);
182 tree_view
= GTK_TREE_VIEW (mail_shell_sidebar
->priv
->folder_tree
);
183 selection
= gtk_tree_view_get_selection (tree_view
);
185 g_signal_connect_swapped (
186 selection
, "changed",
187 G_CALLBACK (mail_shell_sidebar_selection_changed_cb
),
192 guess_screen_width (EMailShellSidebar
*sidebar
)
198 widget
= GTK_WIDGET (sidebar
);
202 screen
= gtk_widget_get_screen (widget
);
208 toplevel
= gtk_widget_get_toplevel (widget
);
209 if (toplevel
&& gtk_widget_get_realized (toplevel
))
210 monitor
= gdk_screen_get_monitor_at_window (
211 screen
, gtk_widget_get_window (toplevel
));
213 /* We don't know in which monitor the window manager
214 * will put us. So we will just use the geometry of
220 gdk_screen_get_monitor_geometry (screen
, monitor
, &rect
);
221 screen_width
= rect
.width
;
224 if (screen_width
== 0)
231 mail_shell_sidebar_get_preferred_height (GtkWidget
*widget
,
232 gint
*minimum_height
,
233 gint
*natural_height
)
235 GTK_WIDGET_CLASS (parent_class
)->get_preferred_height (
236 widget
, minimum_height
, natural_height
);
240 mail_shell_sidebar_get_preferred_width (GtkWidget
*widget
,
244 /* We override the normal size-request handler so that we can
245 * spit out a treeview with a suitable width. We measure the
246 * length of a typical string and use that as the requisition's
249 * EMFolderTreeClass, our parent class, is based on GtkTreeView,
250 * which doesn't really have a good way of figuring out a minimum
251 * width for the tree. This is really GTK+'s fault at large, as
252 * it only has "minimum size / allocated size", instead of
253 * "minimum size / preferred size / allocated size". Hopefully
254 * the extended-layout branch of GTK+ will get merged soon and
255 * then we can remove this crap.
258 EMailShellSidebar
*sidebar
;
260 PangoRectangle ink_rect
;
266 sidebar
= E_MAIL_SHELL_SIDEBAR (widget
);
268 GTK_WIDGET_CLASS (parent_class
)->get_preferred_width (
269 widget
, minimum_width
, natural_width
);
271 /* This string is a mockup only; it doesn't need to be translated */
272 layout
= gtk_widget_create_pango_layout (
273 widget
, "typical.account@mailservice.com");
274 pango_layout_get_pixel_extents (layout
, &ink_rect
, NULL
);
275 g_object_unref (layout
);
277 style
= gtk_widget_get_style (widget
);
279 screen_width
= guess_screen_width (sidebar
);
281 /* Thickness of frame shadow plus some slack for padding. */
282 border
= 2 * style
->xthickness
+ 4;
283 sidebar_width
= ink_rect
.width
+ border
;
284 sidebar_width
= MIN (sidebar_width
, screen_width
/ 4);
285 *minimum_width
= *natural_width
= MAX (*natural_width
, sidebar_width
);
289 mail_shell_sidebar_check_state (EShellSidebar
*shell_sidebar
)
291 EMailShellSidebarPrivate
*priv
;
292 EMailSidebar
*sidebar
;
294 priv
= E_MAIL_SHELL_SIDEBAR (shell_sidebar
)->priv
;
295 sidebar
= E_MAIL_SIDEBAR (priv
->folder_tree
);
297 return e_mail_sidebar_check_state (sidebar
);
301 mail_shell_sidebar_class_init (EMailShellSidebarClass
*class)
303 GObjectClass
*object_class
;
304 GtkWidgetClass
*widget_class
;
305 EShellSidebarClass
*shell_sidebar_class
;
307 parent_class
= g_type_class_peek_parent (class);
308 g_type_class_add_private (class, sizeof (EMailShellSidebarPrivate
));
310 object_class
= G_OBJECT_CLASS (class);
311 object_class
->get_property
= mail_shell_sidebar_get_property
;
312 object_class
->dispose
= mail_shell_sidebar_dispose
;
313 object_class
->constructed
= mail_shell_sidebar_constructed
;
315 widget_class
= GTK_WIDGET_CLASS (class);
316 widget_class
->get_preferred_width
= mail_shell_sidebar_get_preferred_width
;
317 widget_class
->get_preferred_height
= mail_shell_sidebar_get_preferred_height
;
319 shell_sidebar_class
= E_SHELL_SIDEBAR_CLASS (class);
320 shell_sidebar_class
->check_state
= mail_shell_sidebar_check_state
;
322 g_object_class_install_property (
325 g_param_spec_object (
334 mail_shell_sidebar_init (EMailShellSidebar
*mail_shell_sidebar
)
336 mail_shell_sidebar
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (
337 mail_shell_sidebar
, E_TYPE_MAIL_SHELL_SIDEBAR
,
338 EMailShellSidebarPrivate
);
340 /* Postpone widget construction until we have a shell view. */
344 e_mail_shell_sidebar_get_type (void)
346 return mail_shell_sidebar_type
;
350 e_mail_shell_sidebar_register_type (GTypeModule
*type_module
)
352 static const GTypeInfo type_info
= {
353 sizeof (EMailShellSidebarClass
),
354 (GBaseInitFunc
) NULL
,
355 (GBaseFinalizeFunc
) NULL
,
356 (GClassInitFunc
) mail_shell_sidebar_class_init
,
357 (GClassFinalizeFunc
) NULL
,
358 NULL
, /* class_data */
359 sizeof (EMailShellSidebar
),
361 (GInstanceInitFunc
) mail_shell_sidebar_init
,
362 NULL
/* value_table */
365 mail_shell_sidebar_type
= g_type_module_register_type (
366 type_module
, E_TYPE_SHELL_SIDEBAR
,
367 "EMailShellSidebar", &type_info
, 0);
371 e_mail_shell_sidebar_new (EShellView
*shell_view
)
373 g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view
), NULL
);
375 return g_object_new (
376 E_TYPE_MAIL_SHELL_SIDEBAR
,
377 "shell-view", shell_view
, NULL
);
381 e_mail_shell_sidebar_get_folder_tree (EMailShellSidebar
*mail_shell_sidebar
)
383 g_return_val_if_fail (
384 E_IS_MAIL_SHELL_SIDEBAR (mail_shell_sidebar
), NULL
);
386 return EM_FOLDER_TREE (mail_shell_sidebar
->priv
->folder_tree
);