]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-theme.c
Updatre python binding
[empathy.git] / libempathy-gtk / empathy-theme.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2007 Imendio AB
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include <string.h>
24 #include <glib/gi18n.h>
25 #include <gtk/gtk.h>
26
27 #include <libempathy/empathy-debug.h>
28 #include <libempathy/empathy-utils.h>
29
30 #include "empathy-chat.h"
31 #include "empathy-conf.h"
32 #include "empathy-preferences.h"
33 #include "empathy-theme.h"
34 #include "empathy-smiley-manager.h"
35
36 #define DEBUG_DOMAIN "Theme"
37
38 /* Number of seconds between timestamps when using normal mode, 5 minutes. */
39 #define TIMESTAMP_INTERVAL 300
40
41 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_THEME, EmpathyThemePriv))
42
43 typedef struct _EmpathyThemePriv EmpathyThemePriv;
44
45 struct _EmpathyThemePriv {
46         EmpathySmileyManager *smiley_manager;
47         gboolean show_avatars;
48 };
49
50 static void         theme_finalize            (GObject            *object);
51 static void         theme_get_property        (GObject            *object,
52                                                guint               param_id,
53                                                GValue             *value,
54                                                GParamSpec         *pspec);
55 static void         theme_set_property        (GObject            *object,
56                                                guint               param_id,
57                                                const GValue       *value,
58                                                GParamSpec         *pspec);
59
60
61 G_DEFINE_TYPE (EmpathyTheme, empathy_theme, G_TYPE_OBJECT);
62
63 enum {
64         PROP_0,
65         PROP_SHOW_AVATARS
66 };
67
68 static void
69 empathy_theme_class_init (EmpathyThemeClass *class)
70 {
71         GObjectClass *object_class;
72
73         object_class = G_OBJECT_CLASS (class);
74
75         object_class->finalize     = theme_finalize;
76         object_class->get_property = theme_get_property;
77         object_class->set_property = theme_set_property;
78
79         class->update_view      = NULL;
80         class->append_message   = NULL;
81         class->append_event     = NULL;
82         class->append_timestamp = NULL;
83         class->append_spacing   = NULL;
84
85         g_object_class_install_property (object_class,
86                                          PROP_SHOW_AVATARS,
87                                          g_param_spec_boolean ("show-avatars",
88                                                                "", "",
89                                                                TRUE,
90                                                                G_PARAM_READWRITE));
91
92         g_type_class_add_private (object_class, sizeof (EmpathyThemePriv));
93 }
94
95 static void
96 empathy_theme_init (EmpathyTheme *presence)
97 {
98         EmpathyThemePriv *priv;
99
100         priv = GET_PRIV (presence);
101
102         priv->smiley_manager = empathy_smiley_manager_new ();
103 }
104
105 static void
106 theme_finalize (GObject *object)
107 {
108         EmpathyThemePriv *priv;
109
110         priv = GET_PRIV (object);
111
112         if (priv->smiley_manager) {
113                 g_object_unref (priv->smiley_manager);
114         }
115
116         (G_OBJECT_CLASS (empathy_theme_parent_class)->finalize) (object);
117 }
118
119 static void
120 theme_get_property (GObject    *object,
121                     guint       param_id,
122                     GValue     *value,
123                     GParamSpec *pspec)
124 {
125         EmpathyThemePriv *priv;
126
127         priv = GET_PRIV (object);
128
129         switch (param_id) {
130         case PROP_SHOW_AVATARS:
131                 g_value_set_boolean (value, priv->show_avatars);
132                 break;
133         default:
134                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
135                 break;
136         }
137 }
138
139 static void
140 theme_set_property (GObject      *object,
141                     guint         param_id,
142                     const GValue *value,
143                     GParamSpec   *pspec)
144 {
145         EmpathyThemePriv *priv;
146
147         priv = GET_PRIV (object);
148
149         switch (param_id) {
150         case PROP_SHOW_AVATARS:
151                 empathy_theme_set_show_avatars (EMPATHY_THEME (object),
152                                                 g_value_get_boolean (value));
153                 break;
154         default:
155                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
156                 break;
157         }
158 }
159
160 void
161 empathy_theme_maybe_append_date_and_time (EmpathyTheme        *theme,
162                                          EmpathyChatView     *view,
163                                          EmpathyMessage      *message)
164 {
165         time_t    timestamp;
166         GDate    *date, *last_date;
167         gboolean  append_date, append_time;
168
169         date = empathy_message_get_date_and_time (message, &timestamp);
170
171         last_date = g_date_new ();
172         g_date_set_time (last_date, empathy_chat_view_get_last_timestamp (view));
173
174         append_date = FALSE;
175         append_time = FALSE;
176
177         if (g_date_compare (date, last_date) > 0) {
178                 append_date = TRUE;
179                 append_time = TRUE;
180         }
181         
182         g_date_free (last_date);
183         g_date_free (date);
184
185         if (empathy_chat_view_get_last_timestamp (view) + TIMESTAMP_INTERVAL < timestamp) {
186                 append_time = TRUE;
187         }
188
189         if (append_time || append_date) {
190                 empathy_theme_append_timestamp (theme, view, message,
191                                                append_date, append_time);
192         }
193 }
194
195 void
196 empathy_theme_update_view (EmpathyTheme    *theme,
197                            EmpathyChatView *view)
198 {
199         if (!EMPATHY_THEME_GET_CLASS(theme)->update_view) {
200                 g_error ("Theme must override update_view");
201         }
202
203         return EMPATHY_THEME_GET_CLASS(theme)->update_view (theme, view);
204 }
205
206 void
207 empathy_theme_append_message (EmpathyTheme        *theme,
208                              EmpathyChatView     *view,
209                              EmpathyMessage      *message)
210 {
211         if (!EMPATHY_THEME_GET_CLASS(theme)->append_message) {
212                 g_warning ("Theme should override append_message");
213                 return;
214         }
215
216         EMPATHY_THEME_GET_CLASS(theme)->append_message (theme, view, message);
217 }
218
219 static void
220 theme_insert_text_with_emoticons (GtkTextBuffer *buf,
221                                   GtkTextIter   *iter,
222                                   const gchar   *str,
223                                   EmpathySmileyManager *smiley_manager)
224 {
225         gboolean             use_smileys = FALSE;
226         GSList              *smileys, *l;
227
228         empathy_conf_get_bool (empathy_conf_get (),
229                               EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
230                               &use_smileys);
231
232         if (!use_smileys) {
233                 gtk_text_buffer_insert (buf, iter, str, -1);
234                 return;
235         }
236
237         smileys = empathy_smiley_manager_parse (smiley_manager, str);
238         for (l = smileys; l; l = l->next) {
239                 EmpathySmiley *smiley;
240
241                 smiley = l->data;
242                 if (smiley->pixbuf) {
243                         gtk_text_buffer_insert_pixbuf (buf, iter, smiley->pixbuf);
244                 } else {
245                         gtk_text_buffer_insert (buf, iter, smiley->str, -1);
246                 }
247                 empathy_smiley_free (smiley);
248         }
249         g_slist_free (smileys);
250 }
251
252 void
253 empathy_theme_append_text (EmpathyTheme        *theme,
254                           EmpathyChatView     *view,
255                           const gchar        *body,
256                           const gchar        *tag,
257                           const gchar        *link_tag)
258 {
259         EmpathyThemePriv *priv;
260         GtkTextBuffer   *buffer;
261         GtkTextIter      start_iter, end_iter;
262         GtkTextMark     *mark;
263         GtkTextIter      iter;
264         gint             num_matches, i;
265         GArray          *start, *end;
266
267         priv = GET_PRIV (theme);
268         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
269
270         gtk_text_buffer_get_end_iter (buffer, &start_iter);
271         mark = gtk_text_buffer_create_mark (buffer, NULL, &start_iter, TRUE);
272
273         start = g_array_new (FALSE, FALSE, sizeof (gint));
274         end = g_array_new (FALSE, FALSE, sizeof (gint));
275
276         num_matches = empathy_regex_match (EMPATHY_REGEX_ALL, body, start, end);
277
278         if (num_matches == 0) {
279                 gtk_text_buffer_get_end_iter (buffer, &iter);
280                 theme_insert_text_with_emoticons (buffer, &iter, body, priv->smiley_manager);
281         } else {
282                 gint   last = 0;
283                 gint   s = 0, e = 0;
284                 gchar *tmp;
285
286                 for (i = 0; i < num_matches; i++) {
287                         s = g_array_index (start, gint, i);
288                         e = g_array_index (end, gint, i);
289
290                         if (s > last) {
291                                 tmp = empathy_substring (body, last, s);
292
293                                 gtk_text_buffer_get_end_iter (buffer, &iter);
294                                 theme_insert_text_with_emoticons (buffer,
295                                                                   &iter,
296                                                                   tmp,
297                                                                   priv->smiley_manager);
298                                 g_free (tmp);
299                         }
300
301                         tmp = empathy_substring (body, s, e);
302
303                         gtk_text_buffer_get_end_iter (buffer, &iter);
304                         if (!link_tag) {
305                                 gtk_text_buffer_insert (buffer, &iter,
306                                                         tmp, -1);
307                         } {
308                                 gtk_text_buffer_insert_with_tags_by_name (buffer,
309                                                                           &iter,
310                                                                           tmp,
311                                                                           -1,
312                                                                           link_tag,
313                                                                           "link",
314                                                                           NULL);
315                         }
316
317                         g_free (tmp);
318
319                         last = e;
320                 }
321
322                 if (e < strlen (body)) {
323                         tmp = empathy_substring (body, e, strlen (body));
324
325                         gtk_text_buffer_get_end_iter (buffer, &iter);
326                         theme_insert_text_with_emoticons (buffer,
327                                                           &iter,
328                                                           tmp,
329                                                           priv->smiley_manager);
330                         g_free (tmp);
331                 }
332         }
333
334         g_array_free (start, TRUE);
335         g_array_free (end, TRUE);
336
337         gtk_text_buffer_get_end_iter (buffer, &iter);
338         gtk_text_buffer_insert (buffer, &iter, "\n", 1);
339
340         /* Apply the style to the inserted text. */
341         gtk_text_buffer_get_iter_at_mark (buffer, &start_iter, mark);
342         gtk_text_buffer_get_end_iter (buffer, &end_iter);
343
344         gtk_text_buffer_apply_tag_by_name (buffer,
345                                            tag,
346                                            &start_iter,
347                                            &end_iter);
348
349         gtk_text_buffer_delete_mark (buffer, mark);
350 }
351
352 void 
353 empathy_theme_append_event (EmpathyTheme        *theme,
354                            EmpathyChatView     *view,
355                            const gchar        *str)
356 {
357         if (!EMPATHY_THEME_GET_CLASS(theme)->append_event) {
358                 return;
359         }
360
361         EMPATHY_THEME_GET_CLASS(theme)->append_event (theme, view, str);
362 }
363
364 void
365 empathy_theme_append_spacing (EmpathyTheme        *theme, 
366                              EmpathyChatView     *view)
367 {
368         if (!EMPATHY_THEME_GET_CLASS(theme)->append_spacing) {
369                 return;
370         }
371
372         EMPATHY_THEME_GET_CLASS(theme)->append_spacing (theme, view);
373 }
374
375
376 void 
377 empathy_theme_append_timestamp (EmpathyTheme        *theme,
378                                EmpathyChatView     *view,
379                                EmpathyMessage      *message,
380                                gboolean            show_date,
381                                gboolean            show_time)
382 {
383         if (!EMPATHY_THEME_GET_CLASS(theme)->append_timestamp) {
384                 return;
385         }
386
387         EMPATHY_THEME_GET_CLASS(theme)->append_timestamp (theme, view,
388                                                          message, show_date,
389                                                          show_time);
390 }
391
392 gboolean
393 empathy_theme_get_show_avatars (EmpathyTheme *theme)
394 {
395         EmpathyThemePriv *priv;
396
397         g_return_val_if_fail (EMPATHY_IS_THEME (theme), FALSE);
398
399         priv = GET_PRIV (theme);
400
401         return priv->show_avatars;
402 }
403
404 void
405 empathy_theme_set_show_avatars (EmpathyTheme *theme, gboolean show)
406 {
407         EmpathyThemePriv *priv;
408
409         g_return_if_fail (EMPATHY_IS_THEME (theme));
410
411         priv = GET_PRIV (theme);
412
413         priv->show_avatars = show;
414
415         g_object_notify (G_OBJECT (theme), "show-avatars");
416 }
417