No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-shell-sidebar.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-shell-sidebar.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-mail-shell-sidebar.c
3 *
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.
8 *
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.
13 *
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/>
16 *
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "e-mail-shell-sidebar.h"
27
28 #include "mail/e-mail-backend.h"
29 #include "mail/e-mail-sidebar.h"
30 #include "mail/em-folder-utils.h"
31
32 #define E_MAIL_SHELL_SIDEBAR_GET_PRIVATE(obj) \
33 (G_TYPE_INSTANCE_GET_PRIVATE \
34 ((obj), E_TYPE_MAIL_SHELL_SIDEBAR, EMailShellSidebarPrivate))
35
36 struct _EMailShellSidebarPrivate {
37 GtkWidget *folder_tree;
38 };
39
40 enum {
41 PROP_0,
42 PROP_FOLDER_TREE
43 };
44
45 G_DEFINE_DYNAMIC_TYPE (
46 EMailShellSidebar,
47 e_mail_shell_sidebar,
48 E_TYPE_SHELL_SIDEBAR)
49
50 static void
51 mail_shell_sidebar_selection_changed_cb (EShellSidebar *shell_sidebar,
52 GtkTreeSelection *selection)
53 {
54 EShellView *shell_view;
55 EShellViewClass *shell_view_class;
56 GtkTreeModel *model;
57 GtkTreeIter iter;
58 const gchar *icon_name;
59 gchar *display_name = NULL;
60 gboolean is_folder = FALSE;
61 guint flags = 0;
62
63 shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
64 shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
65
66 if (gtk_tree_selection_get_selected (selection, &model, &iter))
67 gtk_tree_model_get (
68 model, &iter,
69 COL_STRING_DISPLAY_NAME, &display_name,
70 COL_BOOL_IS_FOLDER, &is_folder,
71 COL_UINT_FLAGS, &flags, -1);
72
73 if (is_folder)
74 icon_name = em_folder_utils_get_icon_name (flags);
75 else {
76 g_free (display_name);
77
78 icon_name = shell_view_class->icon_name;
79 display_name = g_strdup (shell_view_class->label);
80 }
81
82 e_shell_sidebar_set_icon_name (shell_sidebar, icon_name);
83 e_shell_sidebar_set_primary_text (shell_sidebar, display_name);
84
85 g_free (display_name);
86 }
87
88 static void
89 mail_shell_sidebar_get_property (GObject *object,
90 guint property_id,
91 GValue *value,
92 GParamSpec *pspec)
93 {
94 switch (property_id) {
95 case PROP_FOLDER_TREE:
96 g_value_set_object (
97 value, e_mail_shell_sidebar_get_folder_tree (
98 E_MAIL_SHELL_SIDEBAR (object)));
99 return;
100 }
101
102 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
103 }
104
105 static void
106 mail_shell_sidebar_dispose (GObject *object)
107 {
108 EMailShellSidebarPrivate *priv;
109
110 priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (object);
111
112 if (priv->folder_tree != NULL) {
113 g_object_unref (priv->folder_tree);
114 priv->folder_tree = NULL;
115 }
116
117 /* Chain up to parent's dispose() method. */
118 G_OBJECT_CLASS (e_mail_shell_sidebar_parent_class)->dispose (object);
119 }
120
121 static void
122 mail_shell_sidebar_constructed (GObject *object)
123 {
124 EMailShellSidebar *mail_shell_sidebar;
125 EShellSettings *shell_settings;
126 EShellBackend *shell_backend;
127 EShellSidebar *shell_sidebar;
128 EShellWindow *shell_window;
129 EShellView *shell_view;
130 EShell *shell;
131 EMailBackend *backend;
132 EMailSession *session;
133 EAlertSink *alert_sink;
134 GtkTreeSelection *selection;
135 GtkTreeView *tree_view;
136 GtkWidget *container;
137 GtkWidget *widget;
138
139 /* Chain up to parent's constructed method. */
140 G_OBJECT_CLASS (e_mail_shell_sidebar_parent_class)->constructed (object);
141
142 shell_sidebar = E_SHELL_SIDEBAR (object);
143 shell_view = e_shell_sidebar_get_shell_view (shell_sidebar);
144 shell_backend = e_shell_view_get_shell_backend (shell_view);
145 shell_window = e_shell_view_get_shell_window (shell_view);
146
147 shell = e_shell_window_get_shell (shell_window);
148 shell_settings = e_shell_get_shell_settings (shell);
149
150 backend = E_MAIL_BACKEND (shell_backend);
151 session = e_mail_backend_get_session (backend);
152
153 alert_sink = E_ALERT_SINK (shell_sidebar);
154
155 mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (object);
156
157 /* Build sidebar widgets. */
158
159 container = GTK_WIDGET (object);
160
161 widget = gtk_scrolled_window_new (NULL, NULL);
162 gtk_scrolled_window_set_policy (
163 GTK_SCROLLED_WINDOW (widget),
164 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
165 gtk_scrolled_window_set_shadow_type (
166 GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
167 gtk_container_add (GTK_CONTAINER (container), widget);
168 gtk_widget_show (widget);
169
170 container = widget;
171
172 widget = e_mail_sidebar_new (session, alert_sink);
173 gtk_container_add (GTK_CONTAINER (container), widget);
174 mail_shell_sidebar->priv->folder_tree = g_object_ref (widget);
175 gtk_widget_show (widget);
176
177 g_object_bind_property (
178 shell_view, "state-key-file",
179 widget, "key-file",
180 G_BINDING_SYNC_CREATE);
181
182 g_object_bind_property (
183 shell_settings, "mail-sidebar-ellipsize",
184 widget, "ellipsize",
185 G_BINDING_SYNC_CREATE);
186
187 g_object_bind_property (
188 shell_settings, "mail-sidebar-search",
189 widget, "enable-search",
190 G_BINDING_SYNC_CREATE);
191
192 g_signal_connect_swapped (
193 widget, "key-file-changed",
194 G_CALLBACK (e_shell_view_set_state_dirty), shell_view);
195
196 tree_view = GTK_TREE_VIEW (mail_shell_sidebar->priv->folder_tree);
197 selection = gtk_tree_view_get_selection (tree_view);
198
199 g_signal_connect_swapped (
200 selection, "changed",
201 G_CALLBACK (mail_shell_sidebar_selection_changed_cb),
202 shell_sidebar);
203 }
204
205 static gint
206 guess_screen_width (EMailShellSidebar *sidebar)
207 {
208 GtkWidget *widget;
209 GdkScreen *screen;
210 gint screen_width;
211
212 widget = GTK_WIDGET (sidebar);
213
214 screen_width = 0;
215
216 screen = gtk_widget_get_screen (widget);
217 if (screen) {
218 GtkWidget *toplevel;
219 gint monitor;
220 GdkRectangle rect;
221
222 toplevel = gtk_widget_get_toplevel (widget);
223 if (toplevel && gtk_widget_get_realized (toplevel))
224 monitor = gdk_screen_get_monitor_at_window (
225 screen, gtk_widget_get_window (toplevel));
226 else {
227 /* We don't know in which monitor the window manager
228 * will put us. So we will just use the geometry of
229 * the first monitor.
230 */
231 monitor = 0;
232 }
233
234 gdk_screen_get_monitor_geometry (screen, monitor, &rect);
235 screen_width = rect.width;
236 }
237
238 if (screen_width == 0)
239 screen_width = 1024;
240
241 return screen_width;
242 }
243
244 static void
245 mail_shell_sidebar_get_preferred_height (GtkWidget *widget,
246 gint *minimum_height,
247 gint *natural_height)
248 {
249 GTK_WIDGET_CLASS (e_mail_shell_sidebar_parent_class)->
250 get_preferred_height (widget, minimum_height, natural_height);
251 }
252
253 static void
254 mail_shell_sidebar_get_preferred_width (GtkWidget *widget,
255 gint *minimum_width,
256 gint *natural_width)
257 {
258 /* We override the normal size-request handler so that we can
259 * spit out a treeview with a suitable width. We measure the
260 * length of a typical string and use that as the requisition's
261 * width.
262 *
263 * EMFolderTreeClass, our parent class, is based on GtkTreeView,
264 * which doesn't really have a good way of figuring out a minimum
265 * width for the tree. This is really GTK+'s fault at large, as
266 * it only has "minimum size / allocated size", instead of
267 * "minimum size / preferred size / allocated size". Hopefully
268 * the extended-layout branch of GTK+ will get merged soon and
269 * then we can remove this crap.
270 */
271
272 EMailShellSidebar *sidebar;
273 PangoLayout *layout;
274 PangoRectangle ink_rect;
275 GtkStyle *style;
276 gint border;
277 gint sidebar_width;
278 gint screen_width;
279
280 sidebar = E_MAIL_SHELL_SIDEBAR (widget);
281
282 GTK_WIDGET_CLASS (e_mail_shell_sidebar_parent_class)->
283 get_preferred_width (widget, minimum_width, natural_width);
284
285 /* This string is a mockup only; it doesn't need to be translated */
286 layout = gtk_widget_create_pango_layout (
287 widget, "typical.account@mailservice.com");
288 pango_layout_get_pixel_extents (layout, &ink_rect, NULL);
289 g_object_unref (layout);
290
291 style = gtk_widget_get_style (widget);
292
293 screen_width = guess_screen_width (sidebar);
294
295 /* Thickness of frame shadow plus some slack for padding. */
296 border = 2 * style->xthickness + 4;
297 sidebar_width = ink_rect.width + border;
298 sidebar_width = MIN (sidebar_width, screen_width / 4);
299 *minimum_width = *natural_width = MAX (*natural_width, sidebar_width);
300 }
301
302 static guint32
303 mail_shell_sidebar_check_state (EShellSidebar *shell_sidebar)
304 {
305 EMailShellSidebarPrivate *priv;
306 EMailSidebar *sidebar;
307
308 priv = E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (shell_sidebar);
309 sidebar = E_MAIL_SIDEBAR (priv->folder_tree);
310
311 return e_mail_sidebar_check_state (sidebar);
312 }
313
314 static void
315 e_mail_shell_sidebar_class_init (EMailShellSidebarClass *class)
316 {
317 GObjectClass *object_class;
318 GtkWidgetClass *widget_class;
319 EShellSidebarClass *shell_sidebar_class;
320
321 g_type_class_add_private (class, sizeof (EMailShellSidebarPrivate));
322
323 object_class = G_OBJECT_CLASS (class);
324 object_class->get_property = mail_shell_sidebar_get_property;
325 object_class->dispose = mail_shell_sidebar_dispose;
326 object_class->constructed = mail_shell_sidebar_constructed;
327
328 widget_class = GTK_WIDGET_CLASS (class);
329 widget_class->get_preferred_width = mail_shell_sidebar_get_preferred_width;
330 widget_class->get_preferred_height = mail_shell_sidebar_get_preferred_height;
331
332 shell_sidebar_class = E_SHELL_SIDEBAR_CLASS (class);
333 shell_sidebar_class->check_state = mail_shell_sidebar_check_state;
334
335 g_object_class_install_property (
336 object_class,
337 PROP_FOLDER_TREE,
338 g_param_spec_object (
339 "folder-tree",
340 NULL,
341 NULL,
342 EM_TYPE_FOLDER_TREE,
343 G_PARAM_READABLE));
344 }
345
346 static void
347 e_mail_shell_sidebar_class_finalize (EMailShellSidebarClass *class)
348 {
349 }
350
351 static void
352 e_mail_shell_sidebar_init (EMailShellSidebar *mail_shell_sidebar)
353 {
354 mail_shell_sidebar->priv =
355 E_MAIL_SHELL_SIDEBAR_GET_PRIVATE (mail_shell_sidebar);
356
357 /* Postpone widget construction until we have a shell view. */
358 }
359
360 void
361 e_mail_shell_sidebar_type_register (GTypeModule *type_module)
362 {
363 /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
364 * function, so we have to wrap it with a public function in
365 * order to register types from a separate compilation unit. */
366 e_mail_shell_sidebar_register_type (type_module);
367 }
368
369 GtkWidget *
370 e_mail_shell_sidebar_new (EShellView *shell_view)
371 {
372 g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
373
374 return g_object_new (
375 E_TYPE_MAIL_SHELL_SIDEBAR,
376 "shell-view", shell_view, NULL);
377 }
378
379 EMFolderTree *
380 e_mail_shell_sidebar_get_folder_tree (EMailShellSidebar *mail_shell_sidebar)
381 {
382 g_return_val_if_fail (
383 E_IS_MAIL_SHELL_SIDEBAR (mail_shell_sidebar), NULL);
384
385 return EM_FOLDER_TREE (mail_shell_sidebar->priv->folder_tree);
386 }