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