]> git.0d.be Git - empathy.git/commitdiff
Move modules that make no sense to be used in other applicaton from libempathy-gtk...
authorXavier Claessens <xclaesse@src.gnome.org>
Thu, 13 Mar 2008 17:41:08 +0000 (17:41 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Thu, 13 Mar 2008 17:41:08 +0000 (17:41 +0000)
svn path=/trunk/; revision=789

62 files changed:
libempathy-gtk/Makefile.am
libempathy-gtk/empathy-about-dialog.c [deleted file]
libempathy-gtk/empathy-about-dialog.h [deleted file]
libempathy-gtk/empathy-avatar-chooser.c
libempathy-gtk/empathy-call-window.c [deleted file]
libempathy-gtk/empathy-call-window.glade [deleted file]
libempathy-gtk/empathy-call-window.h [deleted file]
libempathy-gtk/empathy-chat-view.c
libempathy-gtk/empathy-chat-window.c [deleted file]
libempathy-gtk/empathy-chat-window.h [deleted file]
libempathy-gtk/empathy-chat.c
libempathy-gtk/empathy-chat.h
libempathy-gtk/empathy-chatrooms-window.c [deleted file]
libempathy-gtk/empathy-chatrooms-window.glade [deleted file]
libempathy-gtk/empathy-chatrooms-window.h [deleted file]
libempathy-gtk/empathy-conf.h
libempathy-gtk/empathy-group-chat.c
libempathy-gtk/empathy-main-window.c [deleted file]
libempathy-gtk/empathy-main-window.glade [deleted file]
libempathy-gtk/empathy-main-window.h [deleted file]
libempathy-gtk/empathy-new-chatroom-dialog.c [deleted file]
libempathy-gtk/empathy-new-chatroom-dialog.glade [deleted file]
libempathy-gtk/empathy-new-chatroom-dialog.h [deleted file]
libempathy-gtk/empathy-preferences.c [deleted file]
libempathy-gtk/empathy-preferences.glade [deleted file]
libempathy-gtk/empathy-preferences.h [deleted file]
libempathy-gtk/empathy-private-chat.c
libempathy-gtk/empathy-spell.c
libempathy-gtk/empathy-status-icon.c [deleted file]
libempathy-gtk/empathy-status-icon.glade [deleted file]
libempathy-gtk/empathy-status-icon.h [deleted file]
libempathy-gtk/empathy-theme-boxes.c
libempathy-gtk/empathy-theme-manager.c
libempathy-gtk/empathy-theme.c
libempathy-gtk/ephy-spinner.c [deleted file]
libempathy-gtk/ephy-spinner.h [deleted file]
src/Makefile.am
src/empathy-about-dialog.c [new file with mode: 0644]
src/empathy-about-dialog.h [new file with mode: 0644]
src/empathy-call-window.c [new file with mode: 0644]
src/empathy-call-window.glade [new file with mode: 0644]
src/empathy-call-window.h [new file with mode: 0644]
src/empathy-chat-window.c [new file with mode: 0644]
src/empathy-chat-window.h [new file with mode: 0644]
src/empathy-chatrooms-window.c [new file with mode: 0644]
src/empathy-chatrooms-window.glade [new file with mode: 0644]
src/empathy-chatrooms-window.h [new file with mode: 0644]
src/empathy-main-window.c [new file with mode: 0644]
src/empathy-main-window.glade [new file with mode: 0644]
src/empathy-main-window.h [new file with mode: 0644]
src/empathy-new-chatroom-dialog.c [new file with mode: 0644]
src/empathy-new-chatroom-dialog.glade [new file with mode: 0644]
src/empathy-new-chatroom-dialog.h [new file with mode: 0644]
src/empathy-preferences.c [new file with mode: 0644]
src/empathy-preferences.glade [new file with mode: 0644]
src/empathy-preferences.h [new file with mode: 0644]
src/empathy-status-icon.c [new file with mode: 0644]
src/empathy-status-icon.glade [new file with mode: 0644]
src/empathy-status-icon.h [new file with mode: 0644]
src/empathy.c
src/ephy-spinner.c [new file with mode: 0644]
src/ephy-spinner.h [new file with mode: 0644]

index 88e10794d6d2cda8c7a94da74034c4644772dad5..d29a11f6b15bd26513ef7370a5fe8e7f250fb2dc 100644 (file)
@@ -15,48 +15,39 @@ BUILT_SOURCES =                                     \
 lib_LTLIBRARIES = libempathy-gtk.la
 
 libempathy_gtk_la_SOURCES =                    \
-       ephy-spinner.c ephy-spinner.h           \
-       empathy-main-window.c                   \
-       empathy-status-icon.c                   \
-       empathy-conf.c                          \
-       empathy-contact-widget.c                \
-       empathy-contact-dialogs.c               \
+       empathy-account-chooser.c               \
+       empathy-chat.c                          \
+       empathy-irc-network-dialog.c            \
+       empathy-spell-dialog.c                  \
        empathy-accounts-dialog.c               \
+       empathy-chat-view.c                     \
+       empathy-log-window.c                    \
+       empathy-theme-boxes.c                   \
        empathy-account-widget.c                \
-       empathy-account-widget-irc.c            \
-       empathy-profile-chooser.c               \
-       empathy-cell-renderer-expander.c        \
-       empathy-cell-renderer-text.c            \
-       empathy-cell-renderer-activatable.c     \
-       empathy-spell.c                         \
-       empathy-spell-dialog.c                  \
-       empathy-contact-list-store.c            \
-       empathy-contact-list-view.c             \
-       empathy-preferences.c                   \
+       empathy-conf.c                          \
        empathy-theme.c                         \
-       empathy-theme-boxes.c                   \
+       empathy-account-widget-irc.c            \
+       empathy-contact-dialogs.c               \
+       empathy-new-message-dialog.c            \
        empathy-theme-irc.c                     \
-       empathy-theme-manager.c                 \
-       empathy-smiley-manager.c                \
-       empathy-chat-window.c                   \
-       empathy-chat.c                          \
-       empathy-chat-view.c                     \
-       empathy-private-chat.c                  \
-       empathy-group-chat.c                    \
-       empathy-geometry.c                      \
-       empathy-presence-chooser.c              \
-       empathy-about-dialog.c                  \
-       empathy-account-chooser.c               \
-       empathy-new-chatroom-dialog.c           \
-       empathy-chatrooms-window.c              \
-       empathy-log-window.c                    \
-       empathy-call-window.c                   \
        empathy-avatar-chooser.c                \
+       empathy-contact-list-store.c            \
+       empathy-presence-chooser.c              \
+       empathy-theme-manager.c                 \
        empathy-avatar-image.c                  \
+       empathy-contact-list-view.c             \
+       empathy-private-chat.c                  \
        empathy-ui-utils.c                      \
-       empathy-new-message-dialog.c            \
-       empathy-irc-network-dialog.c            \
-       totem-subtitle-encoding.c  totem-subtitle-encoding.h
+       empathy-cell-renderer-activatable.c     \
+       empathy-contact-widget.c                \
+       empathy-profile-chooser.c               \
+       empathy-cell-renderer-expander.c        \
+       empathy-geometry.c                      \
+       empathy-smiley-manager.c                \
+       empathy-cell-renderer-text.c            \
+       empathy-group-chat.c                    \
+       empathy-spell.c                         \
+       totem-subtitle-encoding.c totem-subtitle-encoding.h
 
 # do not distribute generated files
 nodist_libempathy_gtk_la_SOURCES =\
@@ -72,46 +63,38 @@ libempathy_gtk_la_LDFLAGS =                \
 
 libempathy_gtk_headers =                       \
        empathy-images.h                        \
-       empathy-main-window.h                   \
-       empathy-status-icon.h                   \
-       empathy-conf.h                          \
-       empathy-contact-widget.h                \
-       empathy-contact-dialogs.h               \
+       empathy-account-chooser.h               \
+       empathy-chat.h                          \
+       empathy-irc-network-dialog.h            \
+       empathy-spell-dialog.h                  \
        empathy-accounts-dialog.h               \
+       empathy-chat-view.h                     \
+       empathy-log-window.h                    \
+       empathy-theme-boxes.h                   \
        empathy-account-widget.h                \
-       empathy-account-widget-irc.h            \
-       empathy-profile-chooser.h               \
-       empathy-cell-renderer-expander.h        \
-       empathy-cell-renderer-text.h            \
-       empathy-cell-renderer-activatable.h     \
-       empathy-spell.h                         \
-       empathy-spell-dialog.h                  \
-       empathy-contact-list-store.h            \
-       empathy-contact-list-view.h             \
-       empathy-preferences.h                   \
+       empathy-conf.h                          \
        empathy-theme.h                         \
-       empathy-theme-boxes.h                   \
+       empathy-account-widget-irc.h            \
+       empathy-contact-dialogs.h               \
+       empathy-new-message-dialog.h            \
        empathy-theme-irc.h                     \
-       empathy-theme-manager.h                 \
-       empathy-smiley-manager.h                \
-       empathy-chat-window.h                   \
-       empathy-chat.h                          \
-       empathy-chat-view.h                     \
-       empathy-private-chat.h                  \
-       empathy-group-chat.h                    \
-       empathy-geometry.h                      \
-       empathy-presence-chooser.h              \
-       empathy-about-dialog.h                  \
-       empathy-account-chooser.h               \
-       empathy-new-chatroom-dialog.h           \
-       empathy-chatrooms-window.h              \
-       empathy-log-window.h                    \
-       empathy-call-window.h                   \
        empathy-avatar-chooser.h                \
+       empathy-contact-list-store.h            \
+       empathy-presence-chooser.h              \
+       empathy-theme-manager.h                 \
        empathy-avatar-image.h                  \
+       empathy-contact-list-view.h             \
+       empathy-private-chat.h                  \
        empathy-ui-utils.h                      \
-       empathy-new-message-dialog.h            \
-       empathy-irc-network-dialog.h
+       empathy-cell-renderer-activatable.h     \
+       empathy-contact-widget.h                \
+       empathy-profile-chooser.h               \
+       empathy-cell-renderer-expander.h        \
+       empathy-geometry.h                      \
+       empathy-smiley-manager.h                \
+       empathy-cell-renderer-text.h            \
+       empathy-group-chat.h                    \
+       empathy-spell.h
 
 libempathy_gtk_includedir = $(includedir)/libempathy-gtk/
 libempathy_gtk_include_HEADERS =               \
@@ -120,11 +103,8 @@ libempathy_gtk_include_HEADERS =           \
 
 gladedir = $(datadir)/empathy
 glade_DATA =                                   \
-       empathy-main-window.glade               \
-       empathy-status-icon.glade               \
        empathy-contact-widget.glade            \
        empathy-contact-dialogs.glade           \
-       empathy-preferences.glade               \
        empathy-presence-chooser.glade          \
        empathy-accounts-dialog.glade           \
        empathy-account-widget-generic.glade    \
@@ -134,12 +114,9 @@ glade_DATA =                                       \
        empathy-account-widget-irc.glade        \
        empathy-account-widget-icq.glade        \
        empathy-account-widget-yahoo.glade      \
-       empathy-new-chatroom-dialog.glade       \
        empathy-group-chat.glade                \
-       empathy-chatrooms-window.glade          \
        empathy-spell-dialog.glade              \
        empathy-log-window.glade                \
-       empathy-call-window.glade               \
        empathy-chat.glade                      \
        empathy-new-message-dialog.glade
 
diff --git a/libempathy-gtk/empathy-about-dialog.c b/libempathy-gtk/empathy-about-dialog.c
deleted file mode 100644 (file)
index 5ecf667..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Martyn Russell <martyn@imendio.com>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include "config.h"
-
-#include <glib/gi18n.h>
-#include <gtk/gtkaboutdialog.h>
-#include <gtk/gtksizegroup.h>
-#include <glade/glade.h>
-
-#include "empathy-about-dialog.h"
-#include "empathy-ui-utils.h"
-
-#define WEB_SITE "http://live.gnome.org/Empathy"
-
-static void about_dialog_activate_link_cb (GtkAboutDialog  *about,
-                                          const gchar     *link,
-                                          gpointer         data);
-
-static const char *authors[] = {
-       "Mikael Hallendal",
-       "Richard Hult",
-       "Martyn Russell",
-       "Geert-Jan Van den Bogaerde",
-       "Kevin Dougherty",
-       "Eitan Isaacson",
-       "Xavier Claessens",
-       NULL
-};
-
-static const char *documenters[] = {
-       NULL
-};
-
-static const char *artists[] = {
-       "Andreas Nilsson <nisses.mail@home.se>",
-       "Vinicius Depizzol <vdepizzol@gmail.com>",
-       NULL
-};
-
-static const char *license[] = {
-       N_("Empathy is free software; you can redistribute it and/or modify "
-          "it under the terms of the GNU General Public License as published by "
-          "the Free Software Foundation; either version 2 of the License, or "
-          "(at your option) any later version."),
-       N_("Empathy is distributed in the hope that it will be useful, "
-          "but WITHOUT ANY WARRANTY; without even the implied warranty of "
-          "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
-          "GNU General Public License for more details."),
-       N_("You should have received a copy of the GNU General Public License "
-          "along with Empathy; if not, write to the Free Software Foundation, Inc., "
-          "51 Franklin Street, Fifth Floor, Boston, MA 02110-130159 USA")
-};
-
-static void
-about_dialog_activate_link_cb (GtkAboutDialog *about,
-                              const gchar    *link,
-                              gpointer        data)
-{
-       empathy_url_show (link);
-}
-
-void
-empathy_about_dialog_new (GtkWindow *parent)
-{
-       gchar *license_trans;
-
-       gtk_about_dialog_set_url_hook (about_dialog_activate_link_cb, NULL, NULL);
-
-       license_trans = g_strconcat (_(license[0]), "\n\n",
-                                    _(license[1]), "\n\n",
-                                    _(license[2]), "\n\n",
-                                    NULL);
-
-       gtk_show_about_dialog (parent,
-                              "artists", artists,
-                              "authors", authors,
-                              "comments", _("An Instant Messaging client for GNOME"),
-                              "license", license_trans,
-                              "wrap-license", TRUE,
-                              "copyright", "Imendio AB 2002-2007\nCollabora Ltd 2007",
-                              "documenters", documenters,
-                              "logo-icon-name", "empathy",
-                              "translator-credits", _("translator-credits"),
-                              "version", PACKAGE_VERSION,
-                              "website", WEB_SITE,
-                              NULL);
-
-       g_free (license_trans);
-}
-
-
diff --git a/libempathy-gtk/empathy-about-dialog.h b/libempathy-gtk/empathy-about-dialog.h
deleted file mode 100644 (file)
index ff123ab..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Martyn Russell <martyn@imendio.com>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_ABOUT_DIALOG_H__
-#define __EMPATHY_ABOUT_DIALOG_H__
-
-#include <gtk/gtkwindow.h>
-
-G_BEGIN_DECLS
-
-void empathy_about_dialog_new (GtkWindow *parent);
-
-G_END_DECLS
-
-#endif /*  __EMPATHY_ABOUT_DIALOG_H__ */
index 7ff34e812a2574952382fff12a7aca413a8b29cb..99132b8a1739abae0ad5427fc68f53ad14cda950 100644 (file)
@@ -33,7 +33,6 @@
 
 #include "empathy-avatar-chooser.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 #include "empathy-ui-utils.h"
 
 #define DEBUG_DOMAIN "AvatarChooser"
diff --git a/libempathy-gtk/empathy-call-window.c b/libempathy-gtk/empathy-call-window.c
deleted file mode 100644 (file)
index c7f202e..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- *  Copyright (C) 2007 Elliot Fairweather
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *  Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
- */
-
-#include <string.h>
-
-#include <libtelepathy/tp-chan.h>
-
-#include <libmissioncontrol/mc-account.h>
-#include <libmissioncontrol/mc-account-monitor.h>
-#include <libmissioncontrol/mission-control.h>
-
-#include <libempathy/empathy-contact.h>
-#include <libempathy/empathy-tp-call.h>
-#include <libempathy/empathy-chandler.h>
-#include <libempathy/empathy-debug.h>
-#include <libempathy/empathy-utils.h>
-
-#include <libempathy-gtk/empathy-call-window.h>
-#include <libempathy-gtk/empathy-ui-utils.h>
-
-#define DEBUG_DOMAIN "CallWindow"
-
-typedef struct 
-{
-  GtkWidget *window;
-  GtkWidget *status_label;
-  GtkWidget *start_call_button;
-  GtkWidget *end_call_button;
-  GtkWidget *input_volume_scale;
-  GtkWidget *output_volume_scale;
-  GtkWidget *input_mute_button;
-  GtkWidget *output_mute_button;
-  GtkWidget *preview_video_frame;
-  GtkWidget *output_video_frame;
-  GtkWidget *preview_video_socket;
-  GtkWidget *output_video_socket;
-  GtkWidget *video_button;
-  GtkWidget *output_video_label;
-
-  EmpathyTpCall *call;
-
-  GTimeVal start_time;
-  guint timeout_event_id;
-
-  gboolean is_drawing;
-} EmpathyCallWindow;
-
-static gboolean
-call_window_update_timer (gpointer data)
-{
-  EmpathyCallWindow *window = data;
-  GTimeVal current;
-  gchar *str;
-  glong now, then;
-  glong time, seconds, minutes, hours;
-
-  g_get_current_time (&current);
-
-  now = current.tv_sec;
-  then = (window->start_time).tv_sec;
-
-  time = now - then;
-
-  seconds = time % 60;
-  time /= 60;
-  minutes = time % 60;
-  time /= 60;
-  hours = time % 60;
-
-  if (hours > 0)
-    {
-      str = g_strdup_printf ("Connected  -  %02ld : %02ld : %02ld", hours,
-          minutes, seconds);
-    }
-  else
-    {
-      str = g_strdup_printf ("Connected  -  %02ld : %02ld", minutes, seconds);
-    }
-
-  gtk_label_set_text (GTK_LABEL (window->status_label), str);
-
-  g_free (str);
-
-  return TRUE;
-}
-
-static void
-call_window_stop_timeout (EmpathyCallWindow *window)
-{
-  GMainContext *context;
-  GSource *source;
-
-  context = g_main_context_default ();
-
-  empathy_debug (DEBUG_DOMAIN, "Timer stopped");
-
-  if (window->timeout_event_id)
-    {
-      source = g_main_context_find_source_by_id (context,
-          window->timeout_event_id);
-      g_source_destroy (source);
-      window->timeout_event_id = 0;
-    }
-}
-
-static void
-call_window_set_output_video_is_drawing (EmpathyCallWindow *window,
-                                         gboolean is_drawing)
-{
-  GtkWidget* child;
-
-  child = gtk_bin_get_child (GTK_BIN (window->output_video_frame));
-
-  empathy_debug (DEBUG_DOMAIN,
-      "Setting output video is drawing - %d", is_drawing);
-
-  if (is_drawing)
-    {
-      if (!window->is_drawing)
-        {
-          if (child)
-            {
-              gtk_container_remove (GTK_CONTAINER (window->output_video_frame),
-                  child);
-            }
-          gtk_container_add (GTK_CONTAINER (window->output_video_frame),
-              window->output_video_socket);
-          gtk_widget_show (window->output_video_socket);
-          empathy_tp_call_add_output_video (window->call,
-              gtk_socket_get_id (GTK_SOCKET (window->output_video_socket)));
-          window->is_drawing = is_drawing;
-        }
-    }
-  else
-    {
-      if (window->is_drawing)
-        {
-          empathy_tp_call_add_output_video (window->call, 0);
-          if (child)
-            {
-              gtk_container_remove (GTK_CONTAINER (window->output_video_frame),
-                  child);
-            }
-          gtk_container_add (GTK_CONTAINER (window->output_video_frame),
-              window->output_video_label);
-          gtk_widget_show (window->output_video_label);
-          window->is_drawing = is_drawing;
-        }
-    }
-}
-
-static gboolean
-call_window_delete_event_cb (GtkWidget *widget,
-                             GdkEvent *event,
-                             EmpathyCallWindow *window)
-{
-  GtkWidget *dialog;
-  gint result;
-  guint status;
-
-  empathy_debug (DEBUG_DOMAIN, "Delete event occurred");
-
-  g_object_get (G_OBJECT (window->call), "status", &status, NULL);
-
-  if (status != EMPATHY_TP_CALL_STATUS_CLOSED)
-    {
-      dialog = gtk_message_dialog_new (GTK_WINDOW (window->window),
-          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-          GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
-          "This call will be ended. Continue?");
-
-      result = gtk_dialog_run (GTK_DIALOG (dialog));
-      gtk_widget_destroy (dialog);
-
-      switch (result)
-        {
-        case GTK_RESPONSE_YES:
-          call_window_stop_timeout (window);
-          call_window_set_output_video_is_drawing (window, FALSE);
-          empathy_tp_call_close_channel (window->call);
-          empathy_tp_call_remove_preview_video (window->call,
-              gtk_socket_get_id (GTK_SOCKET (window->preview_video_socket)));
-          return FALSE;
-        default:
-          return TRUE;
-        }
-    }
-  else
-    {
-      empathy_tp_call_remove_preview_video (window->call,
-          gtk_socket_get_id (GTK_SOCKET (window->preview_video_socket)));
-      return FALSE;
-    }
-}
-
-static void
-call_window_video_button_toggled_cb (GtkWidget *button,
-                                     EmpathyCallWindow *window)
-{
-  gboolean is_sending;
-
-  is_sending = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
-
-  empathy_debug (DEBUG_DOMAIN, "Send video toggled - %d", is_sending);
-
-  empathy_tp_call_request_video_stream_direction (window->call, is_sending);
-}
-
-static void
-call_window_status_changed_cb (EmpathyTpCall *call,
-                               EmpathyCallWindow *window)
-{
-  EmpathyContact *contact;
-  guint status;
-  guint stream_state;
-  EmpathyTpCallStream *audio_stream;
-  EmpathyTpCallStream *video_stream;
-  gboolean is_incoming;
-  gchar *title;
-
-  g_object_get (G_OBJECT (window->call), "status", &status, NULL);
-  g_object_get (G_OBJECT (window->call), "audio-stream", &audio_stream, NULL);
-  g_object_get (G_OBJECT (window->call), "video-stream", &video_stream, NULL);
-
-  if (video_stream->state > audio_stream->state)
-    {
-      stream_state = video_stream->state;
-    }
-  else
-    {
-      stream_state = audio_stream->state;
-    }
-
-  empathy_debug (DEBUG_DOMAIN, "Status changed - status: %d, stream state: %d",
-      status, stream_state);
-
-  if (window->timeout_event_id)
-    {
-      call_window_stop_timeout (window);
-    }
-
-  if (status == EMPATHY_TP_CALL_STATUS_CLOSED)
-    {
-      gtk_label_set_text (GTK_LABEL (window->status_label), "Closed");
-      gtk_widget_set_sensitive (window->end_call_button, FALSE);
-      gtk_widget_set_sensitive (window->start_call_button, FALSE);
-
-      call_window_set_output_video_is_drawing (window, FALSE);
-    }
-  else if (stream_state == TP_MEDIA_STREAM_STATE_DISCONNECTED)
-    {
-      gtk_label_set_text (GTK_LABEL (window->status_label), "Disconnected");
-    }
-  else if (status == EMPATHY_TP_CALL_STATUS_PENDING)
-    {
-      g_object_get (G_OBJECT (window->call), "contact", &contact, NULL);
-
-      title = g_strdup_printf ("%s - Empathy Call",
-          empathy_contact_get_name (contact));
-      gtk_window_set_title (GTK_WINDOW (window->window), title);
-
-      gtk_label_set_text (GTK_LABEL (window->status_label), "Ringing");
-      gtk_widget_set_sensitive (window->end_call_button, TRUE);
-      gtk_widget_set_sensitive (window->video_button, TRUE);
-
-      g_object_get (G_OBJECT (window->call), "is-incoming", &is_incoming, NULL);
-      if (is_incoming)
-        {
-          gtk_widget_set_sensitive (window->start_call_button, TRUE);
-        }
-      else
-        {
-          g_signal_connect (GTK_OBJECT (window->video_button), "toggled",
-              G_CALLBACK (call_window_video_button_toggled_cb),
-              window);
-        }
-    }
-  else if (status == EMPATHY_TP_CALL_STATUS_ACCEPTED)
-    {
-      if (stream_state == TP_MEDIA_STREAM_STATE_CONNECTING)
-        {
-          gtk_label_set_text (GTK_LABEL (window->status_label), "Connecting");
-        }
-      else if (stream_state == TP_MEDIA_STREAM_STATE_CONNECTED)
-        {
-          if ((window->start_time).tv_sec == 0)
-            {
-              g_get_current_time (&(window->start_time));
-            }
-          window->timeout_event_id = g_timeout_add (1000,
-              call_window_update_timer, window);
-          empathy_debug (DEBUG_DOMAIN, "Timer started");
-        }
-    }
-}
-
-static void
-call_window_receiving_video_cb (EmpathyTpCall *call,
-                                gboolean receiving_video,
-                                EmpathyCallWindow *window)
-{
-  empathy_debug (DEBUG_DOMAIN, "Receiving video signal received");
-
-  call_window_set_output_video_is_drawing (window, receiving_video);
-}
-
-static void
-call_window_sending_video_cb (EmpathyTpCall *call,
-                              gboolean sending_video,
-                              EmpathyCallWindow *window)
-{
-  empathy_debug (DEBUG_DOMAIN, "Sending video signal received");
-
-  g_signal_handlers_block_by_func (window->video_button,
-      call_window_video_button_toggled_cb, window);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->video_button),
-      sending_video);
-  g_signal_handlers_unblock_by_func (window->video_button,
-      call_window_video_button_toggled_cb, window);
-}
-
-static void
-call_window_socket_realized_cb (GtkWidget *widget,
-                                EmpathyCallWindow *window)
-{
-  if (widget == window->preview_video_socket)
-    {
-      empathy_debug (DEBUG_DOMAIN, "Preview socket realized");
-      empathy_tp_call_add_preview_video (window->call,
-          gtk_socket_get_id (GTK_SOCKET (window->preview_video_socket)));
-    }
-  else
-    {
-      empathy_debug (DEBUG_DOMAIN, "Output socket realized");
-    }
-}
-
-static void
-call_window_start_call_button_clicked_cb (GtkWidget *widget,
-                                          EmpathyCallWindow *window)
-{
-  gboolean send_video;
-  gboolean is_incoming;
-
-  empathy_debug (DEBUG_DOMAIN, "Start call clicked");
-
-  gtk_widget_set_sensitive (window->start_call_button, FALSE);
-  g_object_get (G_OBJECT (window->call), "is-incoming", &is_incoming, NULL);
-  if (is_incoming)
-    {
-      empathy_tp_call_accept_incoming_call (window->call);
-      send_video = gtk_toggle_button_get_active
-          (GTK_TOGGLE_BUTTON (window->video_button));
-      empathy_tp_call_request_video_stream_direction (window->call, send_video);
-      g_signal_connect (GTK_OBJECT (window->video_button), "toggled",
-          G_CALLBACK (call_window_video_button_toggled_cb), window);
-    }
-}
-
-static void
-call_window_end_call_button_clicked_cb (GtkWidget *widget,
-                                        EmpathyCallWindow *window)
-{
-  empathy_debug (DEBUG_DOMAIN, "End call clicked");
-
-  call_window_set_output_video_is_drawing (window, FALSE);
-  empathy_tp_call_close_channel (window->call);
-  gtk_widget_set_sensitive (window->end_call_button, FALSE);
-  gtk_widget_set_sensitive (window->start_call_button, FALSE);
-}
-
-static void
-call_window_output_volume_changed_cb (GtkWidget *scale,
-                                      EmpathyCallWindow *window)
-{
-  guint volume;
-
-  volume = (guint) gtk_range_get_value (GTK_RANGE (scale));
-
-  empathy_debug (DEBUG_DOMAIN, "Output volume changed - %u", volume);
-
-  empathy_tp_call_set_output_volume (window->call, volume);
-}
-
-static void
-call_window_output_mute_button_toggled_cb (GtkWidget *button,
-                                           EmpathyCallWindow *window)
-{
-  gboolean is_muted;
-
-  is_muted = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
-
-  empathy_debug (DEBUG_DOMAIN, "Mute output toggled - %d", is_muted);
-
-  empathy_tp_call_mute_output (window->call, is_muted);
-}
-
-static void
-call_window_input_mute_button_toggled_cb (GtkWidget *button,
-                                          EmpathyCallWindow *window)
-{
-  gboolean is_muted;
-
-  is_muted = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
-
-  empathy_debug (DEBUG_DOMAIN, "Mute input toggled - %d", is_muted);
-
-  empathy_tp_call_mute_input (window->call, is_muted);
-}
-
-static void
-call_window_destroy_cb (GtkWidget *widget,
-                        EmpathyCallWindow *window)
-{
-  g_signal_handlers_disconnect_by_func (window->call,
-      call_window_status_changed_cb, window);
-  g_signal_handlers_disconnect_by_func (window->call,
-      call_window_receiving_video_cb, window);
-  g_signal_handlers_disconnect_by_func (window->call,
-      call_window_sending_video_cb, window);
-
-  g_object_unref (window->call);
-  g_object_unref (window->output_video_socket);
-  g_object_unref (window->preview_video_socket);
-  g_object_unref (window->output_video_label);
-
-  g_slice_free (EmpathyCallWindow, window);
-}
-
-GtkWidget *
-empathy_call_window_new (EmpathyTpCall *call)
-{
-  EmpathyCallWindow *window;
-  GladeXML *glade;
-  guint status;
-
-  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), NULL);
-
-  window = g_slice_new0 (EmpathyCallWindow);
-  window->call = g_object_ref (call);
-
-  glade = empathy_glade_get_file ("empathy-call-window.glade",
-      "window",
-      NULL,
-      "window", &window->window,
-      "status_label", &window->status_label,
-      "start_call_button", &window->start_call_button,
-      "end_call_button", &window->end_call_button,
-      "input_volume_scale", &window->input_volume_scale,
-      "output_volume_scale", &window->output_volume_scale,
-      "input_mute_button", &window->input_mute_button,
-      "output_mute_button", &window->output_mute_button,
-      "preview_video_frame", &window->preview_video_frame,
-      "output_video_frame", &window->output_video_frame,
-      "video_button", &window->video_button,
-      NULL);
-
-  empathy_glade_connect (glade,
-      window,
-      "window", "destroy", call_window_destroy_cb,
-      "window", "delete_event", call_window_delete_event_cb,
-      "input_mute_button", "toggled", call_window_input_mute_button_toggled_cb,
-      "output_mute_button", "toggled", call_window_output_mute_button_toggled_cb,
-      "output_volume_scale", "value-changed", call_window_output_volume_changed_cb,
-      "start_call_button", "clicked", call_window_start_call_button_clicked_cb,
-      "end_call_button", "clicked", call_window_end_call_button_clicked_cb,
-      NULL);
-
-  g_object_unref (glade);
-
-  /* Output video label */
-  window->output_video_label = g_object_ref (gtk_label_new ("No video output"));
-  gtk_container_add (GTK_CONTAINER (window->output_video_frame),
-      window->output_video_label);
-  gtk_widget_show (window->output_video_label);
-
-  /* Output video socket */
-  window->output_video_socket = g_object_ref (gtk_socket_new ());
-  g_signal_connect (GTK_OBJECT (window->output_video_socket), "realize",
-      G_CALLBACK (call_window_socket_realized_cb), window);
-  gtk_widget_show (window->output_video_socket);
-
-  /* Preview video socket */
-  window->preview_video_socket = g_object_ref (gtk_socket_new ());
-  g_signal_connect (GTK_OBJECT (window->preview_video_socket), "realize",
-      G_CALLBACK (call_window_socket_realized_cb), window);
-  gtk_container_add (GTK_CONTAINER (window->preview_video_frame),
-      window->preview_video_socket);
-  gtk_widget_show (window->preview_video_socket);
-
-  g_signal_connect (G_OBJECT (window->call), "status-changed",
-      G_CALLBACK (call_window_status_changed_cb),
-      window);
-  g_signal_connect (G_OBJECT (window->call), "receiving-video",
-      G_CALLBACK (call_window_receiving_video_cb),
-      window);
-  g_signal_connect (G_OBJECT (window->call), "sending-video",
-      G_CALLBACK (call_window_sending_video_cb),
-      window);
-
-  window->is_drawing = FALSE;
-
-  g_object_get (G_OBJECT (window->call), "status", &status, NULL);
-
-  if (status == EMPATHY_TP_CALL_STATUS_READYING)
-    {
-      gtk_window_set_title (GTK_WINDOW (window->window), "Empathy Call");
-      gtk_label_set_text (GTK_LABEL (window->status_label), "Readying");
-    }
-
-  gtk_widget_show (window->window);
-
-  return window->window;
-}
-
diff --git a/libempathy-gtk/empathy-call-window.glade b/libempathy-gtk/empathy-call-window.glade
deleted file mode 100644 (file)
index 2eeea0d..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.1 on Wed Mar  5 15:38:49 2008 -->
-<glade-interface>
-  <widget class="GtkWindow" id="window">
-    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-    <child>
-      <widget class="GtkVBox" id="vbox1">
-        <property name="visible">True</property>
-        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-        <property name="border_width">10</property>
-        <property name="spacing">10</property>
-        <child>
-          <widget class="GtkHBox" id="hbox1">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <child>
-              <widget class="GtkLabel" id="status_label">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-              </widget>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkHSeparator" id="hseparator1">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkHBox" id="hbox2">
-            <property name="visible">True</property>
-            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-            <property name="spacing">10</property>
-            <child>
-              <widget class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <property name="label_xalign">0</property>
-                <child>
-                  <widget class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0</property>
-                    <child>
-                      <widget class="GtkHBox" id="hbox3">
-                        <property name="visible">True</property>
-                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                        <property name="homogeneous">True</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox4">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="extension_events">GDK_EXTENSION_EVENTS_CURSOR</property>
-                            <property name="resize_mode">GTK_RESIZE_QUEUE</property>
-                            <child>
-                              <widget class="GtkLabel" id="label2">
-                                <property name="visible">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label" translatable="yes">Input</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="padding">5</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkVScale" id="input_volume_scale">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="adjustment">100 0 100 1 0 0</property>
-                                <property name="inverted">True</property>
-                                <property name="draw_value">False</property>
-                              </widget>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkToggleButton" id="input_mute_button">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label" translatable="yes">Mute</property>
-                                <property name="response_id">0</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="padding">5</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </widget>
-                          <packing>
-                            <property name="padding">5</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <widget class="GtkVBox" id="vbox5">
-                            <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <child>
-                              <widget class="GtkLabel" id="label3">
-                                <property name="visible">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label" translatable="yes">Output</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="padding">5</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkVScale" id="output_volume_scale">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="adjustment">100 0 100 1 0 0</property>
-                                <property name="inverted">True</property>
-                                <property name="draw_value">False</property>
-                              </widget>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkToggleButton" id="output_mute_button">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">True</property>
-                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="label" translatable="yes">Mute</property>
-                                <property name="response_id">0</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="padding">5</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </widget>
-                          <packing>
-                            <property name="padding">5</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-                <child>
-                  <widget class="GtkLabel" id="label4">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Volume</property>
-                    <property name="use_markup">True</property>
-                  </widget>
-                  <packing>
-                    <property name="type">label_item</property>
-                  </packing>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkVBox" id="vbox2">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <child>
-                  <widget class="GtkAspectFrame" id="output_video_frame">
-                    <property name="width_request">352</property>
-                    <property name="height_request">288</property>
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label_xalign">0</property>
-                    <property name="ratio">1.2200000286102295</property>
-                    <property name="obey_child">False</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkVBox" id="vbox3">
-                <property name="visible">True</property>
-                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                <child>
-                  <widget class="GtkAspectFrame" id="preview_video_frame">
-                    <property name="width_request">176</property>
-                    <property name="height_request">144</property>
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label_xalign">0</property>
-                    <property name="ratio">1.2200000286102295</property>
-                    <property name="obey_child">False</property>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </widget>
-                </child>
-                <child>
-                  <widget class="GtkCheckButton" id="video_button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Send Video</property>
-                    <property name="response_id">0</property>
-                    <property name="active">True</property>
-                    <property name="draw_indicator">True</property>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="padding">10</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkHSeparator" id="hseparator2">
-                    <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="padding">5</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkButton" id="start_call_button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">Start Call</property>
-                    <property name="response_id">0</property>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="padding">10</property>
-                    <property name="pack_type">GTK_PACK_END</property>
-                    <property name="position">4</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkButton" id="end_call_button">
-                    <property name="visible">True</property>
-                    <property name="sensitive">False</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="label" translatable="yes">End Call</property>
-                    <property name="response_id">0</property>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="pack_type">GTK_PACK_END</property>
-                    <property name="position">3</property>
-                  </packing>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="padding">10</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/libempathy-gtk/empathy-call-window.h b/libempathy-gtk/empathy-call-window.h
deleted file mode 100644 (file)
index 7d65aae..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  Copyright (C) 2007 Elliot Fairweather
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2.1 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- *  Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
- */
-
-#ifndef __EMPATHY_CALL_WINDOW_H__
-#define __EMPATHY_CALL_WINDOW_H__
-
-#include <gtk/gtk.h>
-
-#include <libempathy/empathy-tp-call.h>
-
-G_BEGIN_DECLS
-
-GtkWidget *empathy_call_window_new (EmpathyTpCall *call);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_CALL_WINDOW_H__ */
index af523180dadc178fa24fe87bc5fac8ac9718d98a..7682bf3a1adfd39ed40177b4b8e15446da75b90c 100644 (file)
@@ -48,7 +48,6 @@
 #include "empathy-chat-view.h"
 #include "empathy-chat.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 #include "empathy-theme-manager.h"
 #include "empathy-ui-utils.h"
 #include "empathy-smiley-manager.h"
diff --git a/libempathy-gtk/empathy-chat-window.c b/libempathy-gtk/empathy-chat-window.c
deleted file mode 100644 (file)
index bbf66fb..0000000
+++ /dev/null
@@ -1,1876 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2003-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Mikael Hallendal <micke@imendio.com>
- *          Richard Hult <richard@imendio.com>
- *          Martyn Russell <martyn@imendio.com>
- *          Geert-Jan Van den Bogaerde <geertjan@gnome.org>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <gdk/gdkkeysyms.h>
-#include <glade/glade.h>
-#include <glib/gi18n.h>
-
-#include <libmissioncontrol/mission-control.h>
-
-#include <libempathy/empathy-contact-factory.h>
-#include <libempathy/empathy-log-manager.h>
-#include <libempathy/empathy-chatroom-manager.h>
-#include <libempathy/empathy-contact.h>
-#include <libempathy/empathy-debug.h>
-#include <libempathy/empathy-message.h>
-#include <libempathy/empathy-utils.h>
-
-#include "empathy-chat-window.h"
-#include "empathy-images.h"
-//#include "empathy-chat-invite.h"
-#include "empathy-contact-dialogs.h"
-#include "empathy-log-window.h"
-#include "empathy-new-chatroom-dialog.h"
-#include "empathy-conf.h"
-#include "empathy-preferences.h"
-#include "empathy-private-chat.h"
-#include "empathy-group-chat.h"
-//#include "empathy-sound.h"
-#include "empathy-ui-utils.h"
-#include "empathy-about-dialog.h"
-
-#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowPriv))
-
-#define DEBUG_DOMAIN "ChatWindow"
-
-struct _EmpathyChatWindowPriv {
-       EmpathyChatroomManager *chatroom_manager;
-       GList                 *chats;
-       GList                 *chats_new_msg;
-       GList                 *chats_composing;
-
-       EmpathyChat            *current_chat;
-
-       gboolean               page_added;
-       gboolean               dnd_same_window;
-
-       GtkWidget             *dialog;
-       GtkWidget             *notebook;
-
-       /* Menu items. */
-       GtkWidget             *menu_conv_clear;
-       GtkWidget             *menu_conv_insert_smiley;
-       GtkWidget             *menu_conv_call;
-       GtkWidget             *menu_conv_call_separator;
-       GtkWidget             *menu_conv_log;
-       GtkWidget             *menu_conv_separator;
-       GtkWidget             *menu_conv_add_contact;
-       GtkWidget             *menu_conv_info;
-       GtkWidget             *menu_conv_close;
-
-       GtkWidget             *menu_room;
-       GtkWidget             *menu_room_set_topic;
-       GtkWidget             *menu_room_join_new;
-       GtkWidget             *menu_room_invite;
-       GtkWidget             *menu_room_add;
-       GtkWidget             *menu_room_show_contacts;
-
-       GtkWidget             *menu_edit_cut;
-       GtkWidget             *menu_edit_copy;
-       GtkWidget             *menu_edit_paste;
-
-       GtkWidget             *menu_tabs_next;
-       GtkWidget             *menu_tabs_prev;
-       GtkWidget             *menu_tabs_left;
-       GtkWidget             *menu_tabs_right;
-       GtkWidget             *menu_tabs_detach;
-       
-       GtkWidget             *menu_help_contents;
-       GtkWidget             *menu_help_about;
-
-       guint                  save_geometry_id;
-};
-
-static void       empathy_chat_window_class_init         (EmpathyChatWindowClass *klass);
-static void       empathy_chat_window_init               (EmpathyChatWindow      *window);
-static void       empathy_chat_window_finalize           (GObject               *object);
-static void       chat_window_accel_cb                  (GtkAccelGroup         *accelgroup,
-                                                        GObject               *object,
-                                                        guint                  key,
-                                                        GdkModifierType        mod,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_close_clicked_cb          (GtkWidget             *button,
-                                                        EmpathyChat            *chat);
-static GtkWidget *chat_window_create_label              (EmpathyChatWindow      *window,
-                                                        EmpathyChat            *chat);
-static void       chat_window_update_status             (EmpathyChatWindow      *window,
-                                                        EmpathyChat            *chat);
-static void       chat_window_update_title              (EmpathyChatWindow      *window,
-                                                        EmpathyChat            *chat);
-static void       chat_window_update_menu               (EmpathyChatWindow      *window);
-static gboolean   chat_window_save_geometry_timeout_cb  (EmpathyChatWindow      *window);
-static gboolean   chat_window_configure_event_cb        (GtkWidget             *widget,
-                                                        GdkEventConfigure     *event,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_conv_activate_cb          (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_clear_activate_cb         (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_info_activate_cb          (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_add_contact_activate_cb   (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_call_activate_cb          (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_log_activate_cb           (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_show_contacts_toggled_cb  (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_edit_activate_cb          (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_insert_smiley_activate_cb (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_close_activate_cb         (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_room_set_topic_activate_cb(GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_room_join_new_activate_cb (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_room_invite_activate_cb   (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_room_add_activate_cb      (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_cut_activate_cb           (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_copy_activate_cb          (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_paste_activate_cb         (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_tabs_left_activate_cb     (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_tabs_right_activate_cb    (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_detach_activate_cb        (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_help_contents_cb          (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_help_about_cb             (GtkWidget             *menuitem,
-                                                        EmpathyChatWindow      *window);
-static gboolean   chat_window_delete_event_cb           (GtkWidget             *dialog,
-                                                        GdkEvent              *event,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_status_changed_cb         (EmpathyChat            *chat,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_update_tooltip            (EmpathyChatWindow      *window,
-                                                        EmpathyChat            *chat);
-static void       chat_window_name_changed_cb           (EmpathyChat            *chat,
-                                                        const gchar           *name,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_composing_cb              (EmpathyChat            *chat,
-                                                        gboolean               is_composing,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_new_message_cb            (EmpathyChat            *chat,
-                                                        EmpathyMessage         *message,
-                                                        gboolean               is_backlog,
-                                                        EmpathyChatWindow      *window);
-static GtkNotebook* chat_window_detach_hook             (GtkNotebook           *source,
-                                                        GtkWidget             *page,
-                                                        gint                   x,
-                                                        gint                   y,
-                                                        gpointer               user_data);
-static void       chat_window_page_switched_cb          (GtkNotebook           *notebook,
-                                                        GtkNotebookPage       *page,
-                                                        gint                   page_num,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_page_reordered_cb         (GtkNotebook           *notebook,
-                                                        GtkWidget             *widget,
-                                                        guint                  page_num,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_page_added_cb             (GtkNotebook           *notebook,
-                                                        GtkWidget             *child,
-                                                        guint                  page_num,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_page_removed_cb           (GtkNotebook           *notebook,
-                                                        GtkWidget             *child,
-                                                        guint                  page_num,
-                                                        EmpathyChatWindow      *window);
-static gboolean   chat_window_focus_in_event_cb         (GtkWidget             *widget,
-                                                        GdkEvent              *event,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_drag_data_received        (GtkWidget             *widget,
-                                                        GdkDragContext        *context,
-                                                        int                    x,
-                                                        int                    y,
-                                                        GtkSelectionData      *selection,
-                                                        guint                  info,
-                                                        guint                  time,
-                                                        EmpathyChatWindow      *window);
-static void       chat_window_set_urgency_hint          (EmpathyChatWindow      *window,
-                                                        gboolean               urgent);
-
-
-static GList *chat_windows = NULL;
-
-static const guint tab_accel_keys[] = {
-       GDK_1, GDK_2, GDK_3, GDK_4, GDK_5,
-       GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
-};
-
-typedef enum {
-       DND_DRAG_TYPE_CONTACT_ID,
-       DND_DRAG_TYPE_TAB
-} DndDragType;
-
-static const GtkTargetEntry drag_types_dest[] = {
-       { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
-       { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, DND_DRAG_TYPE_TAB },
-};
-
-G_DEFINE_TYPE (EmpathyChatWindow, empathy_chat_window, G_TYPE_OBJECT);
-
-static void
-empathy_chat_window_class_init (EmpathyChatWindowClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = empathy_chat_window_finalize;
-
-       g_type_class_add_private (object_class, sizeof (EmpathyChatWindowPriv));
-
-       /* Set up a style for the close button with no focus padding. */
-       gtk_rc_parse_string (
-               "style \"empathy-close-button-style\"\n"
-               "{\n"
-               "  GtkWidget::focus-padding = 0\n"
-               "  xthickness = 0\n"
-               "  ythickness = 0\n"
-               "}\n"
-               "widget \"*.empathy-close-button\" style \"empathy-close-button-style\"");
-
-       gtk_notebook_set_window_creation_hook (chat_window_detach_hook, NULL, NULL);
-}
-
-static void
-empathy_chat_window_init (EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       GladeXML             *glade;
-       GtkAccelGroup        *accel_group;
-       GtkWidget            *image;
-       GClosure             *closure;
-       GtkWidget            *menu_conv;
-       GtkWidget            *menu;
-       gint                  i;
-       GtkWidget            *chat_vbox;
-
-       priv = GET_PRIV (window);
-
-       glade = empathy_glade_get_file ("empathy-chat.glade",
-                                      "chat_window",
-                                      NULL,
-                                      "chat_window", &priv->dialog,
-                                      "chat_vbox", &chat_vbox,
-                                      "menu_conv", &menu_conv,
-                                      "menu_conv_clear", &priv->menu_conv_clear,
-                                      "menu_conv_insert_smiley", &priv->menu_conv_insert_smiley,
-                                      "menu_conv_call", &priv->menu_conv_call,
-                                      "menu_conv_call_separator", &priv->menu_conv_call_separator,
-                                      "menu_conv_log", &priv->menu_conv_log,
-                                      "menu_conv_separator", &priv->menu_conv_separator,
-                                      "menu_conv_add_contact", &priv->menu_conv_add_contact,
-                                      "menu_conv_info", &priv->menu_conv_info,
-                                      "menu_conv_close", &priv->menu_conv_close,
-                                      "menu_room", &priv->menu_room,
-                                      "menu_room_set_topic", &priv->menu_room_set_topic,
-                                      "menu_room_join_new", &priv->menu_room_join_new,
-                                      "menu_room_invite", &priv->menu_room_invite,
-                                      "menu_room_add", &priv->menu_room_add,
-                                      "menu_room_show_contacts", &priv->menu_room_show_contacts,
-                                      "menu_edit_cut", &priv->menu_edit_cut,
-                                      "menu_edit_copy", &priv->menu_edit_copy,
-                                      "menu_edit_paste", &priv->menu_edit_paste,
-                                      "menu_tabs_next", &priv->menu_tabs_next,
-                                      "menu_tabs_prev", &priv->menu_tabs_prev,
-                                      "menu_tabs_left", &priv->menu_tabs_left,
-                                      "menu_tabs_right", &priv->menu_tabs_right,
-                                      "menu_tabs_detach", &priv->menu_tabs_detach,
-                                      "menu_help_contents", &priv->menu_help_contents,
-                                      "menu_help_about", &priv->menu_help_about,
-                                      NULL);
-
-       empathy_glade_connect (glade,
-                             window,
-                             "chat_window", "configure-event", chat_window_configure_event_cb,
-                             "menu_conv", "activate", chat_window_conv_activate_cb,
-                             "menu_conv_clear", "activate", chat_window_clear_activate_cb,
-                             "menu_conv_call", "activate", chat_window_call_activate_cb,
-                             "menu_conv_log", "activate", chat_window_log_activate_cb,
-                             "menu_conv_add_contact", "activate", chat_window_add_contact_activate_cb,
-                             "menu_conv_info", "activate", chat_window_info_activate_cb,
-                             "menu_conv_close", "activate", chat_window_close_activate_cb,
-                             "menu_room_set_topic", "activate", chat_window_room_set_topic_activate_cb,
-                             "menu_room_join_new", "activate", chat_window_room_join_new_activate_cb,
-                             "menu_room_invite", "activate", chat_window_room_invite_activate_cb,
-                             "menu_room_add", "activate", chat_window_room_add_activate_cb,
-                             "menu_edit", "activate", chat_window_edit_activate_cb,
-                             "menu_edit_cut", "activate", chat_window_cut_activate_cb,
-                             "menu_edit_copy", "activate", chat_window_copy_activate_cb,
-                             "menu_edit_paste", "activate", chat_window_paste_activate_cb,
-                             "menu_tabs_left", "activate", chat_window_tabs_left_activate_cb,
-                             "menu_tabs_right", "activate", chat_window_tabs_right_activate_cb,
-                             "menu_tabs_detach", "activate", chat_window_detach_activate_cb,
-                             "menu_help_contents", "activate", chat_window_help_contents_cb,
-                             "menu_help_about", "activate", chat_window_help_about_cb,
-                             NULL);
-
-       g_object_unref (glade);
-
-       /* Set up chatroom manager */
-       priv->chatroom_manager = empathy_chatroom_manager_new ();
-       g_signal_connect_swapped (priv->chatroom_manager, "chatroom-added",
-                                 G_CALLBACK (chat_window_update_menu),
-                                 window);
-       g_signal_connect_swapped (priv->chatroom_manager, "chatroom-removed",
-                                 G_CALLBACK (chat_window_update_menu),
-                                 window);
-
-       priv->notebook = gtk_notebook_new ();
-       gtk_notebook_set_group (GTK_NOTEBOOK (priv->notebook), "EmpathyChatWindow"); 
-       gtk_box_pack_start (GTK_BOX (chat_vbox), priv->notebook, TRUE, TRUE, 0);
-       gtk_widget_show (priv->notebook);
-
-       /* Set up accels */
-       accel_group = gtk_accel_group_new ();
-       gtk_window_add_accel_group (GTK_WINDOW (priv->dialog), accel_group);
-
-       for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
-               closure =  g_cclosure_new (G_CALLBACK (chat_window_accel_cb),
-                                          window,
-                                          NULL);
-               gtk_accel_group_connect (accel_group,
-                                        tab_accel_keys[i],
-                                        GDK_MOD1_MASK,
-                                        0,
-                                        closure);
-       }
-
-       g_object_unref (accel_group);
-
-       /* Set the contact information menu item image to the Empathy
-        * stock image
-        */
-       image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (priv->menu_conv_info));
-       gtk_image_set_from_icon_name (GTK_IMAGE (image),
-                                     EMPATHY_IMAGE_CONTACT_INFORMATION,
-                                     GTK_ICON_SIZE_MENU);
-
-       /* Set up smiley menu */
-       menu = empathy_chat_view_get_smiley_menu (
-               G_CALLBACK (chat_window_insert_smiley_activate_cb),
-               window);
-       gtk_menu_item_set_submenu (GTK_MENU_ITEM (priv->menu_conv_insert_smiley), menu);
-
-       /* Set up signals we can't do with glade since we may need to
-        * block/unblock them at some later stage.
-        */
-
-       g_signal_connect (priv->dialog,
-                         "delete_event",
-                         G_CALLBACK (chat_window_delete_event_cb),
-                         window);
-
-       g_signal_connect (priv->menu_room_show_contacts,
-                         "toggled",
-                         G_CALLBACK (chat_window_show_contacts_toggled_cb),
-                         window);
-
-       g_signal_connect_swapped (priv->menu_tabs_prev,
-                                 "activate",
-                                 G_CALLBACK (gtk_notebook_prev_page),
-                                 priv->notebook);
-       g_signal_connect_swapped (priv->menu_tabs_next,
-                                 "activate",
-                                 G_CALLBACK (gtk_notebook_next_page),
-                                 priv->notebook);
-
-       g_signal_connect (priv->dialog,
-                         "focus_in_event",
-                         G_CALLBACK (chat_window_focus_in_event_cb),
-                         window);
-       g_signal_connect_after (priv->notebook,
-                               "switch_page",
-                               G_CALLBACK (chat_window_page_switched_cb),
-                               window);
-       g_signal_connect (priv->notebook,
-                         "page_reordered",
-                         G_CALLBACK (chat_window_page_reordered_cb),
-                         window);
-       g_signal_connect (priv->notebook,
-                         "page_added",
-                         G_CALLBACK (chat_window_page_added_cb),
-                         window);
-       g_signal_connect (priv->notebook,
-                         "page_removed",
-                         G_CALLBACK (chat_window_page_removed_cb),
-                         window);
-
-       /* Set up drag and drop */
-       gtk_drag_dest_set (GTK_WIDGET (priv->notebook),
-                          GTK_DEST_DEFAULT_ALL,
-                          drag_types_dest,
-                          G_N_ELEMENTS (drag_types_dest),
-                          GDK_ACTION_MOVE);
-
-       g_signal_connect (priv->notebook,
-                         "drag-data-received",
-                         G_CALLBACK (chat_window_drag_data_received),
-                         window);
-
-       chat_windows = g_list_prepend (chat_windows, window);
-
-       /* Set up private details */
-       priv->chats = NULL;
-       priv->chats_new_msg = NULL;
-       priv->chats_composing = NULL;
-       priv->current_chat = NULL;
-}
-
-/* Returns the window to open a new tab in if there is only one window
- * visble, otherwise, returns NULL indicating that a new window should
- * be added.
- */
-EmpathyChatWindow *
-empathy_chat_window_get_default (void)
-{
-       GList    *l;
-       gboolean  separate_windows = TRUE;
-
-       empathy_conf_get_bool (empathy_conf_get (),
-                             EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS,
-                             &separate_windows);
-
-       if (separate_windows) {
-               /* Always create a new window */
-               return NULL;
-       }
-
-       for (l = chat_windows; l; l = l->next) {
-               EmpathyChatWindow *chat_window;
-               GtkWidget         *dialog;
-
-               chat_window = l->data;
-
-               dialog = empathy_chat_window_get_dialog (chat_window);
-               if (empathy_window_get_is_visible (GTK_WINDOW (GTK_WINDOW (dialog)))) {
-                       /* Found a visible window on this desktop */
-                       return chat_window;
-               }
-       }
-
-       return NULL;
-}
-
-static void
-empathy_chat_window_finalize (GObject *object)
-{
-       EmpathyChatWindow     *window;
-       EmpathyChatWindowPriv *priv;
-
-       window = EMPATHY_CHAT_WINDOW (object);
-       priv = GET_PRIV (window);
-
-       empathy_debug (DEBUG_DOMAIN, "Finalized: %p", object);
-
-       if (priv->save_geometry_id != 0) {
-               g_source_remove (priv->save_geometry_id);
-       }
-
-       chat_windows = g_list_remove (chat_windows, window);
-       gtk_widget_destroy (priv->dialog);
-
-       g_signal_handlers_disconnect_by_func (priv->chatroom_manager,
-                                             chat_window_update_menu,
-                                             window);
-       g_object_unref (priv->chatroom_manager);
-
-       G_OBJECT_CLASS (empathy_chat_window_parent_class)->finalize (object);
-}
-
-static void
-chat_window_accel_cb (GtkAccelGroup    *accelgroup,
-                     GObject          *object,
-                     guint             key,
-                     GdkModifierType   mod,
-                     EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       gint                  num = -1;
-       gint                  i;
-
-       priv = GET_PRIV (window);
-
-       for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
-               if (tab_accel_keys[i] == key) {
-                       num = i;
-                       break;
-               }
-       }
-
-       if (num != -1) {
-               gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), num);
-       }
-}
-
-static void
-chat_window_close_clicked_cb (GtkWidget  *button,
-                             EmpathyChat *chat)
-{
-       EmpathyChatWindow *window;
-
-       window = empathy_chat_get_window (chat);
-       empathy_chat_window_remove_chat (window, chat);
-}
-
-static void
-chat_window_close_button_style_set_cb (GtkWidget *button,
-                                      GtkStyle  *previous_style,
-                                      gpointer   user_data)
-{
-       gint h, w;
-
-       gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
-                                          GTK_ICON_SIZE_MENU, &w, &h);
-
-       gtk_widget_set_size_request (button, w, h);
-}
-
-static GtkWidget *
-chat_window_create_label (EmpathyChatWindow *window,
-                         EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       GtkWidget            *hbox;
-       GtkWidget            *name_label;
-       GtkWidget            *status_image;
-       GtkWidget            *close_button;
-       GtkWidget            *close_image;
-       GtkWidget            *event_box;
-       GtkWidget            *event_box_hbox;
-       PangoAttrList        *attr_list;
-       PangoAttribute       *attr;
-
-       priv = GET_PRIV (window);
-
-       /* The spacing between the button and the label. */
-       hbox = gtk_hbox_new (FALSE, 0);
-
-       event_box = gtk_event_box_new ();
-       gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
-
-       name_label = gtk_label_new (empathy_chat_get_name (chat));
-       gtk_label_set_ellipsize (GTK_LABEL (name_label), PANGO_ELLIPSIZE_END);
-
-       attr_list = pango_attr_list_new ();
-       attr = pango_attr_scale_new (1/1.2);
-       attr->start_index = 0;
-       attr->end_index = -1;
-       pango_attr_list_insert (attr_list, attr);
-       gtk_label_set_attributes (GTK_LABEL (name_label), attr_list);
-       pango_attr_list_unref (attr_list);
-
-       gtk_misc_set_padding (GTK_MISC (name_label), 2, 0);
-       gtk_misc_set_alignment (GTK_MISC (name_label), 0.0, 0.5);
-       g_object_set_data (G_OBJECT (chat), "chat-window-tab-label", name_label);
-
-       status_image = gtk_image_new ();
-
-       /* Spacing between the icon and label. */
-       event_box_hbox = gtk_hbox_new (FALSE, 0);
-
-       gtk_box_pack_start (GTK_BOX (event_box_hbox), status_image, FALSE, FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (event_box_hbox), name_label, TRUE, TRUE, 0);
-
-       g_object_set_data (G_OBJECT (chat), "chat-window-tab-image", status_image);
-       g_object_set_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget", event_box);
-
-       close_button = gtk_button_new ();
-       gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
-
-       /* We don't want focus/keynav for the button to avoid clutter, and
-        * Ctrl-W works anyway.
-        */
-       GTK_WIDGET_UNSET_FLAGS (close_button, GTK_CAN_FOCUS);
-       GTK_WIDGET_UNSET_FLAGS (close_button, GTK_CAN_DEFAULT);
-
-       /* Set the name to make the special rc style match. */
-       gtk_widget_set_name (close_button, "empathy-close-button");
-
-       close_image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
-
-       gtk_container_add (GTK_CONTAINER (close_button), close_image);
-
-       gtk_container_add (GTK_CONTAINER (event_box), event_box_hbox);
-       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, TRUE, 0);
-       gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
-
-       /* React to theme changes and also used to setup the initial size
-        * correctly.
-        */
-       g_signal_connect (close_button,
-                         "style-set",
-                         G_CALLBACK (chat_window_close_button_style_set_cb),
-                         chat);
-
-       g_signal_connect (close_button,
-                         "clicked",
-                         G_CALLBACK (chat_window_close_clicked_cb),
-                         chat);
-
-       /* Set up tooltip */
-       chat_window_update_tooltip (window, chat);
-
-       gtk_widget_show_all (hbox);
-
-       return hbox;
-}
-
-static void
-chat_window_update_status (EmpathyChatWindow *window,
-                          EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       GtkImage             *image;
-       const gchar          *icon_name = NULL;
-
-       priv = GET_PRIV (window);
-
-       if (g_list_find (priv->chats_new_msg, chat)) {
-               icon_name = EMPATHY_IMAGE_MESSAGE;
-       }
-       else if (g_list_find (priv->chats_composing, chat)) {
-               icon_name = EMPATHY_IMAGE_TYPING;
-       }
-       else {
-               icon_name = empathy_chat_get_status_icon_name (chat);
-       }
-       image = g_object_get_data (G_OBJECT (chat), "chat-window-tab-image");
-       gtk_image_set_from_icon_name (image, icon_name, GTK_ICON_SIZE_MENU);
-
-       chat_window_update_title (window, chat);
-       chat_window_update_tooltip (window, chat);
-}
-
-static void
-chat_window_update_title (EmpathyChatWindow *window,
-                         EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       gint                   n_chats;
-       
-       priv = GET_PRIV (window);
-       
-       n_chats = g_list_length (priv->chats);
-       if (n_chats == 1) {
-               gtk_window_set_title (GTK_WINDOW (priv->dialog),
-                                     empathy_chat_get_name (priv->current_chat));
-       } else {
-               gchar *title;
-
-               title = g_strdup_printf (_("Conversations (%d)"), n_chats);
-               gtk_window_set_title (GTK_WINDOW (priv->dialog), title);
-               g_free (title);
-       }
-
-       if (priv->chats_new_msg) {
-               gtk_window_set_icon_name (GTK_WINDOW (priv->dialog),
-                                         EMPATHY_IMAGE_MESSAGE);
-       } else {
-               gtk_window_set_icon_name (GTK_WINDOW (priv->dialog), NULL);
-       }
-}
-
-static void
-chat_window_update_menu (EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       gboolean              first_page;
-       gboolean              last_page;
-       gboolean              is_connected;
-       gint                  num_pages;
-       gint                  page_num;
-
-       priv = GET_PRIV (window);
-
-       /* Notebook pages */
-       page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
-       num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
-       first_page = (page_num == 0);
-       last_page = (page_num == (num_pages - 1));
-
-       gtk_widget_set_sensitive (priv->menu_tabs_next, !last_page);
-       gtk_widget_set_sensitive (priv->menu_tabs_prev, !first_page);
-       gtk_widget_set_sensitive (priv->menu_tabs_detach, num_pages > 1);
-       gtk_widget_set_sensitive (priv->menu_tabs_left, !first_page);
-       gtk_widget_set_sensitive (priv->menu_tabs_right, !last_page);
-
-       is_connected = empathy_chat_is_connected (priv->current_chat);
-
-       if (empathy_chat_is_group_chat (priv->current_chat)) {
-               EmpathyGroupChat *group_chat;
-               EmpathyChatroom  *chatroom;
-               gboolean         show_contacts;
-
-               group_chat = EMPATHY_GROUP_CHAT (priv->current_chat);
-
-               /* Show / Hide widgets */
-               gtk_widget_show (priv->menu_room);
-
-               gtk_widget_hide (priv->menu_conv_add_contact);
-               gtk_widget_hide (priv->menu_conv_info);
-               gtk_widget_hide (priv->menu_conv_separator);
-
-               /* Can we add this room to our favourites and are we
-                * connected to the room?
-                */
-               chatroom = empathy_chatroom_manager_find (priv->chatroom_manager,
-                                                         empathy_chat_get_account (priv->current_chat),
-                                                         empathy_chat_get_id (priv->current_chat));
-
-               gtk_widget_set_sensitive (priv->menu_room_add, chatroom == NULL);
-               gtk_widget_set_sensitive (priv->menu_conv_insert_smiley, is_connected);
-               gtk_widget_set_sensitive (priv->menu_room_join_new, is_connected);
-               gtk_widget_set_sensitive (priv->menu_room_invite, is_connected);
-
-               /* We need to block the signal here because all we are
-                * really trying to do is check or uncheck the menu
-                * item. If we don't do this we get funny behaviour
-                * with 2 or more group chat windows where showing
-                * contacts doesn't do anything.
-                */
-               show_contacts = empathy_group_chat_get_show_contacts (group_chat);
-
-               g_signal_handlers_block_by_func (priv->menu_room_show_contacts,
-                                                chat_window_show_contacts_toggled_cb,
-                                                window);
-
-               g_object_set (priv->menu_room_show_contacts,
-                             "active", show_contacts,
-                             NULL);
-
-               g_signal_handlers_unblock_by_func (priv->menu_room_show_contacts,
-                                                  chat_window_show_contacts_toggled_cb,
-                                                  window);
-       } else {
-               EmpathyPrivateChat *chat;
-               EmpathyContact     *contact;
-               McPresence          presence;
-
-               chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
-
-               /* Show / Hide widgets */
-               gtk_widget_hide (priv->menu_room);
-
-               /* Unset presence means this contact refuses to send us his
-                * presence. By adding the contact we ask the contact to accept
-                * to send his presence. */
-               contact = empathy_private_chat_get_contact (chat);
-               presence = empathy_contact_get_presence (contact);
-               if (presence == MC_PRESENCE_UNSET) {
-                       gtk_widget_show (priv->menu_conv_add_contact);
-               } else {
-                       gtk_widget_hide (priv->menu_conv_add_contact);
-               }
-
-               gtk_widget_show (priv->menu_conv_separator);
-               gtk_widget_show (priv->menu_conv_info);
-
-               /* Are we connected? */
-               gtk_widget_set_sensitive (priv->menu_conv_insert_smiley, is_connected);
-               gtk_widget_set_sensitive (priv->menu_conv_add_contact, is_connected);
-               gtk_widget_set_sensitive (priv->menu_conv_info, is_connected);
-       }
-}
-
-static void
-chat_window_insert_smiley_activate_cb (GtkWidget         *menuitem,
-                                      EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChat           *chat;
-       GtkTextBuffer        *buffer;
-       GtkTextIter           iter;
-       const gchar          *smiley;
-
-       priv = GET_PRIV (window);
-
-       chat = priv->current_chat;
-
-       smiley = g_object_get_data (G_OBJECT (menuitem), "smiley_text");
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
-       gtk_text_buffer_get_end_iter (buffer, &iter);
-       gtk_text_buffer_insert (buffer, &iter,
-                               smiley, -1);
-}
-
-static void
-chat_window_clear_activate_cb (GtkWidget        *menuitem,
-                              EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       empathy_chat_clear (priv->current_chat);
-}
-
-static void
-chat_window_add_contact_activate_cb (GtkWidget        *menuitem,
-                                    EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       //EmpathyContact        *contact;
-
-       priv = GET_PRIV (window);
-
-       //contact = empathy_chat_get_contact (priv->current_chat);
-
-       // FIXME: empathy_add_contact_dialog_show (NULL, contact);
-}
-
-static void
-chat_window_call_activate_cb (GtkWidget         *menuitem,
-                             EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       if (!empathy_chat_is_group_chat (priv->current_chat)) {
-               EmpathyPrivateChat *chat;
-               EmpathyContact     *contact;
-
-               chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
-               contact = empathy_private_chat_get_contact (chat);
-
-               empathy_call_with_contact (contact);
-       }
-}
-
-static void
-chat_window_log_activate_cb (GtkWidget        *menuitem,
-                            EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       empathy_log_window_show (empathy_chat_get_account (priv->current_chat),
-                                empathy_chat_get_id (priv->current_chat),
-                                empathy_chat_is_group_chat (priv->current_chat),
-                                GTK_WINDOW (priv->dialog));
-}
-
-static void
-chat_window_info_activate_cb (GtkWidget        *menuitem,
-                             EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyContact        *contact;
-
-       priv = GET_PRIV (window);
-
-       contact = empathy_private_chat_get_contact (EMPATHY_PRIVATE_CHAT (priv->current_chat));
-
-       empathy_contact_information_dialog_show (contact,
-                                                GTK_WINDOW (priv->dialog),
-                                                FALSE, FALSE);
-}
-
-static gboolean
-chat_window_save_geometry_timeout_cb (EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       gint                  x, y, w, h;
-
-       priv = GET_PRIV (window);
-
-       gtk_window_get_size (GTK_WINDOW (priv->dialog), &w, &h);
-       gtk_window_get_position (GTK_WINDOW (priv->dialog), &x, &y);
-
-       empathy_chat_save_geometry (priv->current_chat, x, y, w, h);
-
-       priv->save_geometry_id = 0;
-
-       return FALSE;
-}
-
-static gboolean
-chat_window_configure_event_cb (GtkWidget         *widget,
-                               GdkEventConfigure *event,
-                               EmpathyChatWindow  *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       if (priv->save_geometry_id != 0) {
-               g_source_remove (priv->save_geometry_id);
-       }
-
-       priv->save_geometry_id =
-               g_timeout_add_seconds (1,
-                                      (GSourceFunc) chat_window_save_geometry_timeout_cb,
-                                      window);
-
-       return FALSE;
-}
-
-static void
-chat_window_conv_activate_cb (GtkWidget         *menuitem,
-                             EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyLogManager     *manager;
-       gboolean              log_exists = FALSE;
-       gboolean              can_voip = FALSE;
-
-       priv = GET_PRIV (window);
-
-       manager = empathy_log_manager_new ();
-       log_exists = empathy_log_manager_exists (manager,
-                                                empathy_chat_get_account (priv->current_chat),
-                                                empathy_chat_get_id (priv->current_chat),
-                                                empathy_chat_is_group_chat (priv->current_chat));
-       g_object_unref (manager);
-
-       if (!empathy_chat_is_group_chat (priv->current_chat)) {
-               EmpathyPrivateChat *chat;
-               EmpathyContact     *contact;
-
-               chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
-               contact = empathy_private_chat_get_contact (chat);
-               can_voip = empathy_contact_can_voip (contact);
-       }
-
-       gtk_widget_set_sensitive (priv->menu_conv_log, log_exists);
-#ifdef HAVE_VOIP
-       gtk_widget_set_sensitive (priv->menu_conv_call, can_voip);
-#else 
-       g_object_set (priv->menu_conv_call, "visible", FALSE, NULL);
-       g_object_set (priv->menu_conv_call_separator, "visible", FALSE, NULL);
-#endif
-}
-
-static void
-chat_window_show_contacts_toggled_cb (GtkWidget        *menuitem,
-                                     EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       gboolean              show;
-
-       priv = GET_PRIV (window);
-
-       g_return_if_fail (priv->current_chat != NULL);
-
-       show = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (priv->menu_room_show_contacts));
-       empathy_group_chat_set_show_contacts (EMPATHY_GROUP_CHAT (priv->current_chat), show);
-}
-
-static void
-chat_window_close_activate_cb (GtkWidget        *menuitem,
-                              EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       g_return_if_fail (priv->current_chat != NULL);
-
-       empathy_chat_window_remove_chat (window, priv->current_chat);
-}
-
-static void
-chat_window_room_set_topic_activate_cb (GtkWidget        *menuitem,
-                                       EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       
-       priv = GET_PRIV (window);
-
-       if (empathy_chat_is_group_chat (priv->current_chat)) {
-               EmpathyGroupChat *group_chat;
-
-               group_chat = EMPATHY_GROUP_CHAT (priv->current_chat);
-               empathy_group_chat_set_topic (group_chat);
-       }
-}
-
-static void
-chat_window_room_join_new_activate_cb (GtkWidget        *menuitem,
-                                      EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       empathy_new_chatroom_dialog_show (GTK_WINDOW (priv->dialog));
-}
-
-static void
-chat_window_room_invite_activate_cb (GtkWidget        *menuitem,
-                                    EmpathyChatWindow *window)
-{
-/* FIXME:
-       EmpathyChatWindowPriv *priv;
-       EmpathyContact        *own_contact;
-       EmpathyChatroomId      id = 0;
-
-       priv = GET_PRIV (window);
-       own_contact = empathy_chat_get_own_contact (priv->current_chat);
-
-       if (empathy_chat_is_group_chat (priv->current_chat)) {
-               EmpathyGroupChat *group_chat;
-
-               group_chat = EMPATHY_GROUP_CHAT (priv->current_chat);
-               id = empathy_group_chat_get_chatroom_id (group_chat);
-       }
-
-       empathy_chat_invite_dialog_show (own_contact, id);
-*/
-}
-
-static void
-chat_window_room_add_activate_cb (GtkWidget        *menuitem,
-                                 EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv  *priv;
-       EmpathyChatroomManager *manager;
-       EmpathyChatroom        *chatroom;
-
-       priv = GET_PRIV (window);
-
-       g_return_if_fail (priv->current_chat != NULL);
-
-       if (!empathy_chat_is_group_chat (priv->current_chat)) {
-               return;
-       }
-
-       chatroom = empathy_chatroom_new_full (empathy_chat_get_account (priv->current_chat),
-                                             empathy_chat_get_id (priv->current_chat),
-                                             empathy_chat_get_name (priv->current_chat),
-                                             FALSE);
-
-       manager = empathy_chatroom_manager_new ();
-       empathy_chatroom_manager_add (manager, chatroom);
-       chat_window_update_menu (window);
-
-       g_object_unref (chatroom);
-       g_object_unref (manager);
-}
-
-static void
-chat_window_edit_activate_cb (GtkWidget        *menuitem,
-                             EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       GtkClipboard         *clipboard;
-       GtkTextBuffer        *buffer;
-       gboolean              text_available;
-
-       priv = GET_PRIV (window);
-
-       g_return_if_fail (priv->current_chat != NULL);
-
-       if (!empathy_chat_is_connected (priv->current_chat)) {
-               gtk_widget_set_sensitive (priv->menu_edit_copy, FALSE);
-               gtk_widget_set_sensitive (priv->menu_edit_cut, FALSE);
-               gtk_widget_set_sensitive (priv->menu_edit_paste, FALSE);
-               return;
-       }
-
-       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->current_chat->input_text_view));
-       if (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL)) {
-               gtk_widget_set_sensitive (priv->menu_edit_copy, TRUE);
-               gtk_widget_set_sensitive (priv->menu_edit_cut, TRUE);
-       } else {
-               gboolean selection;
-
-               selection = empathy_chat_view_get_selection_bounds (priv->current_chat->view, 
-                                                                  NULL, NULL);
-
-               gtk_widget_set_sensitive (priv->menu_edit_cut, FALSE);
-               gtk_widget_set_sensitive (priv->menu_edit_copy, selection);
-       }
-
-       clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
-       text_available = gtk_clipboard_wait_is_text_available (clipboard);
-       gtk_widget_set_sensitive (priv->menu_edit_paste, text_available);
-}
-
-static void
-chat_window_cut_activate_cb (GtkWidget        *menuitem,
-                            EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
-
-       priv = GET_PRIV (window);
-
-       empathy_chat_cut (priv->current_chat);
-}
-
-static void
-chat_window_copy_activate_cb (GtkWidget        *menuitem,
-                             EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
-
-       priv = GET_PRIV (window);
-
-       empathy_chat_copy (priv->current_chat);
-}
-
-static void
-chat_window_paste_activate_cb (GtkWidget        *menuitem,
-                              EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
-
-       priv = GET_PRIV (window);
-
-       empathy_chat_paste (priv->current_chat);
-}
-
-static void
-chat_window_tabs_left_activate_cb (GtkWidget        *menuitem,
-                                  EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChat           *chat;
-       gint                  index;
-
-       priv = GET_PRIV (window);
-
-       chat = priv->current_chat;
-       index = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
-       if (index <= 0) {
-               return;
-       }
-
-       gtk_notebook_reorder_child (GTK_NOTEBOOK (priv->notebook),
-                                   empathy_chat_get_widget (chat),
-                                   index - 1);
-
-       chat_window_update_menu (window);
-       chat_window_update_status (window, chat);
-}
-
-static void
-chat_window_tabs_right_activate_cb (GtkWidget        *menuitem,
-                                   EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChat           *chat;
-       gint                  index;
-
-       priv = GET_PRIV (window);
-
-       chat = priv->current_chat;
-       index = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
-
-       gtk_notebook_reorder_child (GTK_NOTEBOOK (priv->notebook),
-                                   empathy_chat_get_widget (chat),
-                                   index + 1);
-
-       chat_window_update_menu (window);
-       chat_window_update_status (window, chat);
-}
-
-static void
-chat_window_detach_activate_cb (GtkWidget        *menuitem,
-                               EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChatWindow     *new_window;
-       EmpathyChat           *chat;
-
-       priv = GET_PRIV (window);
-
-       chat = priv->current_chat;
-       new_window = empathy_chat_window_new ();
-
-       empathy_chat_window_move_chat (window, new_window, chat);
-
-       priv = GET_PRIV (new_window);
-       gtk_widget_show (priv->dialog);
-}
-
-static void
-chat_window_help_contents_cb (GtkWidget         *menuitem,
-                             EmpathyChatWindow *window)
-{
-       //empathy_help_show ();
-}
-
-static void
-chat_window_help_about_cb (GtkWidget         *menuitem,
-                          EmpathyChatWindow *window)
-{
-       empathy_about_dialog_new (GTK_WINDOW (window));
-}
-
-static gboolean
-chat_window_delete_event_cb (GtkWidget        *dialog,
-                            GdkEvent         *event,
-                            EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       GList                *list;
-       GList                *l;
-
-       priv = GET_PRIV (window);
-
-       empathy_debug (DEBUG_DOMAIN, "Delete event received");
-
-       list = g_list_copy (priv->chats);
-
-       for (l = list; l; l = l->next) {
-               empathy_chat_window_remove_chat (window, l->data);
-       }
-
-       g_list_free (list);
-
-       return TRUE;
-}
-
-static void
-chat_window_status_changed_cb (EmpathyChat       *chat,
-                              EmpathyChatWindow *window)
-{
-       chat_window_update_menu (window);
-       chat_window_update_status (window, chat);
-}
-
-static void
-chat_window_update_tooltip (EmpathyChatWindow *window,
-                           EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       GtkWidget            *widget;
-       gchar                *current_tooltip;
-       gchar                *str;
-
-       priv = GET_PRIV (window);
-
-       current_tooltip = empathy_chat_get_tooltip (chat);
-
-       if (g_list_find (priv->chats_composing, chat)) {
-               str = g_strconcat (current_tooltip, "\n", _("Typing a message."), NULL);
-               g_free (current_tooltip);
-       } else {
-               str = current_tooltip;
-       }
-
-       widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget");
-       gtk_widget_set_tooltip_text (widget, str);
-
-       g_free (str);
-}
-
-static void
-chat_window_name_changed_cb (EmpathyChat       *chat,
-                            const gchar      *name,
-                            EmpathyChatWindow *window)
-{
-       GtkLabel *label;
-
-       label = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label");
-
-       gtk_label_set_text (label, name);
-}
-
-static void
-chat_window_composing_cb (EmpathyChat       *chat,
-                         gboolean          is_composing,
-                         EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       if (is_composing && !g_list_find (priv->chats_composing, chat)) {
-               priv->chats_composing = g_list_prepend (priv->chats_composing, chat);
-       } else {
-               priv->chats_composing = g_list_remove (priv->chats_composing, chat);
-       }
-
-       chat_window_update_status (window, chat);
-}
-
-static void
-chat_window_new_message_cb (EmpathyChat       *chat,
-                           EmpathyMessage    *message,
-                           gboolean          is_backlog,
-                           EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       gboolean              has_focus;
-       gboolean              needs_urgency;
-
-       priv = GET_PRIV (window);
-
-       has_focus = empathy_chat_window_has_focus (window);
-       
-       if (has_focus && priv->current_chat == chat) {
-               empathy_debug (DEBUG_DOMAIN, "New message, we have focus");
-               return;
-       }
-       
-       empathy_debug (DEBUG_DOMAIN, "New message, no focus");
-
-       needs_urgency = FALSE;
-       if (empathy_chat_is_group_chat (chat)) {                
-               if (!is_backlog && 
-                   empathy_chat_should_highlight_nick (message)) {
-                       empathy_debug (DEBUG_DOMAIN, "Highlight this nick");
-                       needs_urgency = TRUE;
-               }
-       } else {
-               needs_urgency = TRUE;
-       }
-
-       if (needs_urgency && !has_focus) {
-               chat_window_set_urgency_hint (window, TRUE);
-       }
-
-       if (!is_backlog && 
-           !g_list_find (priv->chats_new_msg, chat)) {
-               priv->chats_new_msg = g_list_prepend (priv->chats_new_msg, chat);
-               chat_window_update_status (window, chat);
-       }
-}
-
-static GtkNotebook *
-chat_window_detach_hook (GtkNotebook *source,
-                        GtkWidget   *page,
-                        gint         x,
-                        gint         y,
-                        gpointer     user_data)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChatWindow     *window, *new_window;
-       EmpathyChat           *chat;
-
-       chat = g_object_get_data (G_OBJECT (page), "chat");
-       window = empathy_chat_get_window (chat);
-
-       new_window = empathy_chat_window_new ();
-       priv = GET_PRIV (new_window);
-
-       empathy_debug (DEBUG_DOMAIN, "Detach hook called");
-
-       empathy_chat_window_move_chat (window, new_window, chat);
-
-       gtk_window_move (GTK_WINDOW (priv->dialog), x, y);
-       gtk_widget_show (priv->dialog);
-
-       return NULL;
-}
-
-static void
-chat_window_page_switched_cb (GtkNotebook      *notebook,
-                             GtkNotebookPage  *page,
-                             gint              page_num,
-                             EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChat           *chat;
-       GtkWidget            *child;
-
-       empathy_debug (DEBUG_DOMAIN, "Page switched");
-
-       priv = GET_PRIV (window);
-
-       child = gtk_notebook_get_nth_page (notebook, page_num);
-       chat = g_object_get_data (G_OBJECT (child), "chat");
-
-       if (priv->page_added) {
-               priv->page_added = FALSE;
-               empathy_chat_scroll_down (chat);
-       }
-       else if (priv->current_chat == chat) {
-               return;
-       }
-
-       priv->current_chat = chat;
-       priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
-
-       chat_window_update_menu (window);
-       chat_window_update_status (window, chat);
-}
-
-static void
-chat_window_page_reordered_cb (GtkNotebook      *notebook,
-                              GtkWidget        *widget,
-                              guint             page_num,
-                              EmpathyChatWindow *window)
-{
-       empathy_debug (DEBUG_DOMAIN, "Page reordered");
-       
-       chat_window_update_menu (window);
-}
-
-static void
-chat_window_page_added_cb (GtkNotebook      *notebook,
-                          GtkWidget        *child,
-                          guint             page_num,
-                          EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChat           *chat;
-
-       priv = GET_PRIV (window);
-
-       /* If we just received DND to the same window, we don't want
-        * to do anything here like removing the tab and then readding
-        * it, so we return here and in "page-added".
-        */
-       if (priv->dnd_same_window) {
-               empathy_debug (DEBUG_DOMAIN, "Page added (back to the same window)");
-               priv->dnd_same_window = FALSE;
-               return;
-       }
-
-       empathy_debug (DEBUG_DOMAIN, "Page added");
-
-       /* Get chat object */
-       chat = g_object_get_data (G_OBJECT (child), "chat");
-
-       /* Set the chat window */
-       empathy_chat_set_window (chat, window);
-
-       /* Connect chat signals for this window */
-       g_signal_connect (chat, "status-changed",
-                         G_CALLBACK (chat_window_status_changed_cb),
-                         window);
-       g_signal_connect (chat, "name-changed",
-                         G_CALLBACK (chat_window_name_changed_cb),
-                         window);
-       g_signal_connect (chat, "composing",
-                         G_CALLBACK (chat_window_composing_cb),
-                         window);
-       g_signal_connect (chat, "new-message",
-                         G_CALLBACK (chat_window_new_message_cb),
-                         window);
-
-       /* Set flag so we know to perform some special operations on
-        * switch page due to the new page being added.
-        */
-       priv->page_added = TRUE;
-
-       /* Get list of chats up to date */
-       priv->chats = g_list_append (priv->chats, chat);
-}
-
-static void
-chat_window_page_removed_cb (GtkNotebook      *notebook,
-                            GtkWidget        *child,
-                            guint             page_num,
-                            EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       EmpathyChat           *chat;
-
-       priv = GET_PRIV (window);
-
-       /* If we just received DND to the same window, we don't want
-        * to do anything here like removing the tab and then readding
-        * it, so we return here and in "page-added".
-        */
-       if (priv->dnd_same_window) {
-               empathy_debug (DEBUG_DOMAIN, "Page removed (and will be readded to same window)");
-               return;
-       }
-
-       empathy_debug (DEBUG_DOMAIN, "Page removed");
-
-       /* Get chat object */
-       chat = g_object_get_data (G_OBJECT (child), "chat");
-
-       /* Unset the window associated with a chat */
-       empathy_chat_set_window (chat, NULL);
-
-       /* Disconnect all signal handlers for this chat and this window */
-       g_signal_handlers_disconnect_by_func (chat,
-                                             G_CALLBACK (chat_window_status_changed_cb),
-                                             window);
-       g_signal_handlers_disconnect_by_func (chat,
-                                             G_CALLBACK (chat_window_name_changed_cb),
-                                             window);
-       g_signal_handlers_disconnect_by_func (chat,
-                                             G_CALLBACK (chat_window_composing_cb),
-                                             window);
-       g_signal_handlers_disconnect_by_func (chat,
-                                             G_CALLBACK (chat_window_new_message_cb),
-                                             window);
-
-       /* Keep list of chats up to date */
-       priv->chats = g_list_remove (priv->chats, chat);
-       priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
-       priv->chats_composing = g_list_remove (priv->chats_composing, chat);
-
-       if (priv->chats == NULL) {
-               g_object_unref (window);
-       } else {
-               chat_window_update_menu (window);
-               chat_window_update_title (window, NULL);
-       }
-}
-
-static gboolean
-chat_window_focus_in_event_cb (GtkWidget        *widget,
-                              GdkEvent         *event,
-                              EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       empathy_debug (DEBUG_DOMAIN, "Focus in event, updating title");
-
-       priv = GET_PRIV (window);
-
-       priv->chats_new_msg = g_list_remove (priv->chats_new_msg, priv->current_chat);
-
-       chat_window_set_urgency_hint (window, FALSE);
-       
-       /* Update the title, since we now mark all unread messages as read. */
-       chat_window_update_status (window, priv->current_chat);
-
-       return FALSE;
-}
-
-static void
-chat_window_drag_data_received (GtkWidget        *widget,
-                               GdkDragContext   *context,
-                               int               x,
-                               int               y,
-                               GtkSelectionData *selection,
-                               guint             info,
-                               guint             time,
-                               EmpathyChatWindow *window)
-{
-       if (info == DND_DRAG_TYPE_CONTACT_ID) {
-               EmpathyChat           *chat;
-               EmpathyChatWindow     *old_window;
-               McAccount             *account;
-               const gchar           *id = NULL;
-               gchar                **strv;
-
-               if (selection) {
-                       id = (const gchar*) selection->data;
-               }
-
-               empathy_debug (DEBUG_DOMAIN, "DND contact from roster with id:'%s'", id);
-               
-               strv = g_strsplit (id, "/", 2);
-               account = mc_account_lookup (strv[0]);
-               chat = empathy_chat_window_find_chat (account, strv[1]);
-
-               if (!chat) {
-                       empathy_chat_with_contact_id (account, strv[2]);
-                       g_object_unref (account);
-                       g_strfreev (strv);
-                       return;
-               }
-               g_object_unref (account);
-               g_strfreev (strv);
-
-               old_window = empathy_chat_get_window (chat);            
-               if (old_window) {
-                       if (old_window == window) {
-                               gtk_drag_finish (context, TRUE, FALSE, time);
-                               return;
-                       }
-                       
-                       empathy_chat_window_move_chat (old_window, window, chat);
-               } else {
-                       empathy_chat_window_add_chat (window, chat);
-               }
-               
-               /* Added to take care of any outstanding chat events */
-               empathy_chat_present (chat);
-
-               /* We should return TRUE to remove the data when doing
-                * GDK_ACTION_MOVE, but we don't here otherwise it has
-                * weird consequences, and we handle that internally
-                * anyway with add_chat() and remove_chat().
-                */
-               gtk_drag_finish (context, TRUE, FALSE, time);
-       }
-       else if (info == DND_DRAG_TYPE_TAB) {
-               EmpathyChat        *chat = NULL;
-               EmpathyChatWindow  *old_window;
-               GtkWidget        **child = NULL;
-
-               empathy_debug (DEBUG_DOMAIN, "DND tab");
-
-               if (selection) {
-                       child = (void*) selection->data;
-               }
-
-               if (child) {
-                       chat = g_object_get_data (G_OBJECT (*child), "chat");
-               }
-
-               old_window = empathy_chat_get_window (chat);
-               if (old_window) {
-                       EmpathyChatWindowPriv *priv;
-
-                       priv = GET_PRIV (window);
-
-                       if (old_window == window) {
-                               empathy_debug (DEBUG_DOMAIN, "DND tab (within same window)");
-                               priv->dnd_same_window = TRUE;
-                               gtk_drag_finish (context, TRUE, FALSE, time);
-                               return;
-                       }
-                       
-                       priv->dnd_same_window = FALSE;
-               }
-
-               /* We should return TRUE to remove the data when doing
-                * GDK_ACTION_MOVE, but we don't here otherwise it has
-                * weird consequences, and we handle that internally
-                * anyway with add_chat() and remove_chat().
-                */
-               gtk_drag_finish (context, TRUE, FALSE, time);
-       } else {
-               empathy_debug (DEBUG_DOMAIN, "DND from unknown source");
-               gtk_drag_finish (context, FALSE, FALSE, time);
-       }
-}
-
-static void
-chat_window_set_urgency_hint (EmpathyChatWindow *window,
-                             gboolean          urgent)
-{
-       EmpathyChatWindowPriv *priv;
-
-       priv = GET_PRIV (window);
-
-       empathy_debug (DEBUG_DOMAIN, "Turning %s urgency hint",
-                      urgent ? "on" : "off");
-       gtk_window_set_urgency_hint (GTK_WINDOW (priv->dialog), urgent);
-}
-
-EmpathyChatWindow *
-empathy_chat_window_new (void)
-{
-       return EMPATHY_CHAT_WINDOW (g_object_new (EMPATHY_TYPE_CHAT_WINDOW, NULL));
-}
-
-GtkWidget *
-empathy_chat_window_get_dialog (EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-
-       g_return_val_if_fail (window != NULL, NULL);
-
-       priv = GET_PRIV (window);
-
-       return priv->dialog;
-}
-
-void
-empathy_chat_window_add_chat (EmpathyChatWindow *window,
-                             EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       GtkWidget             *label;
-       GtkWidget             *child;
-       gint                   x, y, w, h;
-
-       g_return_if_fail (window != NULL);
-       g_return_if_fail (EMPATHY_IS_CHAT (chat));
-
-       priv = GET_PRIV (window);
-
-       /* Reference the chat object */
-       g_object_ref (chat);
-
-       /* Set the chat window */
-       empathy_chat_set_window (chat, window);
-
-       empathy_chat_load_geometry (chat, &x, &y, &w, &h);
-
-       if (x >= 0 && y >= 0) {
-               /* Let the window manager position it if we don't have
-                * good x, y coordinates.
-                */
-               gtk_window_move (GTK_WINDOW (priv->dialog), x, y);
-       }
-
-       if (w > 0 && h > 0) {
-               /* Use the defaults from the glade file if we don't have
-                * good w, h geometry.
-                */
-               gtk_window_resize (GTK_WINDOW (priv->dialog), w, h);
-       }
-
-       child = empathy_chat_get_widget (chat);
-       label = chat_window_create_label (window, chat); 
-
-       gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), child, label);
-       gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
-       gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
-       gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (priv->notebook), child,
-                                           TRUE, TRUE, GTK_PACK_START); 
-
-       empathy_debug (DEBUG_DOMAIN, 
-                     "Chat added (%d references)",
-                     G_OBJECT (chat)->ref_count);
-}
-
-void
-empathy_chat_window_remove_chat (EmpathyChatWindow *window,
-                                EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       gint                  position;
-
-       g_return_if_fail (window != NULL);
-       g_return_if_fail (EMPATHY_IS_CHAT (chat));
-
-       priv = GET_PRIV (window);
-
-       position = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
-                                         empathy_chat_get_widget (chat));
-       gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), position);
-
-       empathy_debug (DEBUG_DOMAIN, 
-                     "Chat removed (%d references)", 
-                     G_OBJECT (chat)->ref_count - 1);
-
-       g_object_unref (chat);
-}
-
-void
-empathy_chat_window_move_chat (EmpathyChatWindow *old_window,
-                              EmpathyChatWindow *new_window,
-                              EmpathyChat       *chat)
-{
-       GtkWidget *widget;
-
-       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (old_window));
-       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (new_window));
-       g_return_if_fail (EMPATHY_IS_CHAT (chat));
-
-       widget = empathy_chat_get_widget (chat);
-
-       empathy_debug (DEBUG_DOMAIN,
-                     "Chat moving with widget:%p (%d references)", 
-                     widget,
-                     G_OBJECT (widget)->ref_count);
-
-       /* We reference here to make sure we don't loose the widget
-        * and the EmpathyChat object during the move.
-        */
-       g_object_ref (chat);
-       g_object_ref (widget);
-
-       empathy_chat_window_remove_chat (old_window, chat);
-       empathy_chat_window_add_chat (new_window, chat);
-
-       g_object_unref (widget);
-       g_object_unref (chat);
-}
-
-void
-empathy_chat_window_switch_to_chat (EmpathyChatWindow *window,
-                                   EmpathyChat       *chat)
-{
-       EmpathyChatWindowPriv *priv;
-       gint                  page_num;
-
-       g_return_if_fail (window != NULL);
-       g_return_if_fail (EMPATHY_IS_CHAT (chat));
-
-       priv = GET_PRIV (window);
-
-       page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
-                                         empathy_chat_get_widget (chat));
-       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
-                                      page_num);
-}
-
-gboolean
-empathy_chat_window_has_focus (EmpathyChatWindow *window)
-{
-       EmpathyChatWindowPriv *priv;
-       gboolean              has_focus;
-
-       g_return_val_if_fail (EMPATHY_IS_CHAT_WINDOW (window), FALSE);
-
-       priv = GET_PRIV (window);
-
-       g_object_get (priv->dialog, "has-toplevel-focus", &has_focus, NULL);
-
-       return has_focus;
-}
-
-EmpathyChat *
-empathy_chat_window_find_chat (McAccount   *account,
-                              const gchar *id)
-{
-       GList *l;
-
-       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
-       g_return_val_if_fail (!G_STR_EMPTY (id), NULL);
-
-       for (l = chat_windows; l; l = l->next) {
-               EmpathyChatWindowPriv *priv;
-               EmpathyChatWindow     *window;
-               GList                *ll;
-
-               window = l->data;
-               priv = GET_PRIV (window);
-
-               for (ll = priv->chats; ll; ll = ll->next) {
-                       EmpathyChat *chat;
-
-                       chat = ll->data;
-
-                       if (empathy_account_equal (account, empathy_chat_get_account (chat)) &&
-                           strcmp (id, empathy_chat_get_id (chat)) == 0) {
-                               return chat;
-                       }
-               }
-       }
-
-       return NULL;
-}
-
diff --git a/libempathy-gtk/empathy-chat-window.h b/libempathy-gtk/empathy-chat-window.h
deleted file mode 100644 (file)
index c79f751..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2003-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Mikael Hallendal <micke@imendio.com>
- *          Richard Hult <richard@imendio.com>
- *          Martyn Russell <martyn@imendio.com>
- *          Geert-Jan Van den Bogaerde <geertjan@gnome.org>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_CHAT_WINDOW_H__
-#define __EMPATHY_CHAT_WINDOW_H__
-
-#include <glib-object.h>
-
-#include <libmissioncontrol/mc-account.h>
-
-G_BEGIN_DECLS
-
-#define EMPATHY_TYPE_CHAT_WINDOW         (empathy_chat_window_get_type ())
-#define EMPATHY_CHAT_WINDOW(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindow))
-#define EMPATHY_CHAT_WINDOW_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowClass))
-#define EMPATHY_IS_CHAT_WINDOW(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CHAT_WINDOW))
-#define EMPATHY_IS_CHAT_WINDOW_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_CHAT_WINDOW))
-#define EMPATHY_CHAT_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowClass))
-
-typedef struct _EmpathyChatWindow      EmpathyChatWindow;
-typedef struct _EmpathyChatWindowClass EmpathyChatWindowClass;
-typedef struct _EmpathyChatWindowPriv  EmpathyChatWindowPriv;
-
-#include "empathy-chat.h"
-
-struct _EmpathyChatWindow {
-       GObject parent;
-};
-
-struct _EmpathyChatWindowClass {
-       GObjectClass parent_class;
-};
-
-GType             empathy_chat_window_get_type        (void);
-EmpathyChatWindow *empathy_chat_window_get_default     (void);
-
-EmpathyChatWindow *empathy_chat_window_new             (void);
-
-GtkWidget *       empathy_chat_window_get_dialog      (EmpathyChatWindow *window);
-
-void              empathy_chat_window_add_chat        (EmpathyChatWindow *window,
-                                                     EmpathyChat       *chat);
-void              empathy_chat_window_remove_chat     (EmpathyChatWindow *window,
-                                                     EmpathyChat       *chat);
-void              empathy_chat_window_move_chat       (EmpathyChatWindow *old_window,
-                                                     EmpathyChatWindow *new_window,
-                                                     EmpathyChat       *chat);
-void              empathy_chat_window_switch_to_chat  (EmpathyChatWindow *window,
-                                                     EmpathyChat       *chat);
-gboolean          empathy_chat_window_has_focus       (EmpathyChatWindow *window);
-EmpathyChat *      empathy_chat_window_find_chat       (McAccount        *account,
-                                                     const gchar      *id);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_CHAT_WINDOW_H__ */
index 1b2fcccb2a9a09dab1ecf1df96c908e348b16d53..50a37003705e931f5cda68bb64f9b81d7b7cdac8 100644 (file)
 #include <libempathy/empathy-utils.h>
 
 #include "empathy-chat.h"
-#include "empathy-chat-window.h"
 #include "empathy-geometry.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 #include "empathy-spell.h"
 #include "empathy-spell-dialog.h"
 #include "empathy-ui-utils.h"
@@ -67,9 +65,9 @@
 struct _EmpathyChatPriv {
        EmpathyLogManager     *log_manager;
        EmpathyTpChat         *tp_chat;
-       EmpathyChatWindow     *window;
        McAccount             *account;
        MissionControl        *mc;
+       GtkWidget             *widget;
        guint                  composing_stop_timeout_id;
        gboolean               sensitive;
        gchar                 *id;
@@ -802,21 +800,20 @@ chat_input_text_buffer_changed_cb (GtkTextBuffer *buffer,
        if (priv->is_first_char) {
                GtkRequisition  req;
                gint            window_height;
-               GtkWidget      *dialog;
+               GtkWindow      *dialog;
                GtkAllocation  *allocation;
 
                /* Save the window's size */
-               dialog = empathy_chat_window_get_dialog (priv->window);
-               gtk_window_get_size (GTK_WINDOW (dialog),
-                                    NULL, &window_height);
-
-               gtk_widget_size_request (chat->input_text_view, &req);
-
-               allocation = &GTK_WIDGET (chat->view)->allocation;
-
-               priv->default_window_height = window_height;
-               priv->last_input_height = req.height;
-               priv->padding_height = window_height - req.height - allocation->height;
+               dialog = empathy_get_toplevel_window (priv->widget);
+               if (dialog) {
+                       gtk_window_get_size (GTK_WINDOW (dialog), NULL, &window_height);
+                       gtk_widget_size_request (chat->input_text_view, &req);
+                       allocation = &GTK_WIDGET (chat->view)->allocation;
+
+                       priv->default_window_height = window_height;
+                       priv->last_input_height = req.height;
+                       priv->padding_height = window_height - req.height - allocation->height;
+               }
 
                priv->is_first_char = FALSE;
        }
@@ -880,7 +877,7 @@ chat_input_text_buffer_changed_cb (GtkTextBuffer *buffer,
 }
 
 typedef struct {
-       GtkWidget *window;
+       GtkWindow *window;
        gint       width;
        gint       height;
 } ChangeSizeData;
@@ -888,8 +885,7 @@ typedef struct {
 static gboolean
 chat_change_size_in_idle_cb (ChangeSizeData *data)
 {
-       gtk_window_resize (GTK_WINDOW (data->window),
-                          data->width, data->height);
+       gtk_window_resize (data->window, data->width, data->height);
 
        return FALSE;
 }
@@ -920,7 +916,7 @@ chat_text_view_size_allocate_cb (GtkWidget     *widget,
 {
        EmpathyChatPriv *priv;
        gint            width;
-       GtkWidget      *dialog;
+       GtkWindow      *dialog;
        ChangeSizeData *data;
        gint            window_height;
        gint            new_height;
@@ -960,8 +956,8 @@ chat_text_view_size_allocate_cb (GtkWidget     *widget,
 
        view_allocation = &GTK_WIDGET (chat->view)->allocation;
 
-       dialog = empathy_chat_window_get_dialog (priv->window);
-       gtk_window_get_size (GTK_WINDOW (dialog), NULL, &current_height);
+       dialog = empathy_get_toplevel_window (priv->widget);
+       gtk_window_get_size (dialog, NULL, &current_height);
 
        new_height = view_allocation->height + priv->padding_height + allocation->height - diff;
 
@@ -976,7 +972,7 @@ chat_text_view_size_allocate_cb (GtkWidget     *widget,
        }
 
        /* Restore the window's size */
-       gtk_window_get_size (GTK_WINDOW (dialog), &width, NULL);
+       gtk_window_get_size (dialog, &width, NULL);
 
        data = g_new0 (ChangeSizeData, 1);
        data->window = dialog;
@@ -1395,13 +1391,15 @@ empathy_chat_get_status_icon_name (EmpathyChat *chat)
 GtkWidget *
 empathy_chat_get_widget (EmpathyChat *chat)
 {
+       EmpathyChatPriv *priv = GET_PRIV (chat);
+
        g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL);
 
-       if (EMPATHY_CHAT_GET_CLASS (chat)->get_widget) {
-               return EMPATHY_CHAT_GET_CLASS (chat)->get_widget (chat);
+       if (!priv->widget && EMPATHY_CHAT_GET_CLASS (chat)->get_widget) {
+               priv->widget = EMPATHY_CHAT_GET_CLASS (chat)->get_widget (chat);
        }
 
-       return NULL;
+       return priv->widget;
 }
 
 gboolean
@@ -1579,26 +1577,6 @@ empathy_chat_clear (EmpathyChat *chat)
        empathy_chat_view_clear (chat->view);
 }
 
-void
-empathy_chat_set_window (EmpathyChat       *chat,
-                       EmpathyChatWindow *window)
-{
-       EmpathyChatPriv *priv;
-
-       priv = GET_PRIV (chat);
-       priv->window = window;
-}
-
-EmpathyChatWindow *
-empathy_chat_get_window (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
-
-       priv = GET_PRIV (chat);
-
-       return priv->window;
-}
-
 void
 empathy_chat_scroll_down (EmpathyChat *chat)
 {
@@ -1660,50 +1638,21 @@ empathy_chat_paste (EmpathyChat *chat)
        gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
 }
 
-void
-empathy_chat_present (EmpathyChat *chat)
-{
-       EmpathyChatPriv *priv;
-
-       g_return_if_fail (EMPATHY_IS_CHAT (chat));
-
-       priv = GET_PRIV (chat);
-
-       if (priv->window == NULL) {
-               EmpathyChatWindow *window;
-
-               window = empathy_chat_window_get_default ();
-               if (!window) {
-                       window = empathy_chat_window_new ();
-               }
-
-               empathy_chat_window_add_chat (window, chat);
-       }
-
-       empathy_chat_window_switch_to_chat (priv->window, chat);
-       empathy_window_present (
-               GTK_WINDOW (empathy_chat_window_get_dialog (priv->window)),
-               TRUE);
-
-       gtk_widget_grab_focus (chat->input_text_view); 
-}
-
 gboolean
 empathy_chat_should_play_sound (EmpathyChat *chat)
 {
-       EmpathyChatWindow *window;
-       gboolean          play = TRUE;
+       EmpathyChatPriv *priv = GET_PRIV (chat);
+       GtkWindow       *window;
+       gboolean         has_focus = FALSE;
 
        g_return_val_if_fail (EMPATHY_IS_CHAT (chat), FALSE);
 
-       window = empathy_chat_get_window (chat);
-       if (!window) {
-               return TRUE;
+       window = empathy_get_toplevel_window (priv->widget);
+       if (window) {
+               g_object_get (window, "has-toplevel-focus", &has_focus, NULL);
        }
 
-       play = !empathy_chat_window_has_focus (window);
-
-       return play;
+       return !has_focus;
 }
 
 gboolean
index bcf382e535200c6bbb584cc42d98e3cebe0b03af..d235c08af56467c4cd418331e93352d296114041 100644 (file)
@@ -50,8 +50,6 @@ typedef struct _EmpathyChat       EmpathyChat;
 typedef struct _EmpathyChatClass  EmpathyChatClass;
 typedef struct _EmpathyChatPriv   EmpathyChatPriv;
 
-#include "empathy-chat-window.h"
-
 struct _EmpathyChat {
        GObject          parent;
 
@@ -79,9 +77,6 @@ struct _EmpathyChatClass {
 GType              empathy_chat_get_type              (void);
 
 EmpathyChatView *  empathy_chat_get_view              (EmpathyChat       *chat);
-EmpathyChatWindow *empathy_chat_get_window            (EmpathyChat       *chat);
-void               empathy_chat_set_window            (EmpathyChat       *chat,
-                                                      EmpathyChatWindow *window);
 void               empathy_chat_present               (EmpathyChat       *chat);
 void               empathy_chat_clear                 (EmpathyChat       *chat);
 void               empathy_chat_scroll_down           (EmpathyChat       *chat);
diff --git a/libempathy-gtk/empathy-chatrooms-window.c b/libempathy-gtk/empathy-chatrooms-window.c
deleted file mode 100644 (file)
index 7855f3c..0000000
+++ /dev/null
@@ -1,582 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2004-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- *          Martyn Russell <martyn@imendio.com>
- *          Mikael Hallendal <micke@imendio.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdio.h>
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include <libempathy/empathy-chatroom-manager.h>
-#include <libempathy/empathy-utils.h>
-
-#include "empathy-account-chooser.h"
-#include "empathy-chatrooms-window.h"
-#include "empathy-new-chatroom-dialog.h"
-#include "empathy-ui-utils.h"
-
-typedef struct {
-       EmpathyChatroomManager *manager;
-
-       GtkWidget             *window;
-       GtkWidget             *hbox_account;
-       GtkWidget             *label_account;
-       GtkWidget             *account_chooser;
-       GtkWidget             *treeview;
-       GtkWidget             *button_remove;
-       GtkWidget             *button_edit;
-       GtkWidget             *button_close;
-
-       gint                   room_column;
-} EmpathyChatroomsWindow;
-
-static void             chatrooms_window_destroy_cb                      (GtkWidget             *widget,
-                                                                         EmpathyChatroomsWindow *window);
-static void             chatrooms_window_model_setup                     (EmpathyChatroomsWindow *window);
-static void             chatrooms_window_model_add_columns               (EmpathyChatroomsWindow *window);
-static void             chatrooms_window_model_refresh_data              (EmpathyChatroomsWindow *window,
-                                                                         gboolean               first_time);
-static void             chatrooms_window_model_add                       (EmpathyChatroomsWindow *window,
-                                                                         EmpathyChatroom        *chatroom,
-                                                                         gboolean               set_active);
-static void             chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
-                                                                         gchar                  *path_string,
-                                                                         EmpathyChatroomsWindow  *window);
-static EmpathyChatroom * chatrooms_window_model_get_selected              (EmpathyChatroomsWindow *window);
-static void             chatrooms_window_model_action_selected           (EmpathyChatroomsWindow *window);
-static void             chatrooms_window_row_activated_cb                (GtkTreeView           *tree_view,
-                                                                         GtkTreePath           *path,
-                                                                         GtkTreeViewColumn     *column,
-                                                                         EmpathyChatroomsWindow *window);
-static void             chatrooms_window_button_remove_clicked_cb        (GtkWidget             *widget,
-                                                                         EmpathyChatroomsWindow *window);
-static void             chatrooms_window_button_edit_clicked_cb          (GtkWidget             *widget,
-                                                                         EmpathyChatroomsWindow *window);
-static void             chatrooms_window_button_close_clicked_cb         (GtkWidget             *widget,
-                                                                         EmpathyChatroomsWindow *window);
-static void             chatrooms_window_chatroom_added_cb               (EmpathyChatroomManager *manager,
-                                                                         EmpathyChatroom        *chatroom,
-                                                                         EmpathyChatroomsWindow *window);
-static void             chatrooms_window_chatroom_removed_cb             (EmpathyChatroomManager *manager,
-                                                                         EmpathyChatroom        *chatroom,
-                                                                         EmpathyChatroomsWindow *window);
-static gboolean         chatrooms_window_remove_chatroom_foreach         (GtkTreeModel          *model,
-                                                                         GtkTreePath           *path,
-                                                                         GtkTreeIter           *iter,
-                                                                         EmpathyChatroom        *chatroom);
-static void             chatrooms_window_account_changed_cb              (GtkWidget             *combo_box,
-                                                                         EmpathyChatroomsWindow *window);
-
-enum {
-       COL_IMAGE,
-       COL_NAME,
-       COL_ROOM,
-       COL_AUTO_CONNECT,
-       COL_POINTER,
-       COL_COUNT
-};
-
-void
-empathy_chatrooms_window_show (GtkWindow *parent)
-{
-       static EmpathyChatroomsWindow *window = NULL;
-       GladeXML                     *glade;
-
-       if (window) {
-               gtk_window_present (GTK_WINDOW (window->window));
-               return;
-       }
-
-       window = g_new0 (EmpathyChatroomsWindow, 1);
-
-       glade = empathy_glade_get_file ("empathy-chatrooms-window.glade",
-                                      "chatrooms_window",
-                                      NULL,
-                                      "chatrooms_window", &window->window,
-                                      "hbox_account", &window->hbox_account,
-                                      "label_account", &window->label_account,
-                                      "treeview", &window->treeview,
-                                      "button_edit", &window->button_edit,
-                                      "button_remove", &window->button_remove,
-                                      "button_close", &window->button_close,
-                                      NULL);
-
-       empathy_glade_connect (glade,
-                             window,
-                             "chatrooms_window", "destroy", chatrooms_window_destroy_cb,
-                             "button_remove", "clicked", chatrooms_window_button_remove_clicked_cb,
-                             "button_edit", "clicked", chatrooms_window_button_edit_clicked_cb,
-                             "button_close", "clicked", chatrooms_window_button_close_clicked_cb,
-                             NULL);
-
-       g_object_unref (glade);
-
-       g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer) &window);
-
-       /* Get the session and chat room manager */
-       window->manager = empathy_chatroom_manager_new ();
-
-       g_signal_connect (window->manager, "chatroom-added",
-                         G_CALLBACK (chatrooms_window_chatroom_added_cb),
-                         window);
-       g_signal_connect (window->manager, "chatroom-removed",
-                         G_CALLBACK (chatrooms_window_chatroom_removed_cb),
-                         window);
-
-       /* Account chooser for chat rooms */
-       window->account_chooser = empathy_account_chooser_new ();
-       empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
-                                           empathy_account_chooser_filter_is_connected,
-                                           NULL);
-       g_object_set (window->account_chooser, 
-                     "has-all-option", TRUE,
-                     NULL);
-       empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser), NULL);
-
-       gtk_box_pack_start (GTK_BOX (window->hbox_account),
-                           window->account_chooser,
-                           TRUE, TRUE, 0);
-
-       g_signal_connect (window->account_chooser, "changed",
-                         G_CALLBACK (chatrooms_window_account_changed_cb),
-                         window);
-
-       gtk_widget_show (window->account_chooser);
-
-       /* Set up chatrooms */
-       chatrooms_window_model_setup (window);
-
-       /* Set focus */
-       gtk_widget_grab_focus (window->treeview);
-
-       /* Last touches */
-       if (parent) {
-               gtk_window_set_transient_for (GTK_WINDOW (window->window),
-                                             GTK_WINDOW (parent));
-       }
-
-       gtk_widget_show (window->window);
-}
-
-static void
-chatrooms_window_destroy_cb (GtkWidget             *widget,
-                            EmpathyChatroomsWindow *window)
-{
-       g_signal_handlers_disconnect_by_func (window->manager,
-                                             chatrooms_window_chatroom_added_cb,
-                                             window);
-       g_signal_handlers_disconnect_by_func (window->manager,
-                                             chatrooms_window_chatroom_removed_cb,
-                                             window);
-       g_object_unref (window->manager);
-       g_free (window);
-}
-
-static void
-chatrooms_window_model_setup (EmpathyChatroomsWindow *window)
-{
-       GtkTreeView      *view;
-       GtkListStore     *store;
-       GtkTreeSelection *selection;
-
-       /* View */
-       view = GTK_TREE_VIEW (window->treeview);
-
-       g_signal_connect (view, "row-activated",
-                         G_CALLBACK (chatrooms_window_row_activated_cb),
-                         window);
-
-       /* Store */
-       store = gtk_list_store_new (COL_COUNT,
-                                   G_TYPE_STRING,         /* Image */
-                                   G_TYPE_STRING,         /* Name */
-                                   G_TYPE_STRING,         /* Room */
-                                   G_TYPE_BOOLEAN,        /* Auto start */
-                                   EMPATHY_TYPE_CHATROOM); /* Chatroom */
-
-       gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
-
-       /* Selection */ 
-       selection = gtk_tree_view_get_selection (view);
-       gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
-
-       /* Columns */
-       chatrooms_window_model_add_columns (window);
-
-       /* Add data */
-       chatrooms_window_model_refresh_data (window, TRUE);
-
-       /* Clean up */
-       g_object_unref (store);
-}
-
-static void
-chatrooms_window_model_add_columns (EmpathyChatroomsWindow *window)
-{
-       GtkTreeView       *view;
-       GtkTreeModel      *model;
-       GtkTreeViewColumn *column;
-       GtkCellRenderer   *cell;
-       gint               count;
-
-       view = GTK_TREE_VIEW (window->treeview);
-       model = gtk_tree_view_get_model (view);
-
-       gtk_tree_view_set_headers_visible (view, TRUE);
-       gtk_tree_view_set_headers_clickable (view, TRUE);
-
-       /* Name & Status */
-       column = gtk_tree_view_column_new ();
-       count = gtk_tree_view_append_column (view, column);
-
-       gtk_tree_view_column_set_title (column, _("Name"));
-       gtk_tree_view_column_set_expand (column, TRUE);
-       gtk_tree_view_column_set_sort_column_id (column, count - 1);
-
-       cell = gtk_cell_renderer_pixbuf_new ();
-       gtk_tree_view_column_pack_start (column, cell, FALSE);
-       gtk_tree_view_column_add_attribute (column, cell, "icon-name", COL_IMAGE);
-
-       cell = gtk_cell_renderer_text_new ();
-       g_object_set (cell,
-                     "xpad", 4,
-                     "ypad", 1,
-                     NULL);
-       gtk_tree_view_column_pack_start (column, cell, TRUE);
-       gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
-
-       /* Room */
-       cell = gtk_cell_renderer_text_new ();
-       column = gtk_tree_view_column_new_with_attributes (_("Room"), cell, 
-                                                          "text", COL_ROOM, 
-                                                          NULL);
-       count = gtk_tree_view_append_column (view, column);
-       gtk_tree_view_column_set_sort_column_id (column, count - 1);
-       window->room_column = count - 1;
-
-       /* Chatroom auto connect */
-       cell = gtk_cell_renderer_toggle_new ();
-       column = gtk_tree_view_column_new_with_attributes (_("Auto Connect"), cell,
-                                                          "active", COL_AUTO_CONNECT,
-                                                          NULL);
-       count = gtk_tree_view_append_column (view, column);
-       gtk_tree_view_column_set_sort_column_id (column, count - 1);
-
-       g_signal_connect (cell, "toggled",
-                         G_CALLBACK (chatrooms_window_model_cell_auto_connect_toggled),
-                         window);
-
-       /* Sort model */
-       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 0, 
-                                             GTK_SORT_ASCENDING);
-}
-
-static void
-chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
-                                    gboolean               first_time)
-{
-       GtkTreeView           *view;
-       GtkTreeSelection      *selection;
-       GtkTreeModel          *model;
-       GtkListStore          *store;
-       GtkTreeIter            iter;
-       GtkTreeViewColumn     *column;
-       EmpathyAccountChooser  *account_chooser;
-       McAccount             *account;
-       GList                 *chatrooms, *l;
-
-       view = GTK_TREE_VIEW (window->treeview);
-       selection = gtk_tree_view_get_selection (view);
-       model = gtk_tree_view_get_model (view);
-       store = GTK_LIST_STORE (model);
-
-       /* Look up chatrooms */
-       account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
-
-       chatrooms = empathy_chatroom_manager_get_chatrooms (window->manager, account);
-
-       /* Sort out columns, we only show the server column for
-        * selected protocol types, such as Jabber. 
-        */
-       if (account) {
-               column = gtk_tree_view_get_column (view, window->room_column);
-               gtk_tree_view_column_set_visible (column, TRUE);
-       } else {
-               column = gtk_tree_view_get_column (view, window->room_column);
-               gtk_tree_view_column_set_visible (column, FALSE);
-       }
-
-       /* Clean out the store */
-       gtk_list_store_clear (store);
-
-       /* Populate with chatroom list. */
-       for (l = chatrooms; l; l = l->next) {
-               chatrooms_window_model_add (window, l->data,  FALSE);
-       }
-
-       if (gtk_tree_model_get_iter_first (model, &iter)) {
-               gtk_tree_selection_select_iter (selection, &iter);
-       }
-
-       if (account) {
-               g_object_unref (account);
-       }
-
-       g_list_free (chatrooms);
-}
-
-static void
-chatrooms_window_model_add (EmpathyChatroomsWindow *window,
-                           EmpathyChatroom        *chatroom,
-                           gboolean               set_active)
-{
-       GtkTreeView      *view;
-       GtkTreeModel     *model;
-       GtkTreeSelection *selection;
-       GtkListStore     *store;
-       GtkTreeIter       iter;
-
-       view = GTK_TREE_VIEW (window->treeview);
-       selection = gtk_tree_view_get_selection (view);
-       model = gtk_tree_view_get_model (view);
-       store = GTK_LIST_STORE (model);
-
-       gtk_list_store_append (store, &iter);
-       gtk_list_store_set (store, &iter,
-                           COL_NAME, empathy_chatroom_get_name (chatroom),
-                           COL_ROOM, empathy_chatroom_get_room (chatroom),
-                           COL_AUTO_CONNECT, empathy_chatroom_get_auto_connect (chatroom),
-                           COL_POINTER, chatroom,
-                           -1);
-
-       if (set_active) {
-               gtk_tree_selection_select_iter (selection, &iter);
-       }
-}
-
-static void
-chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
-                                                 gchar                  *path_string,
-                                                 EmpathyChatroomsWindow  *window)
-{
-       EmpathyChatroom *chatroom;
-       gboolean        enabled;
-       GtkTreeView    *view;
-       GtkTreeModel   *model;
-       GtkListStore   *store;
-       GtkTreePath    *path;
-       GtkTreeIter     iter;
-
-       view = GTK_TREE_VIEW (window->treeview);
-       model = gtk_tree_view_get_model (view);
-       store = GTK_LIST_STORE (model);
-
-       path = gtk_tree_path_new_from_string (path_string);
-
-       gtk_tree_model_get_iter (model, &iter, path);
-       gtk_tree_model_get (model, &iter,
-                           COL_AUTO_CONNECT, &enabled,
-                           COL_POINTER, &chatroom,
-                           -1);
-
-       enabled = !enabled;
-
-       empathy_chatroom_set_auto_connect (chatroom, enabled);
-       empathy_chatroom_manager_store (window->manager);
-
-       gtk_list_store_set (store, &iter, COL_AUTO_CONNECT, enabled, -1);
-       gtk_tree_path_free (path);
-       g_object_unref (chatroom);
-}
-
-static EmpathyChatroom *
-chatrooms_window_model_get_selected (EmpathyChatroomsWindow *window)
-{
-       GtkTreeView      *view;
-       GtkTreeModel     *model;
-       GtkTreeSelection *selection;
-       GtkTreeIter       iter;
-       EmpathyChatroom   *chatroom = NULL;
-
-       view = GTK_TREE_VIEW (window->treeview);
-       selection = gtk_tree_view_get_selection (view);
-
-       if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
-               gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
-       }
-
-       return chatroom;
-}
-
-static void
-chatrooms_window_model_action_selected (EmpathyChatroomsWindow *window)
-{
-       EmpathyChatroom *chatroom;
-       GtkTreeView    *view;
-       GtkTreeModel   *model;
-
-       view = GTK_TREE_VIEW (window->treeview);
-       model = gtk_tree_view_get_model (view);
-
-       chatroom = chatrooms_window_model_get_selected (window);
-       if (!chatroom) {
-               return;
-       }
-
-       //empathy_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom);
-
-       g_object_unref (chatroom);
-}
-
-static void
-chatrooms_window_row_activated_cb (GtkTreeView           *tree_view,
-                                  GtkTreePath           *path,
-                                  GtkTreeViewColumn     *column,
-                                  EmpathyChatroomsWindow *window)
-{
-       if (GTK_WIDGET_IS_SENSITIVE (window->button_edit)) {
-               chatrooms_window_model_action_selected (window);
-       }
-}
-
-static void
-chatrooms_window_button_remove_clicked_cb (GtkWidget             *widget,
-                                          EmpathyChatroomsWindow *window)
-{
-       EmpathyChatroom        *chatroom;
-       GtkTreeView           *view;
-       GtkTreeModel          *model;
-       GtkTreeSelection      *selection;
-       GtkTreeIter            iter;
-
-       /* Remove from treeview */
-       view = GTK_TREE_VIEW (window->treeview);
-       selection = gtk_tree_view_get_selection (view);
-
-       if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
-               return;
-       }
-
-       gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
-       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
-
-       /* Remove from config */
-       empathy_chatroom_manager_remove (window->manager, chatroom);
-
-       g_object_unref (chatroom);
-}
-
-static void
-chatrooms_window_button_edit_clicked_cb (GtkWidget             *widget,
-                                        EmpathyChatroomsWindow *window)
-{
-       EmpathyChatroom *chatroom;
-
-       chatroom = chatrooms_window_model_get_selected (window);
-       if (!chatroom) {
-               return;
-       }
-
-       //empathy_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom);
-
-       g_object_unref (chatroom);
-}
-
-static void
-chatrooms_window_button_close_clicked_cb (GtkWidget             *widget,
-                                         EmpathyChatroomsWindow *window)
-{
-       gtk_widget_destroy (window->window);
-}
-
-static void
-chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager,
-                                   EmpathyChatroom        *chatroom,
-                                   EmpathyChatroomsWindow *window)
-{
-       EmpathyAccountChooser *account_chooser;
-       McAccount            *account;
-
-       account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
-
-       if (!account) {
-               chatrooms_window_model_add (window, chatroom, FALSE);
-       } else {
-               if (empathy_account_equal (account, empathy_chatroom_get_account (chatroom))) {
-                       chatrooms_window_model_add (window, chatroom, FALSE);
-               }
-
-               g_object_unref (account);
-       }
-}
-
-static void
-chatrooms_window_chatroom_removed_cb (EmpathyChatroomManager *manager,
-                                     EmpathyChatroom        *chatroom,
-                                     EmpathyChatroomsWindow *window)
-{
-       GtkTreeModel *model;
-
-       model = gtk_tree_view_get_model (GTK_TREE_VIEW (window->treeview));
-
-       gtk_tree_model_foreach (model,
-                               (GtkTreeModelForeachFunc) chatrooms_window_remove_chatroom_foreach,
-                               chatroom);
-}
-
-static gboolean
-chatrooms_window_remove_chatroom_foreach (GtkTreeModel   *model,
-                                         GtkTreePath    *path,
-                                         GtkTreeIter    *iter,
-                                         EmpathyChatroom *chatroom)
-{
-       EmpathyChatroom *this_chatroom;
-
-       gtk_tree_model_get (model, iter, COL_POINTER, &this_chatroom, -1);
-
-       if (empathy_chatroom_equal (chatroom, this_chatroom)) {
-               gtk_list_store_remove (GTK_LIST_STORE (model), iter);
-               g_object_unref (this_chatroom);
-               return TRUE;
-       }
-
-       g_object_unref (this_chatroom);
-
-       return FALSE;
-}
-
-static void
-chatrooms_window_account_changed_cb (GtkWidget             *combo_box,
-                                    EmpathyChatroomsWindow *window)
-{
-       chatrooms_window_model_refresh_data (window, FALSE);
-}
-
diff --git a/libempathy-gtk/empathy-chatrooms-window.glade b/libempathy-gtk/empathy-chatrooms-window.glade
deleted file mode 100644 (file)
index 3316e6e..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--*- mode: xml -*-->
-<glade-interface>
-  <widget class="GtkDialog" id="edit_chatroom_dialog">
-    <property name="visible">True</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Edit Favorite Room</property>
-    <property name="resizable">False</property>
-    <property name="icon_name">gtk-edit</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox3">
-        <property name="visible">True</property>
-        <property name="spacing">2</property>
-        <child>
-          <widget class="GtkTable" id="table4">
-            <property name="visible">True</property>
-            <property name="border_width">5</property>
-            <property name="n_rows">5</property>
-            <property name="n_columns">2</property>
-            <property name="column_spacing">12</property>
-            <property name="row_spacing">6</property>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <widget class="GtkCheckButton" id="checkbutton_auto_connect">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="tooltip" translatable="yes">Join this chat room when Empathy starts and you are connected</property>
-                <property name="label" translatable="yes">Join room on start_up</property>
-                <property name="use_underline">True</property>
-                <property name="response_id">0</property>
-                <property name="draw_indicator">True</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">4</property>
-                <property name="bottom_attach">5</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkEntry" id="entry_name">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="invisible_char">*</property>
-                <property name="width_chars">25</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label_name">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">N_ame:</property>
-                <property name="use_underline">True</property>
-                <property name="mnemonic_widget">entry_name</property>
-              </widget>
-              <packing>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label_nickname">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">_Nickname:</property>
-                <property name="use_underline">True</property>
-                <property name="mnemonic_widget">entry_nickname</property>
-              </widget>
-              <packing>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label_server">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">S_erver:</property>
-                <property name="use_underline">True</property>
-                <property name="mnemonic_widget">entry_server</property>
-              </widget>
-              <packing>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label_room">
-                <property name="visible">True</property>
-                <property name="xalign">0</property>
-                <property name="label" translatable="yes">_Room:</property>
-                <property name="use_underline">True</property>
-                <property name="mnemonic_widget">entry_room</property>
-              </widget>
-              <packing>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
-                <property name="x_options">GTK_FILL</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkEntry" id="entry_nickname">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="invisible_char">*</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">1</property>
-                <property name="bottom_attach">2</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkEntry" id="entry_server">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="invisible_char">*</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">2</property>
-                <property name="bottom_attach">3</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkEntry" id="entry_room">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="invisible_char">*</property>
-              </widget>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="right_attach">2</property>
-                <property name="top_attach">3</property>
-                <property name="bottom_attach">4</property>
-                <property name="y_options"></property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <widget class="GtkHButtonBox" id="dialog-action_area3">
-            <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
-            <child>
-              <widget class="GtkButton" id="button_cancel">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-cancel</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">-6</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button_save">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-save</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">-5</property>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">GTK_PACK_END</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-  <widget class="GtkWindow" id="chatrooms_window">
-    <property name="visible">True</property>
-    <property name="border_width">12</property>
-    <property name="title" translatable="yes">Manage Favorite Rooms</property>
-    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
-    <child>
-      <widget class="GtkVBox" id="vbox12">
-        <property name="visible">True</property>
-        <property name="spacing">12</property>
-        <child>
-          <widget class="GtkVBox" id="vbox18">
-            <property name="visible">True</property>
-            <property name="spacing">18</property>
-            <child>
-              <widget class="GtkHBox" id="hbox_account">
-                <property name="visible">True</property>
-                <property name="spacing">12</property>
-                <child>
-                  <widget class="GtkLabel" id="label_account">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Account:</property>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </widget>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkScrolledWindow" id="scrolledwindow1">
-                <property name="height_request">150</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
-                <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                <property name="shadow_type">GTK_SHADOW_IN</property>
-                <child>
-                  <widget class="GtkTreeView" id="treeview">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="has_focus">True</property>
-                  </widget>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </widget>
-        </child>
-        <child>
-          <widget class="GtkHButtonBox" id="hbuttonbox3">
-            <property name="visible">True</property>
-            <property name="spacing">6</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
-            <child>
-              <widget class="GtkButton" id="button_remove">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-remove</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">0</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button_edit">
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-edit</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">0</property>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button_close">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-close</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">0</property>
-              </widget>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/libempathy-gtk/empathy-chatrooms-window.h b/libempathy-gtk/empathy-chatrooms-window.h
deleted file mode 100644 (file)
index 1790820..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2004-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- *          Martyn Russell <martyn@imendio.com>
- *          Mikael Hallendal <micke@imendio.com>
- */
-
-#ifndef __EMPATHY_CHATROOMS_WINDOW_H__
-#define __EMPATHY_CHATROOMS_WINDOW_H__
-
-G_BEGIN_DECLS
-
-void empathy_chatrooms_window_show (GtkWindow *parent);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_CHATROOMS_WINDOW_H__ */
index 7e8e60e25864c84a8dbac3f8809952830659f3cf..c1e4913522e11c90b6e00f806325e5ff193488e6 100644 (file)
@@ -43,6 +43,29 @@ struct _EmpathyConfClass {
        GObjectClass parent_class;
 };
 
+#define EMPATHY_PREFS_PATH "/apps/empathy"
+#define EMPATHY_PREFS_SOUNDS_FOR_MESSAGES          EMPATHY_PREFS_PATH "/notifications/sounds_for_messages"
+#define EMPATHY_PREFS_SOUNDS_WHEN_AWAY             EMPATHY_PREFS_PATH "/notifications/sounds_when_away"
+#define EMPATHY_PREFS_SOUNDS_WHEN_BUSY             EMPATHY_PREFS_PATH "/notifications/sounds_when_busy"
+#define EMPATHY_PREFS_POPUPS_WHEN_AVAILABLE        EMPATHY_PREFS_PATH "/notifications/popups_when_available"
+#define EMPATHY_PREFS_CHAT_SHOW_SMILEYS            EMPATHY_PREFS_PATH "/conversation/graphical_smileys"
+#define EMPATHY_PREFS_CHAT_THEME                   EMPATHY_PREFS_PATH "/conversation/theme"
+#define EMPATHY_PREFS_CHAT_THEME_CHAT_ROOM         EMPATHY_PREFS_PATH "/conversation/theme_chat_room"
+#define EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES EMPATHY_PREFS_PATH "/conversation/spell_checker_languages"
+#define EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED   EMPATHY_PREFS_PATH "/conversation/spell_checker_enabled"
+#define EMPATHY_PREFS_CHAT_NICK_COMPLETION_CHAR    EMPATHY_PREFS_PATH "/conversation/nick_completion_char"
+#define EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS     EMPATHY_PREFS_PATH "/ui/separate_chat_windows"
+#define EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN        EMPATHY_PREFS_PATH "/ui/main_window_hidden"
+#define EMPATHY_PREFS_UI_AVATAR_DIRECTORY          EMPATHY_PREFS_PATH "/ui/avatar_directory"
+#define EMPATHY_PREFS_UI_SHOW_AVATARS              EMPATHY_PREFS_PATH "/ui/show_avatars"
+#define EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST      EMPATHY_PREFS_PATH "/ui/compact_contact_list"
+#define EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE        EMPATHY_PREFS_PATH "/contacts/show_offline"
+#define EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM      EMPATHY_PREFS_PATH "/contacts/sort_criterium"
+#define EMPATHY_PREFS_HINTS_CLOSE_MAIN_WINDOW      EMPATHY_PREFS_PATH "/hints/close_main_window"
+#define EMPATHY_PREFS_SALUT_ACCOUNT_CREATED        EMPATHY_PREFS_PATH "/accounts/salut_created"
+#define EMPATHY_PREFS_USE_NM                       EMPATHY_PREFS_PATH "/use_nm"
+#define EMPATHY_PREFS_AUTOCONNECT                  EMPATHY_PREFS_PATH "/autoconnect"
+
 typedef void (*EmpathyConfNotifyFunc) (EmpathyConf  *conf, 
                                      const gchar *key,
                                      gpointer     user_data);
index 007e6947653bc4d02cedc63f91724c40d3b31cc8..909e2316258665f79054a59dc99e088fc9c3c46e 100644 (file)
@@ -51,7 +51,6 @@
 #include "empathy-images.h"
 #include "empathy-ui-utils.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 
 #define DEBUG_DOMAIN "GroupChat"
 
@@ -90,11 +89,6 @@ static void          group_chat_members_changed_cb       (EmpathyTpChatroom *tp_
                                                          gchar             *message,
                                                          gboolean           is_member,
                                                          EmpathyGroupChat  *chat);
-static void          group_chat_topic_entry_activate_cb  (GtkWidget         *entry,
-                                                         GtkDialog         *dialog);
-static void          group_chat_topic_response_cb        (GtkWidget         *dialog,
-                                                         gint               response,                        
-                                                         EmpathyGroupChat  *chat);
 static const gchar * group_chat_get_name                 (EmpathyChat       *chat);
 static gchar *       group_chat_get_tooltip              (EmpathyChat       *chat);
 static const gchar * group_chat_get_status_icon_name     (EmpathyChat       *chat);
@@ -224,25 +218,58 @@ empathy_group_chat_set_show_contacts (EmpathyGroupChat *chat,
        }
 }
 
+static void
+group_chat_topic_response_cb (GtkWidget        *dialog,
+                             gint              response,
+                             EmpathyGroupChat *chat)
+{
+       if (response == GTK_RESPONSE_OK) {
+               GtkWidget   *entry;
+               const gchar *topic;
+
+               entry = g_object_get_data (G_OBJECT (dialog), "entry");
+               topic = gtk_entry_get_text (GTK_ENTRY (entry));
+               
+               if (!G_STR_EMPTY (topic)) {
+                       EmpathyGroupChatPriv *priv;
+                       GValue                value = {0, };
+
+                       priv = GET_PRIV (chat);
+
+                       g_value_init (&value, G_TYPE_STRING);
+                       g_value_set_string (&value, topic);
+                       empathy_tp_chat_set_property (EMPATHY_TP_CHAT (priv->tp_chat),
+                                                     "subject", &value);
+                       g_value_unset (&value);
+               }
+       }
+
+       gtk_widget_destroy (dialog);
+}
+
+static void
+group_chat_topic_entry_activate_cb (GtkWidget *entry,
+                                   GtkDialog *dialog)
+{
+       gtk_dialog_response (dialog, GTK_RESPONSE_OK);
+}
+
 void
 empathy_group_chat_set_topic (EmpathyGroupChat *chat)
 {
        EmpathyGroupChatPriv *priv;
-       EmpathyChatWindow    *chat_window;
-       GtkWidget           *chat_dialog;
-       GtkWidget           *dialog;
-       GtkWidget           *entry;
-       GtkWidget           *hbox;
-       const gchar         *topic;
-
-       g_return_if_fail (EMPATHY_IS_GROUP_CHAT (chat));
+       GtkWindow            *parent;
+       GtkWidget            *dialog;
+       GtkWidget            *entry;
+       GtkWidget            *hbox;
+       const gchar          *topic;
 
        priv = GET_PRIV (chat);
 
-       chat_window = empathy_chat_get_window (EMPATHY_CHAT (chat));
-       chat_dialog = empathy_chat_window_get_dialog (chat_window);
+       g_return_if_fail (EMPATHY_IS_GROUP_CHAT (chat));
 
-       dialog = gtk_message_dialog_new (GTK_WINDOW (chat_dialog),
+       parent = empathy_get_toplevel_window (empathy_chat_get_widget (EMPATHY_CHAT (chat)));
+       dialog = gtk_message_dialog_new (GTK_WINDOW (parent),
                                         0,
                                         GTK_MESSAGE_QUESTION,
                                         GTK_BUTTONS_OK_CANCEL,
@@ -367,42 +394,6 @@ group_chat_members_changed_cb (EmpathyTpChatroom *tp_chat,
        }
 }
 
-static void
-group_chat_topic_entry_activate_cb (GtkWidget *entry,
-                                   GtkDialog *dialog)
-{
-       gtk_dialog_response (dialog, GTK_RESPONSE_OK);
-}
-
-static void
-group_chat_topic_response_cb (GtkWidget       *dialog,
-                             gint             response,                              
-                             EmpathyGroupChat *chat)
-{
-       if (response == GTK_RESPONSE_OK) {
-               GtkWidget   *entry;
-               const gchar *topic;
-
-               entry = g_object_get_data (G_OBJECT (dialog), "entry");
-               topic = gtk_entry_get_text (GTK_ENTRY (entry));
-               
-               if (!G_STR_EMPTY (topic)) {
-                       EmpathyGroupChatPriv *priv;
-                       GValue                value = {0, };
-
-                       priv = GET_PRIV (chat);
-
-                       g_value_init (&value, G_TYPE_STRING);
-                       g_value_set_string (&value, topic);
-                       empathy_tp_chat_set_property (EMPATHY_TP_CHAT (priv->tp_chat),
-                                                     "subject", &value);
-                       g_value_unset (&value);
-               }
-       }
-
-       gtk_widget_destroy (dialog);
-}
-
 static const gchar *
 group_chat_get_name (EmpathyChat *chat)
 {
diff --git a/libempathy-gtk/empathy-main-window.c b/libempathy-gtk/empathy-main-window.c
deleted file mode 100644 (file)
index c447c47..0000000
+++ /dev/null
@@ -1,1166 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2002-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include <config.h>
-
-#include <sys/stat.h>
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <glib/gi18n.h>
-
-#include <libempathy/empathy-contact.h>
-#include <libempathy/empathy-debug.h>
-#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-chatroom-manager.h>
-#include <libempathy/empathy-chatroom.h>
-#include <libempathy/empathy-contact-list.h>
-#include <libempathy/empathy-contact-manager.h>
-#include <libempathy/empathy-contact-factory.h>
-#include <libempathy/empathy-status-presets.h>
-
-#include "empathy-main-window.h"
-#include "empathy-contact-dialogs.h"
-#include "ephy-spinner.h"
-#include "empathy-contact-list-store.h"
-#include "empathy-contact-list-view.h"
-#include "empathy-presence-chooser.h"
-#include "empathy-ui-utils.h"
-#include "empathy-geometry.h"
-#include "empathy-conf.h"
-#include "empathy-preferences.h"
-#include "empathy-accounts-dialog.h"
-#include "empathy-about-dialog.h"
-#include "empathy-new-chatroom-dialog.h"
-#include "empathy-chatrooms-window.h"
-#include "empathy-log-window.h"
-#include "empathy-new-message-dialog.h"
-#include "empathy-gtk-enum-types.h"
-
-#define DEBUG_DOMAIN "MainWindow"
-
-/* Minimum width of roster window if something goes wrong. */
-#define MIN_WIDTH 50
-
-/* Accels (menu shortcuts) can be configured and saved */
-#define ACCELS_FILENAME "accels.txt"
-
-/* Name in the geometry file */
-#define GEOMETRY_NAME "main-window"
-
-typedef struct {
-       EmpathyContactListView  *list_view;
-       EmpathyContactListStore *list_store;
-       MissionControl          *mc;
-       EmpathyChatroomManager  *chatroom_manager;
-
-       GtkWidget              *window;
-       GtkWidget              *main_vbox;
-       GtkWidget              *throbber;
-       GtkWidget              *presence_toolbar;
-       GtkWidget              *presence_chooser;
-       GtkWidget              *errors_vbox;
-
-       GtkWidget              *room;
-       GtkWidget              *room_menu;
-       GtkWidget              *room_sep;
-       GtkWidget              *room_join_favorites;
-       GtkWidget              *edit_context;
-       GtkWidget              *edit_context_separator;
-
-       guint                   size_timeout_id;
-       GHashTable             *errors;
-
-       /* Widgets that are enabled when there is... */
-       GList                  *widgets_connected;      /* ... connected accounts */
-       GList                  *widgets_disconnected;   /* ... disconnected accounts */
-} EmpathyMainWindow;
-
-static void     main_window_destroy_cb                         (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_favorite_chatroom_menu_setup       (EmpathyMainWindow        *window);
-static void     main_window_favorite_chatroom_menu_added_cb    (EmpathyChatroomManager   *manager,
-                                                               EmpathyChatroom          *chatroom,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_favorite_chatroom_menu_removed_cb  (EmpathyChatroomManager   *manager,
-                                                               EmpathyChatroom          *chatroom,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem              *menu_item,
-                                                               EmpathyChatroom          *chatroom);
-static void     main_window_favorite_chatroom_menu_update      (EmpathyMainWindow        *window);
-static void     main_window_favorite_chatroom_menu_add         (EmpathyMainWindow        *window,
-                                                               EmpathyChatroom          *chatroom);
-static void     main_window_favorite_chatroom_join             (EmpathyChatroom          *chatroom);
-static void     main_window_chat_quit_cb                       (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_chat_new_message_cb                (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_chat_history_cb                    (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_room_join_new_cb                   (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_room_join_favorites_cb             (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_room_manage_favorites_cb           (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_chat_add_contact_cb                (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_chat_show_offline_cb               (GtkCheckMenuItem         *item,
-                                                               EmpathyMainWindow        *window);
-static gboolean main_window_edit_button_press_event_cb         (GtkWidget                *widget,
-                                                               GdkEventButton           *event,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_edit_accounts_cb                   (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_edit_personal_information_cb       (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_edit_preferences_cb                (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_help_about_cb                      (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_help_contents_cb                   (GtkWidget                *widget,
-                                                               EmpathyMainWindow        *window);
-static gboolean main_window_throbber_button_press_event_cb     (GtkWidget                *throbber_ebox,
-                                                               GdkEventButton           *event,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_status_changed_cb                  (MissionControl           *mc,
-                                                               TpConnectionStatus        status,
-                                                               McPresence                presence,
-                                                               TpConnectionStatusReason  reason,
-                                                               const gchar              *unique_name,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_update_status                      (EmpathyMainWindow        *window);
-static void     main_window_accels_load                        (void);
-static void     main_window_accels_save                        (void);
-static void     main_window_connection_items_setup             (EmpathyMainWindow        *window,
-                                                               GladeXML                 *glade);
-static gboolean main_window_configure_event_timeout_cb         (EmpathyMainWindow        *window);
-static gboolean main_window_configure_event_cb                 (GtkWidget                *widget,
-                                                               GdkEventConfigure        *event,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_notify_show_offline_cb             (EmpathyConf              *conf,
-                                                               const gchar              *key,
-                                                               gpointer                  check_menu_item);
-static void     main_window_notify_show_avatars_cb             (EmpathyConf              *conf,
-                                                               const gchar              *key,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_notify_compact_contact_list_cb     (EmpathyConf              *conf,
-                                                               const gchar              *key,
-                                                               EmpathyMainWindow        *window);
-static void     main_window_notify_sort_criterium_cb           (EmpathyConf              *conf,
-                                                               const gchar              *key,
-                                                               EmpathyMainWindow        *window);
-
-GtkWidget *
-empathy_main_window_show (void)
-{
-       static EmpathyMainWindow *window = NULL;
-       EmpathyContactList       *list_iface;
-       GladeXML                 *glade;
-       EmpathyConf               *conf;
-       GtkWidget                *sw;
-       GtkWidget                *show_offline_widget;
-       GtkWidget                *ebox;
-       GtkToolItem              *item;
-       gboolean                  show_offline;
-       gboolean                  show_avatars;
-       gboolean                  compact_contact_list;
-       gint                      x, y, w, h;
-
-       if (window) {
-               empathy_window_present (GTK_WINDOW (window->window), TRUE);
-               return window->window;
-       }
-
-       window = g_new0 (EmpathyMainWindow, 1);
-
-       /* Set up interface */
-       glade = empathy_glade_get_file ("empathy-main-window.glade",
-                                      "main_window",
-                                      NULL,
-                                      "main_window", &window->window,
-                                      "main_vbox", &window->main_vbox,
-                                      "errors_vbox", &window->errors_vbox,
-                                      "chat_show_offline", &show_offline_widget,
-                                      "room", &window->room,
-                                      "room_sep", &window->room_sep,
-                                      "room_join_favorites", &window->room_join_favorites,
-                                      "edit_context", &window->edit_context,
-                                      "edit_context_separator", &window->edit_context_separator,
-                                      "presence_toolbar", &window->presence_toolbar,
-                                      "roster_scrolledwindow", &sw,
-                                      NULL);
-
-       empathy_glade_connect (glade,
-                             window,
-                             "main_window", "destroy", main_window_destroy_cb,
-                             "main_window", "configure_event", main_window_configure_event_cb,
-                             "chat_quit", "activate", main_window_chat_quit_cb,
-                             "chat_new_message", "activate", main_window_chat_new_message_cb,
-                             "chat_history", "activate", main_window_chat_history_cb,
-                             "room_join_new", "activate", main_window_room_join_new_cb,
-                             "room_join_favorites", "activate", main_window_room_join_favorites_cb,
-                             "room_manage_favorites", "activate", main_window_room_manage_favorites_cb,
-                             "chat_add_contact", "activate", main_window_chat_add_contact_cb,
-                             "chat_show_offline", "toggled", main_window_chat_show_offline_cb,
-                             "edit", "button-press-event", main_window_edit_button_press_event_cb,
-                             "edit_accounts", "activate", main_window_edit_accounts_cb,
-                             "edit_personal_information", "activate", main_window_edit_personal_information_cb,
-                             "edit_preferences", "activate", main_window_edit_preferences_cb,
-                             "help_about", "activate", main_window_help_about_cb,
-                             "help_contents", "activate", main_window_help_contents_cb,
-                             NULL);
-
-       /* Set up connection related widgets. */
-       main_window_connection_items_setup (window, glade);
-       g_object_unref (glade);
-
-       window->mc = empathy_mission_control_new ();
-       dbus_g_proxy_connect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged",
-                                    G_CALLBACK (main_window_status_changed_cb),
-                                    window, NULL);
-
-       window->errors = g_hash_table_new_full (empathy_account_hash,
-                                               empathy_account_equal,
-                                               g_object_unref,
-                                               NULL);
-
-       /* Set up menu */
-       main_window_favorite_chatroom_menu_setup (window);
-
-       gtk_widget_hide (window->edit_context);
-       gtk_widget_hide (window->edit_context_separator);
-
-       /* Set up presence chooser */
-       window->presence_chooser = empathy_presence_chooser_new ();
-       gtk_widget_show (window->presence_chooser);
-       item = gtk_tool_item_new ();
-       gtk_widget_show (GTK_WIDGET (item));
-       gtk_container_add (GTK_CONTAINER (item), window->presence_chooser);
-       gtk_tool_item_set_is_important (item, TRUE);
-       gtk_tool_item_set_expand (item, TRUE);
-       gtk_toolbar_insert (GTK_TOOLBAR (window->presence_toolbar), item, -1);
-
-       /* Set up the throbber */
-       ebox = gtk_event_box_new ();
-       gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE);
-       gtk_widget_set_tooltip_text (ebox, _("Show and edit accounts"));
-       g_signal_connect (ebox,
-                         "button-press-event",
-                         G_CALLBACK (main_window_throbber_button_press_event_cb),
-                         window);
-       gtk_widget_show (ebox);
-
-       window->throbber = ephy_spinner_new ();
-       ephy_spinner_set_size (EPHY_SPINNER (window->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR);
-       gtk_container_add (GTK_CONTAINER (ebox), window->throbber);
-       gtk_widget_show (window->throbber);
-
-       item = gtk_tool_item_new ();
-       gtk_container_add (GTK_CONTAINER (item), ebox);
-       gtk_toolbar_insert (GTK_TOOLBAR (window->presence_toolbar), item, -1);
-       gtk_widget_show (GTK_WIDGET (item));
-
-       /* Set up contact list. */
-       empathy_status_presets_get_all ();
-
-       list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_new ());
-       window->list_store = empathy_contact_list_store_new (list_iface);
-       window->list_view = empathy_contact_list_view_new (window->list_store,
-                                                          EMPATHY_CONTACT_LIST_FEATURE_ALL);
-       g_object_unref (list_iface);
-
-       gtk_widget_show (GTK_WIDGET (window->list_view));
-       gtk_container_add (GTK_CONTAINER (sw),
-                          GTK_WIDGET (window->list_view));
-
-       /* Load user-defined accelerators. */
-       main_window_accels_load ();
-
-       /* Set window size. */
-       empathy_geometry_load (GEOMETRY_NAME, &x, &y, &w, &h);
-
-       if (w >= 1 && h >= 1) {
-               /* Use the defaults from the glade file if we
-                * don't have good w, h geometry.
-                */
-               empathy_debug (DEBUG_DOMAIN, "Configuring window default size w:%d, h:%d", w, h);
-               gtk_window_set_default_size (GTK_WINDOW (window->window), w, h);
-       }
-
-       if (x >= 0 && y >= 0) {
-               /* Let the window manager position it if we
-                * don't have good x, y coordinates.
-                */
-               empathy_debug (DEBUG_DOMAIN, "Configuring window default position x:%d, y:%d", x, y);
-               gtk_window_move (GTK_WINDOW (window->window), x, y);
-       }
-
-       conf = empathy_conf_get ();
-       
-       /* Show offline ? */
-       empathy_conf_get_bool (conf,
-                             EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE,
-                             &show_offline);
-       empathy_conf_notify_add (conf,
-                               EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE,
-                               main_window_notify_show_offline_cb,
-                               show_offline_widget);
-
-       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (show_offline_widget),
-                                       show_offline);
-
-       /* Show avatars ? */
-       empathy_conf_get_bool (conf,
-                             EMPATHY_PREFS_UI_SHOW_AVATARS,
-                             &show_avatars);
-       empathy_conf_notify_add (conf,
-                               EMPATHY_PREFS_UI_SHOW_AVATARS,
-                               (EmpathyConfNotifyFunc) main_window_notify_show_avatars_cb,
-                               window);
-       empathy_contact_list_store_set_show_avatars (window->list_store, show_avatars);
-
-       /* Is compact ? */
-       empathy_conf_get_bool (conf,
-                             EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
-                             &compact_contact_list);
-       empathy_conf_notify_add (conf,
-                               EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
-                               (EmpathyConfNotifyFunc) main_window_notify_compact_contact_list_cb,
-                               window);
-       empathy_contact_list_store_set_is_compact (window->list_store, compact_contact_list);
-
-       /* Sort criterium */
-       empathy_conf_notify_add (conf,
-                               EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
-                               (EmpathyConfNotifyFunc) main_window_notify_sort_criterium_cb,
-                               window);
-       main_window_notify_sort_criterium_cb (conf,
-                                             EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
-                                             window);
-
-       main_window_update_status (window);
-
-       return window->window;
-}
-
-static void
-main_window_destroy_cb (GtkWidget         *widget,
-                       EmpathyMainWindow *window)
-{
-       /* Save user-defined accelerators. */
-       main_window_accels_save ();
-
-       dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged",
-                                       G_CALLBACK (main_window_status_changed_cb),
-                                       window);
-
-       if (window->size_timeout_id) {
-               g_source_remove (window->size_timeout_id);
-       }
-
-       g_list_free (window->widgets_connected);
-       g_list_free (window->widgets_disconnected);
-
-       g_object_unref (window->mc);
-       g_object_unref (window->list_store);
-       g_hash_table_destroy (window->errors);
-
-       g_free (window);
-}
-
-static void
-main_window_favorite_chatroom_menu_setup (EmpathyMainWindow *window)
-{
-       GList *chatrooms, *l;
-
-       window->chatroom_manager = empathy_chatroom_manager_new ();
-       chatrooms = empathy_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
-       window->room_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (window->room));
-
-       for (l = chatrooms; l; l = l->next) {
-               main_window_favorite_chatroom_menu_add (window, l->data);
-       }
-
-       if (!chatrooms) {
-               gtk_widget_hide (window->room_sep);
-       }
-
-       gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL);
-
-       g_signal_connect (window->chatroom_manager, "chatroom-added",
-                         G_CALLBACK (main_window_favorite_chatroom_menu_added_cb),
-                         window);
-       g_signal_connect (window->chatroom_manager, "chatroom-removed",
-                         G_CALLBACK (main_window_favorite_chatroom_menu_removed_cb),
-                         window);
-
-       g_list_free (chatrooms);
-}
-
-static void
-main_window_favorite_chatroom_menu_added_cb (EmpathyChatroomManager *manager,
-                                            EmpathyChatroom        *chatroom,
-                                            EmpathyMainWindow     *window)
-{
-       main_window_favorite_chatroom_menu_add (window, chatroom);
-       gtk_widget_show (window->room_sep);
-       gtk_widget_set_sensitive (window->room_join_favorites, TRUE);
-}
-
-static void
-main_window_favorite_chatroom_menu_removed_cb (EmpathyChatroomManager *manager,
-                                              EmpathyChatroom        *chatroom,
-                                              EmpathyMainWindow     *window)
-{
-       GtkWidget *menu_item;
-
-       menu_item = g_object_get_data (G_OBJECT (chatroom), "menu_item");
-
-       g_object_set_data (G_OBJECT (chatroom), "menu_item", NULL);
-       gtk_widget_destroy (menu_item);
-
-       main_window_favorite_chatroom_menu_update (window);
-}
-
-static void
-main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem    *menu_item,
-                                               EmpathyChatroom *chatroom)
-{
-       main_window_favorite_chatroom_join (chatroom);
-}
-
-static void
-main_window_favorite_chatroom_menu_update (EmpathyMainWindow *window)
-{
-       GList *chatrooms;
-
-       chatrooms = empathy_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
-
-       if (chatrooms) {
-               gtk_widget_show (window->room_sep);
-       } else {
-               gtk_widget_hide (window->room_sep);
-       }
-
-       gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL);
-       g_list_free (chatrooms);
-}
-
-static void
-main_window_favorite_chatroom_menu_add (EmpathyMainWindow *window,
-                                       EmpathyChatroom    *chatroom)
-{
-       GtkWidget   *menu_item;
-       const gchar *name;
-
-       if (g_object_get_data (G_OBJECT (chatroom), "menu_item")) {
-               return;
-       }
-
-       name = empathy_chatroom_get_name (chatroom);
-       menu_item = gtk_menu_item_new_with_label (name);
-
-       g_object_set_data (G_OBJECT (chatroom), "menu_item", menu_item);
-       g_signal_connect (menu_item, "activate",
-                         G_CALLBACK (main_window_favorite_chatroom_menu_activate_cb),
-                         chatroom);
-
-       gtk_menu_shell_insert (GTK_MENU_SHELL (window->room_menu),
-                              menu_item, 3);
-
-       gtk_widget_show (menu_item);
-}
-
-static void
-main_window_favorite_chatroom_join (EmpathyChatroom *chatroom)
-{
-       MissionControl *mc;
-       McAccount      *account;
-       const gchar    *room;
-
-       mc = empathy_mission_control_new ();
-       account = empathy_chatroom_get_account (chatroom);
-       room = empathy_chatroom_get_room (chatroom);
-
-       empathy_debug (DEBUG_DOMAIN, "Requesting channel for '%s'", room);
-
-       mission_control_request_channel_with_string_handle (mc,
-                                                           account,
-                                                           TP_IFACE_CHANNEL_TYPE_TEXT,
-                                                           room,
-                                                           TP_HANDLE_TYPE_ROOM,
-                                                           NULL, NULL);        
-       g_object_unref (mc);
-}
-
-static void
-main_window_chat_quit_cb (GtkWidget         *widget,
-                         EmpathyMainWindow *window)
-{
-       gtk_main_quit ();
-}
-
-static void
-main_window_chat_new_message_cb (GtkWidget         *widget,
-                                EmpathyMainWindow *window)
-{
-       empathy_new_message_dialog_show (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_chat_history_cb (GtkWidget         *widget,
-                            EmpathyMainWindow *window)
-{
-       empathy_log_window_show (NULL, NULL, FALSE, GTK_WINDOW (window->window));
-}
-
-static void
-main_window_room_join_new_cb (GtkWidget         *widget,
-                             EmpathyMainWindow *window)
-{
-       empathy_new_chatroom_dialog_show (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_room_join_favorites_cb (GtkWidget         *widget,
-                                   EmpathyMainWindow *window)
-{
-       GList *chatrooms, *l;
-
-       chatrooms = empathy_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
-       for (l = chatrooms; l; l = l->next) {
-               main_window_favorite_chatroom_join (l->data);
-       }
-       g_list_free (chatrooms);
-}
-
-static void
-main_window_room_manage_favorites_cb (GtkWidget         *widget,
-                                     EmpathyMainWindow *window)
-{
-       empathy_chatrooms_window_show (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_chat_add_contact_cb (GtkWidget         *widget,
-                                EmpathyMainWindow *window)
-{
-       empathy_new_contact_dialog_show (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_chat_show_offline_cb (GtkCheckMenuItem  *item,
-                                 EmpathyMainWindow *window)
-{
-       gboolean current;
-
-       current = gtk_check_menu_item_get_active (item);
-
-       empathy_conf_set_bool (empathy_conf_get (),
-                             EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE,
-                             current);
-
-       /* Turn off sound just while we alter the contact list. */
-       // FIXME: empathy_sound_set_enabled (FALSE);
-       empathy_contact_list_store_set_show_offline (window->list_store, current);
-       //empathy_sound_set_enabled (TRUE);
-}
-
-static gboolean
-main_window_edit_button_press_event_cb (GtkWidget         *widget,
-                                       GdkEventButton    *event,
-                                       EmpathyMainWindow *window)
-{
-       EmpathyContact *contact;
-       gchar         *group;
-
-       if (!event->button == 1) {
-               return FALSE;
-       }
-
-       group = empathy_contact_list_view_get_selected_group (window->list_view);
-       if (group) {
-               GtkMenuItem *item;
-               GtkWidget   *label;
-               GtkWidget   *submenu;
-
-               item = GTK_MENU_ITEM (window->edit_context);
-               label = gtk_bin_get_child (GTK_BIN (item));
-               gtk_label_set_text (GTK_LABEL (label), _("Group"));
-
-               gtk_widget_show (window->edit_context);
-               gtk_widget_show (window->edit_context_separator);
-
-               submenu = empathy_contact_list_view_get_group_menu (window->list_view);
-               gtk_menu_item_set_submenu (item, submenu);
-
-               g_free (group);
-
-               return FALSE;
-       }
-
-       contact = empathy_contact_list_view_get_selected (window->list_view);
-       if (contact) {
-               GtkMenuItem *item;
-               GtkWidget   *label;
-               GtkWidget   *submenu;
-
-               item = GTK_MENU_ITEM (window->edit_context);
-               label = gtk_bin_get_child (GTK_BIN (item));
-               gtk_label_set_text (GTK_LABEL (label), _("Contact"));
-
-               gtk_widget_show (window->edit_context);
-               gtk_widget_show (window->edit_context_separator);
-
-               submenu = empathy_contact_list_view_get_contact_menu (window->list_view,
-                                                                    contact);
-               gtk_menu_item_set_submenu (item, submenu);
-
-               g_object_unref (contact);
-
-               return FALSE;
-       }
-
-       gtk_widget_hide (window->edit_context);
-       gtk_widget_hide (window->edit_context_separator);
-
-       return FALSE;
-}
-
-static void
-main_window_edit_accounts_cb (GtkWidget         *widget,
-                             EmpathyMainWindow *window)
-{
-       empathy_accounts_dialog_show (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_edit_personal_information_cb (GtkWidget         *widget,
-                                         EmpathyMainWindow *window)
-{
-       GSList *accounts;
-
-       accounts = mission_control_get_online_connections (window->mc, NULL);
-       if (accounts) {
-               EmpathyContactFactory *factory;
-               EmpathyContact        *contact;
-               McAccount             *account;
-
-               account = accounts->data;
-               factory = empathy_contact_factory_new ();
-               contact = empathy_contact_factory_get_user (factory, account);
-               empathy_contact_run_until_ready (contact,
-                                                EMPATHY_CONTACT_READY_HANDLE |
-                                                EMPATHY_CONTACT_READY_ID,
-                                                NULL);
-
-               empathy_contact_information_dialog_show (contact,
-                                                        GTK_WINDOW (window->window),
-                                                        TRUE, TRUE);
-
-               g_slist_foreach (accounts, (GFunc) g_object_unref, NULL);
-               g_slist_free (accounts);
-               g_object_unref (factory);
-               g_object_unref (contact);
-       }
-}
-
-static void
-main_window_edit_preferences_cb (GtkWidget         *widget,
-                                EmpathyMainWindow *window)
-{
-       empathy_preferences_show (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_help_about_cb (GtkWidget         *widget,
-                          EmpathyMainWindow *window)
-{
-       empathy_about_dialog_new (GTK_WINDOW (window->window));
-}
-
-static void
-main_window_help_contents_cb (GtkWidget         *widget,
-                             EmpathyMainWindow *window)
-{
-       //empathy_help_show ();
-}
-
-static gboolean
-main_window_throbber_button_press_event_cb (GtkWidget         *throbber_ebox,
-                                           GdkEventButton    *event,
-                                           EmpathyMainWindow *window)
-{
-       if (event->type != GDK_BUTTON_PRESS ||
-           event->button != 1) {
-               return FALSE;
-       }
-
-       empathy_accounts_dialog_show (GTK_WINDOW (window->window));
-
-       return FALSE;
-}
-
-static void
-main_window_error_edit_clicked_cb (GtkButton         *button,
-                                  EmpathyMainWindow *window)
-{
-       McAccount *account;
-       GtkWidget *error_widget;
-
-       empathy_accounts_dialog_show (GTK_WINDOW (window->window));
-
-       account = g_object_get_data (G_OBJECT (button), "account");
-       error_widget = g_hash_table_lookup (window->errors, account);
-       gtk_widget_destroy (error_widget);
-       g_hash_table_remove (window->errors, account);
-}
-
-static void
-main_window_error_clear_clicked_cb (GtkButton         *button,
-                                   EmpathyMainWindow *window)
-{
-       McAccount *account;
-       GtkWidget *error_widget;
-
-       account = g_object_get_data (G_OBJECT (button), "account");
-       error_widget = g_hash_table_lookup (window->errors, account);
-       gtk_widget_destroy (error_widget);
-       g_hash_table_remove (window->errors, account);
-}
-
-static void
-main_window_error_display (EmpathyMainWindow *window,
-                          McAccount         *account,
-                          const gchar       *message)
-{
-       GtkWidget *child;
-       GtkWidget *table;
-       GtkWidget *image;
-       GtkWidget *button_edit;
-       GtkWidget *alignment;
-       GtkWidget *hbox;
-       GtkWidget *label;
-       GtkWidget *fixed;
-       GtkWidget *vbox;
-       GtkWidget *button_close;
-       gchar     *str;
-
-       child = g_hash_table_lookup (window->errors, account);
-       if (child) {
-               label = g_object_get_data (G_OBJECT (child), "label");
-
-               /* Just set the latest error and return */
-               str = g_markup_printf_escaped ("<b>%s</b>\n%s",
-                                              mc_account_get_display_name (account),
-                                              message);
-               gtk_label_set_markup (GTK_LABEL (label), str);
-               g_free (str);
-
-               return;
-       }
-
-       child = gtk_vbox_new (FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (window->errors_vbox), child, FALSE, TRUE, 0);
-       gtk_container_set_border_width (GTK_CONTAINER (child), 6);
-       gtk_widget_show (child);
-
-       table = gtk_table_new (2, 4, FALSE);
-       gtk_widget_show (table);
-       gtk_box_pack_start (GTK_BOX (child), table, TRUE, TRUE, 0);
-       gtk_table_set_row_spacings (GTK_TABLE (table), 12);
-       gtk_table_set_col_spacings (GTK_TABLE (table), 6);
-
-       image = gtk_image_new_from_stock (GTK_STOCK_DISCONNECT, GTK_ICON_SIZE_MENU);
-       gtk_widget_show (image);
-       gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 2,
-                         (GtkAttachOptions) (GTK_FILL),
-                         (GtkAttachOptions) (GTK_FILL), 0, 0);
-       gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
-
-       button_edit = gtk_button_new ();
-       gtk_widget_show (button_edit);
-       gtk_table_attach (GTK_TABLE (table), button_edit, 1, 2, 1, 2,
-                         (GtkAttachOptions) (GTK_FILL),
-                         (GtkAttachOptions) (0), 0, 0);
-
-       alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
-       gtk_widget_show (alignment);
-       gtk_container_add (GTK_CONTAINER (button_edit), alignment);
-
-       hbox = gtk_hbox_new (FALSE, 2);
-       gtk_widget_show (hbox);
-       gtk_container_add (GTK_CONTAINER (alignment), hbox);
-
-       image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
-       gtk_widget_show (image);
-       gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
-
-       label = gtk_label_new_with_mnemonic (_("_Edit account"));
-       gtk_widget_show (label);
-       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
-       fixed = gtk_fixed_new ();
-       gtk_widget_show (fixed);
-       gtk_table_attach (GTK_TABLE (table), fixed, 2, 3, 1, 2,
-                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-                         (GtkAttachOptions) (GTK_FILL), 0, 0);
-
-       vbox = gtk_vbox_new (FALSE, 6);
-       gtk_widget_show (vbox);
-       gtk_table_attach (GTK_TABLE (table), vbox, 3, 4, 0, 2,
-                         (GtkAttachOptions) (GTK_FILL),
-                         (GtkAttachOptions) (GTK_FILL), 0, 0);
-
-       button_close = gtk_button_new ();
-       gtk_widget_show (button_close);
-       gtk_box_pack_start (GTK_BOX (vbox), button_close, FALSE, FALSE, 0);
-       gtk_button_set_relief (GTK_BUTTON (button_close), GTK_RELIEF_NONE);
-
-
-       image = gtk_image_new_from_stock ("gtk-close", GTK_ICON_SIZE_MENU);
-       gtk_widget_show (image);
-       gtk_container_add (GTK_CONTAINER (button_close), image);
-
-       label = gtk_label_new ("");
-       gtk_widget_show (label);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 3, 0, 1,
-                         (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL),
-                         (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL), 0, 0);
-       gtk_widget_set_size_request (label, 175, -1);
-       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-       gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
-
-       str = g_markup_printf_escaped ("<b>%s</b>\n%s",
-                                      mc_account_get_display_name (account),
-                                      message);
-       gtk_label_set_markup (GTK_LABEL (label), str);
-       g_free (str);
-
-       g_object_set_data (G_OBJECT (child), "label", label);
-       g_object_set_data_full (G_OBJECT (button_edit),
-                               "account", g_object_ref (account),
-                               g_object_unref);
-       g_object_set_data_full (G_OBJECT (button_close),
-                               "account", g_object_ref (account),
-                               g_object_unref);
-
-       g_signal_connect (button_edit, "clicked",
-                         G_CALLBACK (main_window_error_edit_clicked_cb),
-                         window);
-
-       g_signal_connect (button_close, "clicked",
-                         G_CALLBACK (main_window_error_clear_clicked_cb),
-                         window);
-
-       gtk_widget_show (window->errors_vbox);
-
-       g_hash_table_insert (window->errors, g_object_ref (account), child);
-}
-
-static void
-main_window_status_changed_cb (MissionControl           *mc,
-                              TpConnectionStatus        status,
-                              McPresence                presence,
-                              TpConnectionStatusReason  reason,
-                              const gchar              *unique_name,
-                              EmpathyMainWindow        *window)
-{
-       McAccount *account;
-
-       main_window_update_status (window);
-
-       account = mc_account_lookup (unique_name);
-
-       if (status == TP_CONNECTION_STATUS_DISCONNECTED &&
-           reason > TP_CONNECTION_STATUS_REASON_REQUESTED) {
-               const gchar *message;
-
-               switch (reason) {
-               case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
-                       message = _("Network error");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
-                       message = _("Authentication failed");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
-                       message = _("Encryption error");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
-                       message = _("Name in use");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
-                       message = _("Certificate not provided");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
-                       message = _("Certificate untrusted");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
-                       message = _("Certificate expired");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
-                       message = _("Certificate not activated");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
-                       message = _("Certificate hostname mismatch");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
-                       message = _("Certificate fingerprint mismatch");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
-                       message = _("Certificate self signed");
-                       break;
-               case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
-                       message = _("Certificate error");
-                       break;
-               default:
-                       message = _("Unknown error");
-                       break;
-               }
-
-               main_window_error_display (window, account, message);
-       }
-
-       if (status == TP_CONNECTION_STATUS_CONNECTED) {
-               GtkWidget *error_widget;
-
-               /* Account connected without error, remove error message if any */
-               error_widget = g_hash_table_lookup (window->errors, account);
-               if (error_widget) {
-                       gtk_widget_destroy (error_widget);
-                       g_hash_table_remove (window->errors, account);
-               }
-       }
-
-       g_object_unref (account);
-}
-
-static void
-main_window_update_status (EmpathyMainWindow *window)
-{
-       GList *accounts, *l;
-       guint  connected = 0;
-       guint  connecting = 0;
-       guint  disconnected = 0;
-
-       /* Count number of connected/connecting/disconnected accounts */
-       accounts = mc_accounts_list (); 
-       for (l = accounts; l; l = l->next) {
-               McAccount *account;
-               guint      status;
-
-               account = l->data;
-
-               status = mission_control_get_connection_status (window->mc,
-                                                               account,
-                                                               NULL);
-
-               if (status == 0) {
-                       connected++;
-               } else if (status == 1) {
-                       connecting++;
-               } else if (status == 2) {
-                       disconnected++;
-               }
-
-               g_object_unref (account);
-       }
-       g_list_free (accounts);
-
-       /* Update the spinner state */
-       if (connecting > 0) {
-               ephy_spinner_start (EPHY_SPINNER (window->throbber));
-       } else {
-               ephy_spinner_stop (EPHY_SPINNER (window->throbber));
-       }
-
-       /* Update widgets sensibility */
-       for (l = window->widgets_connected; l; l = l->next) {
-               gtk_widget_set_sensitive (l->data, (connected > 0));
-       }
-
-       for (l = window->widgets_disconnected; l; l = l->next) {
-               gtk_widget_set_sensitive (l->data, (disconnected > 0));
-       }
-}
-
-/*
- * Accels
- */
-static void
-main_window_accels_load (void)
-{
-       gchar *filename;
-
-       filename = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, ACCELS_FILENAME, NULL);
-       if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
-               empathy_debug (DEBUG_DOMAIN, "Loading from:'%s'", filename);
-               gtk_accel_map_load (filename);
-       }
-
-       g_free (filename);
-}
-
-static void
-main_window_accels_save (void)
-{
-       gchar *dir;
-       gchar *file_with_path;
-
-       dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
-       g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
-       file_with_path = g_build_filename (dir, ACCELS_FILENAME, NULL);
-       g_free (dir);
-
-       empathy_debug (DEBUG_DOMAIN, "Saving to:'%s'", file_with_path);
-       gtk_accel_map_save (file_with_path);
-
-       g_free (file_with_path);
-}
-
-static void
-main_window_connection_items_setup (EmpathyMainWindow *window,
-                                   GladeXML          *glade)
-{
-       GList         *list;
-       GtkWidget     *w;
-       gint           i;
-       const gchar *widgets_connected[] = {
-               "room",
-               "chat_new_message",
-               "chat_add_contact",
-               "edit_personal_information"
-       };
-       const gchar *widgets_disconnected[] = {
-       };
-
-       for (i = 0, list = NULL; i < G_N_ELEMENTS (widgets_connected); i++) {
-               w = glade_xml_get_widget (glade, widgets_connected[i]);
-               list = g_list_prepend (list, w);
-       }
-
-       window->widgets_connected = list;
-
-       for (i = 0, list = NULL; i < G_N_ELEMENTS (widgets_disconnected); i++) {
-               w = glade_xml_get_widget (glade, widgets_disconnected[i]);
-               list = g_list_prepend (list, w);
-       }
-
-       window->widgets_disconnected = list;
-}
-
-static gboolean
-main_window_configure_event_timeout_cb (EmpathyMainWindow *window)
-{
-       gint x, y, w, h;
-
-       gtk_window_get_size (GTK_WINDOW (window->window), &w, &h);
-       gtk_window_get_position (GTK_WINDOW (window->window), &x, &y);
-
-       empathy_geometry_save (GEOMETRY_NAME, x, y, w, h);
-
-       window->size_timeout_id = 0;
-
-       return FALSE;
-}
-
-static gboolean
-main_window_configure_event_cb (GtkWidget         *widget,
-                               GdkEventConfigure *event,
-                               EmpathyMainWindow *window)
-{
-       if (window->size_timeout_id) {
-               g_source_remove (window->size_timeout_id);
-       }
-
-       window->size_timeout_id = g_timeout_add_seconds (1,
-                                                        (GSourceFunc) main_window_configure_event_timeout_cb,
-                                                        window);
-
-       return FALSE;
-}
-
-static void
-main_window_notify_show_offline_cb (EmpathyConf  *conf,
-                                   const gchar *key,
-                                   gpointer     check_menu_item)
-{
-       gboolean show_offline;
-
-       if (empathy_conf_get_bool (conf, key, &show_offline)) {
-               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (check_menu_item),
-                                               show_offline);
-       }
-}
-
-static void
-main_window_notify_show_avatars_cb (EmpathyConf        *conf,
-                                   const gchar       *key,
-                                   EmpathyMainWindow *window)
-{
-       gboolean show_avatars;
-
-       if (empathy_conf_get_bool (conf, key, &show_avatars)) {
-               empathy_contact_list_store_set_show_avatars (window->list_store,
-                                                           show_avatars);
-       }
-}
-
-static void
-main_window_notify_compact_contact_list_cb (EmpathyConf        *conf,
-                                           const gchar       *key,
-                                           EmpathyMainWindow *window)
-{
-       gboolean compact_contact_list;
-
-       if (empathy_conf_get_bool (conf, key, &compact_contact_list)) {
-               empathy_contact_list_store_set_is_compact (window->list_store,
-                                                         compact_contact_list);
-       }
-}
-
-static void
-main_window_notify_sort_criterium_cb (EmpathyConf       *conf,
-                                     const gchar       *key,
-                                     EmpathyMainWindow *window)
-{
-       gchar *str = NULL;
-
-       if (empathy_conf_get_string (conf, key, &str) && str) {
-               GType       type;
-               GEnumClass *enum_class;
-               GEnumValue *enum_value;
-
-               type = empathy_contact_list_store_sort_get_type ();
-               enum_class = G_ENUM_CLASS (g_type_class_peek (type));
-               enum_value = g_enum_get_value_by_nick (enum_class, str);
-               g_free (str);
-
-               if (enum_value) {
-                       empathy_contact_list_store_set_sort_criterium (window->list_store, 
-                                                                      enum_value->value);
-               }
-       }
-}
-
diff --git a/libempathy-gtk/empathy-main-window.glade b/libempathy-gtk/empathy-main-window.glade
deleted file mode 100644 (file)
index 5ac2187..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--*- mode: xml -*-->
-<glade-interface>
-  <widget class="GtkWindow" id="main_window">
-    <property name="title" translatable="yes">Contact List</property>
-    <property name="default_width">225</property>
-    <property name="default_height">325</property>
-    <child>
-      <widget class="GtkVBox" id="main_vbox">
-        <property name="visible">True</property>
-        <child>
-          <widget class="GtkMenuBar" id="menubar2">
-            <property name="visible">True</property>
-            <child>
-              <widget class="GtkMenuItem" id="chat">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Chat</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="chat_menu">
-                    <child>
-                      <widget class="GtkImageMenuItem" id="chat_new_message">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_New Conversation...</property>
-                        <property name="use_underline">True</property>
-                        <accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image885">
-                            <property name="visible">True</property>
-                            <property name="icon_size">1</property>
-                            <property name="icon_name">im-message-new</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="chat_history">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_View Previous Conversations</property>
-                        <property name="use_underline">True</property>
-                        <accelerator key="F3" modifiers="" signal="activate"/>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image886">
-                            <property name="visible">True</property>
-                            <property name="icon_size">1</property>
-                            <property name="icon_name">document-open-recent</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="separator5">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="chat_add_contact">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_Add Contact...</property>
-                        <property name="use_underline">True</property>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image887">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-add</property>
-                            <property name="icon_size">1</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="separator3">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkCheckMenuItem" id="chat_show_offline">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Show _Offline Contacts</property>
-                        <property name="use_underline">True</property>
-                        <accelerator key="H" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="separator6">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="chat_quit">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">gtk-quit</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkMenuItem" id="edit">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Edit</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="edit_menu">
-                    <child>
-                      <widget class="GtkMenuItem" id="edit_context">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Context</property>
-                        <property name="use_underline">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="edit_context_separator">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkMenuItem" id="edit_accounts">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_Accounts</property>
-                        <property name="use_underline">True</property>
-                        <accelerator key="F4" modifiers="" signal="activate"/>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="edit_personal_information">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_Personal Information</property>
-                        <property name="use_underline">True</property>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image894">
-                            <property name="visible">True</property>
-                            <property name="icon_size">1</property>
-                            <property name="icon_name">user-info</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="separator2">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="edit_preferences">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_Preferences</property>
-                        <property name="use_underline">True</property>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image891">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-preferences</property>
-                            <property name="icon_size">1</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkMenuItem" id="room">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Room</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="room_menu">
-                    <child>
-                      <widget class="GtkMenuItem" id="room_join_new">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Join _New...</property>
-                        <property name="use_underline">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkMenuItem" id="room_join_favorites">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Join _Favorites</property>
-                        <property name="use_underline">True</property>
-                        <accelerator key="F5" modifiers="" signal="activate"/>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="room_sep">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkSeparatorMenuItem" id="room_sep2">
-                        <property name="visible">True</property>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="room_manage_favorites">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Manage Favorites</property>
-                        <property name="use_underline">True</property>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image890">
-                            <property name="visible">True</property>
-                            <property name="icon_size">1</property>
-                            <property name="icon_name">system-users</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkMenuItem" id="help">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">_Help</property>
-                <property name="use_underline">True</property>
-                <child>
-                  <widget class="GtkMenu" id="help_menu">
-                    <child>
-                      <widget class="GtkImageMenuItem" id="help_contents">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_Contents</property>
-                        <property name="use_underline">True</property>
-                        <accelerator key="F1" modifiers="" signal="activate"/>
-                        <child internal-child="image">
-                          <widget class="GtkImage" id="image892">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-help</property>
-                            <property name="icon_size">1</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkImageMenuItem" id="help_about">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">gtk-about</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkToolbar" id="presence_toolbar">
-            <property name="visible">True</property>
-            <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkVBox" id="errors_vbox">
-            <child>
-              <placeholder/>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <widget class="GtkScrolledWindow" id="roster_scrolledwindow">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="has_focus">True</property>
-            <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
-            <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-            <property name="shadow_type">GTK_SHADOW_IN</property>
-            <child>
-              <placeholder/>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">3</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/libempathy-gtk/empathy-main-window.h b/libempathy-gtk/empathy-main-window.h
deleted file mode 100644 (file)
index 669a978..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2002-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_MAIN_WINDOW_H__
-#define __EMPATHY_MAIN_WINDOW_H__
-
-#include <gtk/gtkwidget.h>
-
-G_BEGIN_DECLS
-
-GtkWidget *empathy_main_window_show (void);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_MAIN_WINDOW_H__ */
diff --git a/libempathy-gtk/empathy-new-chatroom-dialog.c b/libempathy-gtk/empathy-new-chatroom-dialog.c
deleted file mode 100644 (file)
index b334394..0000000
+++ /dev/null
@@ -1,566 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006-2007 Imendio AB
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Martyn Russell <martyn@imendio.com>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdio.h>
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include <libmissioncontrol/mission-control.h>
-#include <libmissioncontrol/mc-account.h>
-#include <libmissioncontrol/mc-profile.h>
-
-#include <libempathy/empathy-tp-roomlist.h>
-#include <libempathy/empathy-chatroom.h>
-#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-debug.h>
-
-#include "empathy-new-chatroom-dialog.h"
-#include "empathy-account-chooser.h"
-#include "empathy-ui-utils.h"
-#include "ephy-spinner.h"
-
-#define DEBUG_DOMAIN "NewChatroomDialog"
-
-typedef struct {
-       EmpathyTpRoomlist *room_list;
-
-       GtkWidget         *window;
-       GtkWidget         *vbox_widgets;
-       GtkWidget         *table_info;
-       GtkWidget         *label_account;
-       GtkWidget         *account_chooser;
-       GtkWidget         *label_server;
-       GtkWidget         *entry_server;
-       GtkWidget         *togglebutton_refresh;
-       GtkWidget         *label_room;
-       GtkWidget         *entry_room;
-       GtkWidget         *vbox_browse;
-       GtkWidget         *image_status;
-       GtkWidget         *label_status;
-       GtkWidget         *hbox_status;
-       GtkWidget         *throbber;
-       GtkWidget         *treeview;
-       GtkTreeModel      *model;
-       GtkWidget         *button_join;
-       GtkWidget         *button_close;
-} EmpathyNewChatroomDialog;
-
-enum {
-       COL_NAME,
-       COL_ROOM,
-       COL_COUNT
-};
-
-static void     new_chatroom_dialog_response_cb                     (GtkWidget               *widget,
-                                                                    gint                     response,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_destroy_cb                      (GtkWidget               *widget,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_model_setup                     (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_model_add_columns               (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_update_widgets                  (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_account_changed_cb              (GtkComboBox              *combobox,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_roomlist_destroy_cb             (EmpathyTpRoomlist        *room_list,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_new_room_cb                     (EmpathyTpRoomlist        *room_list,
-                                                                    EmpathyChatroom          *chatroom,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_listing_cb                      (EmpathyTpRoomlist        *room_list,
-                                                                    gboolean                  listing,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_model_clear                     (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_model_row_activated_cb          (GtkTreeView             *tree_view,
-                                                                    GtkTreePath             *path,
-                                                                    GtkTreeViewColumn       *column,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_model_selection_changed         (GtkTreeSelection        *selection,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_join                            (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_entry_changed_cb                (GtkWidget               *entry,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_browse_start                    (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_browse_stop                     (EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_entry_server_activate_cb        (GtkWidget               *widget,
-                                                                    EmpathyNewChatroomDialog *dialog);
-static void     new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget               *widget,
-                                                                    EmpathyNewChatroomDialog *dialog);
-
-static EmpathyNewChatroomDialog *dialog_p = NULL;
-
-void
-empathy_new_chatroom_dialog_show (GtkWindow *parent)
-{
-       EmpathyNewChatroomDialog *dialog;
-       GladeXML                 *glade;
-       GtkSizeGroup             *size_group;
-
-       if (dialog_p) {
-               gtk_window_present (GTK_WINDOW (dialog_p->window));
-               return;
-       }
-
-       dialog_p = dialog = g_new0 (EmpathyNewChatroomDialog, 1);
-
-       glade = empathy_glade_get_file ("empathy-new-chatroom-dialog.glade",
-                                      "new_chatroom_dialog",
-                                      NULL,
-                                      "new_chatroom_dialog", &dialog->window,
-                                      "table_info", &dialog->table_info,
-                                      "label_account", &dialog->label_account,
-                                      "label_server", &dialog->label_server,
-                                      "label_room", &dialog->label_room,
-                                      "entry_server", &dialog->entry_server,
-                                      "entry_room", &dialog->entry_room,
-                                      "togglebutton_refresh", &dialog->togglebutton_refresh,
-                                      "vbox_browse", &dialog->vbox_browse,
-                                      "image_status", &dialog->image_status,
-                                      "label_status", &dialog->label_status,
-                                      "hbox_status", &dialog->hbox_status,
-                                      "treeview", &dialog->treeview,
-                                      "button_join", &dialog->button_join,
-                                      NULL);
-
-       empathy_glade_connect (glade,
-                             dialog,
-                             "new_chatroom_dialog", "response", new_chatroom_dialog_response_cb,
-                             "new_chatroom_dialog", "destroy", new_chatroom_dialog_destroy_cb,
-                             "entry_server", "changed", new_chatroom_dialog_entry_changed_cb,
-                             "entry_server", "activate", new_chatroom_dialog_entry_server_activate_cb,
-                             "entry_room", "changed", new_chatroom_dialog_entry_changed_cb,
-                             "togglebutton_refresh", "toggled", new_chatroom_dialog_togglebutton_refresh_toggled_cb,
-                             NULL);
-
-       g_object_unref (glade);
-
-       g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog_p);
-
-       /* Label alignment */
-       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
-
-       gtk_size_group_add_widget (size_group, dialog->label_account);
-       gtk_size_group_add_widget (size_group, dialog->label_server);
-       gtk_size_group_add_widget (size_group, dialog->label_room);
-
-       g_object_unref (size_group);
-
-       /* Set up chatrooms treeview */
-       new_chatroom_dialog_model_setup (dialog);
-
-       /* Add throbber */
-       dialog->throbber = ephy_spinner_new ();
-       ephy_spinner_set_size (EPHY_SPINNER (dialog->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR);
-       gtk_widget_show (dialog->throbber);
-
-       gtk_box_pack_start (GTK_BOX (dialog->hbox_status), dialog->throbber, 
-                           FALSE, FALSE, 0);
-
-       /* Account chooser for custom */
-       dialog->account_chooser = empathy_account_chooser_new ();
-       empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser),
-                                           empathy_account_chooser_filter_is_connected,
-                                           NULL);
-       gtk_table_attach_defaults (GTK_TABLE (dialog->table_info),
-                                  dialog->account_chooser,
-                                  1, 3, 0, 1);
-       gtk_widget_show (dialog->account_chooser);
-
-       g_signal_connect (GTK_COMBO_BOX (dialog->account_chooser), "changed",
-                         G_CALLBACK (new_chatroom_dialog_account_changed_cb),
-                         dialog);
-       new_chatroom_dialog_account_changed_cb (GTK_COMBO_BOX (dialog->account_chooser),
-                                               dialog);
-
-       if (parent) {
-               gtk_window_set_transient_for (GTK_WINDOW (dialog->window),
-                                             GTK_WINDOW (parent));
-       }
-
-       gtk_widget_show (dialog->window);
-}
-
-static void
-new_chatroom_dialog_response_cb (GtkWidget               *widget,
-                                gint                     response,
-                                EmpathyNewChatroomDialog *dialog)
-{
-       if (response == GTK_RESPONSE_OK) {
-               new_chatroom_dialog_join (dialog);
-       }
-
-       gtk_widget_destroy (widget);
-}
-
-static void
-new_chatroom_dialog_destroy_cb (GtkWidget               *widget,
-                               EmpathyNewChatroomDialog *dialog)
-{
-       if (dialog->room_list) {
-               g_object_unref (dialog->room_list);
-       }
-       g_object_unref (dialog->model);  
-
-       g_free (dialog);
-}
-
-static void
-new_chatroom_dialog_model_setup (EmpathyNewChatroomDialog *dialog)
-{
-       GtkTreeView      *view;
-       GtkListStore     *store;
-       GtkTreeSelection *selection;
-
-       /* View */
-       view = GTK_TREE_VIEW (dialog->treeview);
-
-       g_signal_connect (view, "row-activated",
-                         G_CALLBACK (new_chatroom_dialog_model_row_activated_cb),
-                         dialog);
-
-       /* Store/Model */
-       store = gtk_list_store_new (COL_COUNT,
-                                   G_TYPE_STRING,       /* Image */
-                                   G_TYPE_STRING,       /* Text */
-                                   G_TYPE_STRING);      /* Room */
-
-       dialog->model = GTK_TREE_MODEL (store);
-       gtk_tree_view_set_model (view, dialog->model);
-
-       /* Selection */
-       selection = gtk_tree_view_get_selection (view);
-       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
-                                             COL_NAME, GTK_SORT_ASCENDING);
-
-       g_signal_connect (selection, "changed",
-                         G_CALLBACK (new_chatroom_dialog_model_selection_changed),
-                         dialog);
-
-       /* Columns */
-       new_chatroom_dialog_model_add_columns (dialog);
-}
-
-static void
-new_chatroom_dialog_model_add_columns (EmpathyNewChatroomDialog *dialog)
-{
-       GtkTreeView       *view;
-       GtkTreeViewColumn *column;
-       GtkCellRenderer   *cell;
-
-       view = GTK_TREE_VIEW (dialog->treeview);
-       gtk_tree_view_set_headers_visible (view, FALSE);
-
-       cell = gtk_cell_renderer_text_new ();
-       g_object_set (cell,
-                     "xpad", (guint) 4,
-                     "ypad", (guint) 1,
-                     "ellipsize", PANGO_ELLIPSIZE_END,
-                     NULL);
-
-       column = gtk_tree_view_column_new_with_attributes (_("Chat Rooms"),
-                                                          cell,
-                                                          "text", COL_NAME,
-                                                          NULL);
-
-       gtk_tree_view_column_set_expand (column, TRUE);
-       gtk_tree_view_append_column (view, column);
-}
-
-static void
-new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog)
-{
-       EmpathyAccountChooser *account_chooser;
-       McAccount             *account;
-       McProfile             *profile;
-       const gchar           *protocol;
-       const gchar           *room;
-       
-       account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
-       profile = mc_account_get_profile (account);
-       protocol = mc_profile_get_protocol_name (profile);
-
-       gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), "");
-
-       /* hardcode here known protocols */
-       if (strcmp (protocol, "jabber") == 0) {
-               gtk_widget_set_sensitive (dialog->entry_server, TRUE);
-               gtk_widget_show (dialog->vbox_browse);
-
-       }
-       else if (strcmp (protocol, "local-xmpp") == 0) {
-               gtk_widget_set_sensitive (dialog->entry_server, FALSE);
-               gtk_widget_show (dialog->vbox_browse);          
-       }
-       else if (strcmp (protocol, "irc") == 0) {
-               gtk_widget_set_sensitive (dialog->entry_server, FALSE);
-               gtk_widget_show (dialog->vbox_browse);          
-       } else {
-               gtk_widget_set_sensitive (dialog->entry_server, TRUE);
-               gtk_widget_show (dialog->vbox_browse);
-       }
-
-       room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
-       gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room));
-
-       /* Final set up of the dialog */
-       gtk_widget_grab_focus (dialog->entry_room);
-
-       g_object_unref (account);
-       g_object_unref (profile);
-}
-
-static void
-new_chatroom_dialog_account_changed_cb (GtkComboBox             *combobox,
-                                       EmpathyNewChatroomDialog *dialog)
-{
-       EmpathyAccountChooser *account_chooser;
-       McAccount             *account;
-       gboolean               listing = FALSE;
-
-       if (dialog->room_list) {
-               g_object_unref (dialog->room_list);
-       }
-
-       ephy_spinner_stop (EPHY_SPINNER (dialog->throbber));
-       new_chatroom_dialog_model_clear (dialog);
-
-       account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
-       dialog->room_list = empathy_tp_roomlist_new (account);
-
-       if (dialog->room_list)  {
-               g_signal_connect (dialog->room_list, "destroy",
-                                 G_CALLBACK (new_chatroom_dialog_roomlist_destroy_cb),
-                                 dialog);
-               g_signal_connect (dialog->room_list, "new-room",
-                                 G_CALLBACK (new_chatroom_dialog_new_room_cb),
-                                 dialog);
-               g_signal_connect (dialog->room_list, "listing",
-                                 G_CALLBACK (new_chatroom_dialog_listing_cb),
-                                 dialog);
-
-               listing = empathy_tp_roomlist_is_listing (dialog->room_list);
-               if (listing) {
-                       ephy_spinner_start (EPHY_SPINNER (dialog->throbber));
-               }
-       }
-
-       new_chatroom_dialog_update_widgets (dialog);
-}
-
-static void
-new_chatroom_dialog_roomlist_destroy_cb (EmpathyTpRoomlist        *room_list,
-                                        EmpathyNewChatroomDialog *dialog)
-{
-       g_object_unref (dialog->room_list);
-       dialog->room_list = NULL;
-}
-
-static void
-new_chatroom_dialog_new_room_cb (EmpathyTpRoomlist        *room_list,
-                                EmpathyChatroom          *chatroom,
-                                EmpathyNewChatroomDialog *dialog)
-{
-       GtkTreeView      *view;
-       GtkTreeSelection *selection;
-       GtkListStore     *store;
-       GtkTreeIter       iter;
-
-       empathy_debug (DEBUG_DOMAIN, "New chatroom listed: %s (%s)",
-                      empathy_chatroom_get_name (chatroom),
-                      empathy_chatroom_get_room (chatroom));
-
-       /* Add to model */
-       view = GTK_TREE_VIEW (dialog->treeview);
-       selection = gtk_tree_view_get_selection (view);
-       store = GTK_LIST_STORE (dialog->model);
-
-       gtk_list_store_append (store, &iter);
-       gtk_list_store_set (store, &iter,
-                           COL_NAME, empathy_chatroom_get_name (chatroom),
-                           COL_ROOM, empathy_chatroom_get_room (chatroom),
-                           -1);
-}
-
-static void
-new_chatroom_dialog_listing_cb (EmpathyTpRoomlist        *room_list,
-                               gboolean                  listing,
-                               EmpathyNewChatroomDialog *dialog)
-{
-       /* Update the throbber */
-       if (listing) {
-               ephy_spinner_start (EPHY_SPINNER (dialog->throbber));           
-       } else {
-               ephy_spinner_stop (EPHY_SPINNER (dialog->throbber));
-       }
-
-       /* Update the refresh toggle button */
-       g_signal_handlers_block_by_func (dialog->togglebutton_refresh,
-                                        new_chatroom_dialog_togglebutton_refresh_toggled_cb,
-                                        dialog);
-       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->togglebutton_refresh),
-                                     listing);
-       g_signal_handlers_unblock_by_func (dialog->togglebutton_refresh,
-                                          new_chatroom_dialog_togglebutton_refresh_toggled_cb,
-                                          dialog);
-}
-
-static void
-new_chatroom_dialog_model_clear (EmpathyNewChatroomDialog *dialog)
-{
-       GtkListStore *store;
-
-       store = GTK_LIST_STORE (dialog->model);
-       gtk_list_store_clear (store);
-}
-
-static void
-new_chatroom_dialog_model_row_activated_cb (GtkTreeView             *tree_view,
-                                           GtkTreePath             *path,
-                                           GtkTreeViewColumn       *column,
-                                           EmpathyNewChatroomDialog *dialog)
-{
-       gtk_widget_activate (dialog->button_join);
-}
-
-static void
-new_chatroom_dialog_model_selection_changed (GtkTreeSelection         *selection,
-                                            EmpathyNewChatroomDialog *dialog)
-{      
-       GtkTreeModel *model;
-       GtkTreeIter   iter;
-       gchar        *room = NULL;
-       gchar        *server = NULL;
-
-       if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
-               return;
-       }
-
-       gtk_tree_model_get (model, &iter, COL_ROOM, &room, -1);
-       server = strstr (room, "@");
-       if (server) {
-               *server = '\0';
-               server++;
-       }
-
-       gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), server ? server : "");
-       gtk_entry_set_text (GTK_ENTRY (dialog->entry_room), room ? room : "");
-
-       g_free (room);
-}
-
-static void
-new_chatroom_dialog_join (EmpathyNewChatroomDialog *dialog)
-{
-       McAccount            *account;
-       EmpathyAccountChooser *account_chooser;
-       MissionControl       *mc;
-       const gchar          *room;
-       const gchar          *server = NULL;
-       gchar                *room_name = NULL;
-
-       room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
-       server = gtk_entry_get_text (GTK_ENTRY (dialog->entry_server));
-
-       account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
-       account = empathy_account_chooser_get_account (account_chooser);
-
-       if (!G_STR_EMPTY (server)) {
-               room_name = g_strconcat (room, "@", server, NULL);
-       } else {
-               room_name = g_strdup (room);
-       }
-
-       empathy_debug (DEBUG_DOMAIN, "Requesting channel for '%s'", room_name);
-
-       mc = empathy_mission_control_new ();
-       mission_control_request_channel_with_string_handle (mc,
-                                                           account,
-                                                           TP_IFACE_CHANNEL_TYPE_TEXT,
-                                                           room_name,
-                                                           TP_HANDLE_TYPE_ROOM,
-                                                           NULL, NULL);        
-       g_free (room_name);
-       g_object_unref (mc);
-}
-
-static void
-new_chatroom_dialog_entry_changed_cb (GtkWidget                *entry,
-                                     EmpathyNewChatroomDialog *dialog)
-{
-       if (entry == dialog->entry_room) {
-               const gchar *room;
-
-               room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
-               gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room));
-               /* FIXME: Select the room in the list */
-       }
-}
-
-static void
-new_chatroom_dialog_browse_start (EmpathyNewChatroomDialog *dialog)
-{
-       new_chatroom_dialog_model_clear (dialog);
-       if (dialog->room_list) {
-               empathy_tp_roomlist_start (dialog->room_list);
-       }
-}
-
-static void
-new_chatroom_dialog_browse_stop (EmpathyNewChatroomDialog *dialog)
-{
-       if (dialog->room_list) {
-               empathy_tp_roomlist_stop (dialog->room_list);
-       }
-}
-
-static void
-new_chatroom_dialog_entry_server_activate_cb (GtkWidget                *widget,
-                                             EmpathyNewChatroomDialog  *dialog)
-{
-       new_chatroom_dialog_togglebutton_refresh_toggled_cb (dialog->togglebutton_refresh, 
-                                                            dialog);
-}
-
-static void
-new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget               *widget,
-                                                    EmpathyNewChatroomDialog *dialog)
-{
-       gboolean toggled;
-
-       toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
-       
-       if (toggled) {
-               new_chatroom_dialog_browse_start (dialog);
-       } else {
-               new_chatroom_dialog_browse_stop (dialog);
-       }
-}
-
diff --git a/libempathy-gtk/empathy-new-chatroom-dialog.glade b/libempathy-gtk/empathy-new-chatroom-dialog.glade
deleted file mode 100644 (file)
index 1ba74ec..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--*- mode: xml -*-->
-<glade-interface>
-  <widget class="GtkDialog" id="new_chatroom_dialog">
-    <property name="visible">True</property>
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Join New</property>
-    <property name="resizable">False</property>
-    <property name="default_width">350</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox4">
-        <property name="visible">True</property>
-        <property name="spacing">6</property>
-        <child>
-          <widget class="GtkVBox" id="vbox_widgets">
-            <property name="visible">True</property>
-            <property name="border_width">5</property>
-            <property name="spacing">18</property>
-            <child>
-              <widget class="GtkTable" id="table_info">
-                <property name="visible">True</property>
-                <property name="n_rows">3</property>
-                <property name="n_columns">3</property>
-                <property name="column_spacing">6</property>
-                <property name="row_spacing">6</property>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-                <child>
-                  <widget class="GtkEntry" id="entry_room">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="tooltip" translatable="yes">Enter the room name to join here or click on one or more rooms in the list.</property>
-                    <property name="invisible_char">*</property>
-                    <property name="activates_default">True</property>
-                    <property name="width_chars">32</property>
-                  </widget>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkToggleButton" id="togglebutton_refresh">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="label" translatable="yes">Re_fresh</property>
-                    <property name="use_underline">True</property>
-                    <property name="response_id">0</property>
-                  </widget>
-                  <packing>
-                    <property name="left_attach">2</property>
-                    <property name="right_attach">3</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkEntry" id="entry_server">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="tooltip" translatable="yes">Enter the server which hosts the room, or leave it empty if the room is on the current account's server</property>
-                    <property name="invisible_char">*</property>
-                    <property name="width_chars">25</property>
-                  </widget>
-                  <packing>
-                    <property name="left_attach">1</property>
-                    <property name="right_attach">2</property>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkLabel" id="label_room">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Room:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">entry_room</property>
-                  </widget>
-                  <packing>
-                    <property name="top_attach">2</property>
-                    <property name="bottom_attach">3</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkLabel" id="label_server">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">_Server:</property>
-                    <property name="use_underline">True</property>
-                    <property name="mnemonic_widget">entry_server</property>
-                  </widget>
-                  <packing>
-                    <property name="top_attach">1</property>
-                    <property name="bottom_attach">2</property>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkLabel" id="label_account">
-                    <property name="visible">True</property>
-                    <property name="xalign">0</property>
-                    <property name="label" translatable="yes">Account:</property>
-                  </widget>
-                  <packing>
-                    <property name="x_options">GTK_FILL</property>
-                    <property name="y_options"></property>
-                  </packing>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkVBox" id="vbox_browse">
-                <property name="visible">True</property>
-                <property name="spacing">6</property>
-                <child>
-                  <widget class="GtkHBox" id="hbox_status">
-                    <property name="visible">True</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <widget class="GtkHBox" id="hbox35">
-                        <property name="visible">True</property>
-                        <property name="spacing">3</property>
-                        <child>
-                          <widget class="GtkImage" id="image_status">
-                            <property name="visible">True</property>
-                            <property name="icon_size">2</property>
-                            <property name="icon_name">gtk-find</property>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <widget class="GtkLabel" id="label_status">
-                            <property name="visible">True</property>
-                            <property name="xalign">0</property>
-                            <property name="label" translatable="yes">Browse:</property>
-                            <property name="wrap">True</property>
-                          </widget>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                  </widget>
-                </child>
-                <child>
-                  <widget class="GtkScrolledWindow" id="scrolledwindow2">
-                    <property name="height_request">150</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
-                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="shadow_type">GTK_SHADOW_IN</property>
-                    <child>
-                      <widget class="GtkTreeView" id="treeview">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="tooltip" translatable="yes">This list represents all chat rooms hosted on the server you have entered.</property>
-                        <property name="headers_visible">False</property>
-                      </widget>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <widget class="GtkHButtonBox" id="dialog-action_area4">
-            <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
-            <child>
-              <widget class="GtkButton" id="button_cancel">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-close</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">-7</property>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkButton" id="button_join">
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="has_default">True</property>
-                <property name="response_id">-5</property>
-                <child>
-                  <widget class="GtkAlignment" id="alignment4">
-                    <property name="visible">True</property>
-                    <property name="xscale">0</property>
-                    <property name="yscale">0</property>
-                    <child>
-                      <widget class="GtkHBox" id="hbox29">
-                        <property name="visible">True</property>
-                        <property name="spacing">2</property>
-                        <child>
-                          <widget class="GtkImage" id="image4">
-                            <property name="visible">True</property>
-                            <property name="stock">gtk-execute</property>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <widget class="GtkLabel" id="label79">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Join</property>
-                            <property name="use_underline">True</property>
-                          </widget>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                      </widget>
-                    </child>
-                  </widget>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">GTK_PACK_END</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/libempathy-gtk/empathy-new-chatroom-dialog.h b/libempathy-gtk/empathy-new-chatroom-dialog.h
deleted file mode 100644 (file)
index 2a12608..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006-2007 Imendio AB
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- * 
- * Authors: Martyn Russell <martyn@imendio.com>
- *          Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_NEW_CHATROOMS_WINDOW_H__
-#define __EMPATHY_NEW_CHATROOMS_WINDOW_H__
-
-G_BEGIN_DECLS
-
-void empathy_new_chatroom_dialog_show (GtkWindow *parent);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_NEW_CHATROOMS_WINDOW_H__ */
diff --git a/libempathy-gtk/empathy-preferences.c b/libempathy-gtk/empathy-preferences.c
deleted file mode 100644 (file)
index 1b64666..0000000
+++ /dev/null
@@ -1,1017 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2003-2007 Imendio AB
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors: Mikael Hallendal <micke@imendio.com>
- *          Richard Hult <richard@imendio.com>
- *          Martyn Russell <martyn@imendio.com>
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <glib/gi18n.h>
-
-#include "empathy-conf.h"
-#include "empathy-preferences.h"
-#include "empathy-ui-utils.h"
-#include "empathy-theme-manager.h"
-#include "empathy-spell.h"
-#include "empathy-contact-list-store.h"
-#include "empathy-gtk-enum-types.h"
-
-typedef struct {
-       GtkWidget *dialog;
-
-       GtkWidget *notebook;
-
-       GtkWidget *checkbutton_show_avatars;
-       GtkWidget *checkbutton_compact_contact_list;
-       GtkWidget *checkbutton_show_smileys;
-       GtkWidget *combobox_chat_theme;
-       GtkWidget *checkbutton_theme_chat_room;
-       GtkWidget *checkbutton_separate_chat_windows;
-       GtkWidget *checkbutton_autoconnect;
-       GtkWidget *radiobutton_contact_list_sort_by_name;
-       GtkWidget *radiobutton_contact_list_sort_by_state;
-
-       GtkWidget *checkbutton_sounds_for_messages;
-       GtkWidget *checkbutton_sounds_when_busy;
-       GtkWidget *checkbutton_sounds_when_away;
-       GtkWidget *checkbutton_popups_when_available;
-
-       GtkWidget *treeview_spell_checker;
-
-       GList     *notify_ids;
-} EmpathyPreferences;
-
-static void     preferences_setup_widgets                (EmpathyPreferences      *preferences);
-static void     preferences_languages_setup              (EmpathyPreferences      *preferences);
-static void     preferences_languages_add                (EmpathyPreferences      *preferences);
-static void     preferences_languages_save               (EmpathyPreferences      *preferences);
-static gboolean preferences_languages_save_foreach       (GtkTreeModel           *model,
-                                                         GtkTreePath            *path,
-                                                         GtkTreeIter            *iter,
-                                                         gchar                 **languages);
-static void     preferences_languages_load               (EmpathyPreferences      *preferences);
-static gboolean preferences_languages_load_foreach       (GtkTreeModel           *model,
-                                                         GtkTreePath            *path,
-                                                         GtkTreeIter            *iter,
-                                                         gchar                 **languages);
-static void     preferences_languages_cell_toggled_cb    (GtkCellRendererToggle  *cell,
-                                                         gchar                  *path_string,
-                                                         EmpathyPreferences      *preferences);
-static void     preferences_themes_setup                 (EmpathyPreferences      *preferences);
-static void     preferences_widget_sync_bool             (const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_widget_sync_int              (const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_widget_sync_string           (const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_widget_sync_string_combo     (const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_notify_int_cb                (EmpathyConf             *conf,
-                                                         const gchar            *key,
-                                                         gpointer                user_data);
-static void     preferences_notify_string_cb             (EmpathyConf             *conf,
-                                                         const gchar            *key,
-                                                         gpointer                user_data);
-static void     preferences_notify_string_combo_cb       (EmpathyConf             *conf,
-                                                         const gchar            *key,
-                                                         gpointer                user_data);
-static void     preferences_notify_bool_cb               (EmpathyConf             *conf,
-                                                         const gchar            *key,
-                                                         gpointer                user_data);
-static void     preferences_notify_sensitivity_cb        (EmpathyConf             *conf,
-                                                         const gchar            *key,
-                                                         gpointer                user_data);
-static void     preferences_hookup_spin_button           (EmpathyPreferences      *preferences,
-                                                         const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_hookup_entry                 (EmpathyPreferences      *preferences,
-                                                         const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_hookup_toggle_button         (EmpathyPreferences      *preferences,
-                                                         const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_hookup_radio_button          (EmpathyPreferences      *preferences,
-                                                         const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_hookup_string_combo          (EmpathyPreferences      *preferences,
-                                                         const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_hookup_sensitivity           (EmpathyPreferences      *preferences,
-                                                         const gchar            *key,
-                                                         GtkWidget              *widget);
-static void     preferences_spin_button_value_changed_cb (GtkWidget              *button,
-                                                         gpointer                user_data);
-static void     preferences_entry_value_changed_cb       (GtkWidget              *entry,
-                                                         gpointer                user_data);
-static void     preferences_toggle_button_toggled_cb     (GtkWidget              *button,
-                                                         gpointer                user_data);
-static void     preferences_radio_button_toggled_cb      (GtkWidget              *button,
-                                                         gpointer                user_data);
-static void     preferences_string_combo_changed_cb      (GtkWidget *button,
-                                                         gpointer                user_data);
-static void     preferences_destroy_cb                   (GtkWidget              *widget,
-                                                         EmpathyPreferences      *preferences);
-static void     preferences_response_cb                  (GtkWidget              *widget,
-                                                         gint                    response,
-                                                         EmpathyPreferences      *preferences);
-
-enum {
-       COL_LANG_ENABLED,
-       COL_LANG_CODE,
-       COL_LANG_NAME,
-       COL_LANG_COUNT
-};
-
-enum {
-       COL_COMBO_VISIBLE_NAME,
-       COL_COMBO_NAME,
-       COL_COMBO_COUNT
-};
-
-static void
-preferences_add_id (EmpathyPreferences *preferences, guint id)
-{
-       preferences->notify_ids = g_list_prepend (preferences->notify_ids,
-                                                 GUINT_TO_POINTER (id));
-}
-
-static void
-preferences_compact_contact_list_changed_cb (EmpathyConf *conf,
-                                            const gchar *key,
-                                            gpointer     user_data)
-{
-       EmpathyPreferences *preferences = user_data;
-       gboolean            value;
-
-       if (empathy_conf_get_bool (empathy_conf_get (), key, &value)) {
-               gtk_widget_set_sensitive (preferences->checkbutton_show_avatars,
-                                         !value);
-       }
-}
-
-static void
-preferences_setup_widgets (EmpathyPreferences *preferences)
-{
-       guint id;
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_SOUNDS_FOR_MESSAGES,
-                                         preferences->checkbutton_sounds_for_messages);
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_SOUNDS_WHEN_AWAY,
-                                         preferences->checkbutton_sounds_when_away);
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_SOUNDS_WHEN_BUSY,
-                                         preferences->checkbutton_sounds_when_busy);
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_POPUPS_WHEN_AVAILABLE,
-                                         preferences->checkbutton_popups_when_available);
-
-       preferences_hookup_sensitivity (preferences,
-                                       EMPATHY_PREFS_SOUNDS_FOR_MESSAGES,
-                                       preferences->checkbutton_sounds_when_away);
-       preferences_hookup_sensitivity (preferences,
-                                       EMPATHY_PREFS_SOUNDS_FOR_MESSAGES,
-                                       preferences->checkbutton_sounds_when_busy);
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS,
-                                         preferences->checkbutton_separate_chat_windows);
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_UI_SHOW_AVATARS,
-                                         preferences->checkbutton_show_avatars);
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
-                                         preferences->checkbutton_compact_contact_list);
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
-                                         preferences->checkbutton_show_smileys);
-
-       preferences_hookup_string_combo (preferences,
-                                        EMPATHY_PREFS_CHAT_THEME,
-                                        preferences->combobox_chat_theme);
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_CHAT_THEME_CHAT_ROOM,
-                                         preferences->checkbutton_theme_chat_room);
-
-       preferences_hookup_radio_button (preferences,
-                                        EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
-                                        preferences->radiobutton_contact_list_sort_by_name);
-
-       preferences_hookup_toggle_button (preferences,
-                                         EMPATHY_PREFS_AUTOCONNECT,
-                                         preferences->checkbutton_autoconnect);
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                     EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
-                                     preferences_compact_contact_list_changed_cb,
-                                     preferences);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-       preferences_compact_contact_list_changed_cb (empathy_conf_get (),
-                                                    EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
-                                                    preferences);
-}
-
-static void
-preferences_languages_setup (EmpathyPreferences *preferences)
-{
-       GtkTreeView       *view;
-       GtkListStore      *store;
-       GtkTreeSelection  *selection;
-       GtkTreeModel      *model;
-       GtkTreeViewColumn *column;
-       GtkCellRenderer   *renderer;
-       guint              col_offset;
-
-       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
-
-       store = gtk_list_store_new (COL_LANG_COUNT,
-                                   G_TYPE_BOOLEAN,  /* enabled */
-                                   G_TYPE_STRING,   /* code */
-                                   G_TYPE_STRING);  /* name */
-
-       gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
-
-       selection = gtk_tree_view_get_selection (view);
-       gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
-
-       model = GTK_TREE_MODEL (store);
-
-       renderer = gtk_cell_renderer_toggle_new ();
-       g_signal_connect (renderer, "toggled",
-                         G_CALLBACK (preferences_languages_cell_toggled_cb),
-                         preferences);
-
-       column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
-                                                          "active", COL_LANG_ENABLED,
-                                                          NULL);
-
-       gtk_tree_view_append_column (view, column);
-
-       renderer = gtk_cell_renderer_text_new ();
-       col_offset = gtk_tree_view_insert_column_with_attributes (view,
-                                                                 -1, _("Language"),
-                                                                 renderer,
-                                                                 "text", COL_LANG_NAME,
-                                                                 NULL);
-
-       g_object_set_data (G_OBJECT (renderer),
-                          "column", GINT_TO_POINTER (COL_LANG_NAME));
-
-       column = gtk_tree_view_get_column (view, col_offset - 1);
-       gtk_tree_view_column_set_sort_column_id (column, COL_LANG_NAME);
-       gtk_tree_view_column_set_resizable (column, FALSE);
-       gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
-
-       g_object_unref (store);
-}
-
-static void
-preferences_languages_add (EmpathyPreferences *preferences)
-{
-       GtkTreeView  *view;
-       GtkListStore *store;
-       GList        *codes, *l;
-
-       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
-       store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
-
-       codes = empathy_spell_get_language_codes ();
-
-       empathy_conf_set_bool (empathy_conf_get(),
-                              EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
-                              codes != NULL);
-       if (!codes) {
-               gtk_widget_set_sensitive (preferences->treeview_spell_checker, FALSE);
-       }               
-
-       for (l = codes; l; l = l->next) {
-               GtkTreeIter  iter;
-               const gchar *code;
-               const gchar *name;
-
-               code = l->data;
-               name = empathy_spell_get_language_name (code);
-               if (!name) {
-                       continue;
-               }
-
-               gtk_list_store_append (store, &iter);
-               gtk_list_store_set (store, &iter,
-                                   COL_LANG_CODE, code,
-                                   COL_LANG_NAME, name,
-                                   -1);
-       }
-
-       empathy_spell_free_language_codes (codes);
-}
-
-static void
-preferences_languages_save (EmpathyPreferences *preferences)
-{
-       GtkTreeView       *view;
-       GtkTreeModel      *model;
-
-       gchar             *languages = NULL;
-
-       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
-       model = gtk_tree_view_get_model (view);
-
-       gtk_tree_model_foreach (model,
-                               (GtkTreeModelForeachFunc) preferences_languages_save_foreach,
-                               &languages);
-
-       /* if user selects no languages, we don't want spell check */
-       empathy_conf_set_bool (empathy_conf_get (),
-                              EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
-                              languages != NULL);
-
-       empathy_conf_set_string (empathy_conf_get (),
-                                EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
-                                languages ? languages : "");
-
-       g_free (languages);
-}
-
-static gboolean
-preferences_languages_save_foreach (GtkTreeModel  *model,
-                                   GtkTreePath   *path,
-                                   GtkTreeIter   *iter,
-                                   gchar        **languages)
-{
-       gboolean  enabled;
-       gchar    *code;
-
-       if (!languages) {
-               return TRUE;
-       }
-
-       gtk_tree_model_get (model, iter, COL_LANG_ENABLED, &enabled, -1);
-       if (!enabled) {
-               return FALSE;
-       }
-
-       gtk_tree_model_get (model, iter, COL_LANG_CODE, &code, -1);
-       if (!code) {
-               return FALSE;
-       }
-
-       if (!(*languages)) {
-               *languages = g_strdup (code);
-       } else {
-               gchar *str = *languages;
-               *languages = g_strdup_printf ("%s,%s", str, code);
-               g_free (str);
-       }
-
-       g_free (code);
-
-       return FALSE;
-}
-
-static void
-preferences_languages_load (EmpathyPreferences *preferences)
-{
-       GtkTreeView   *view;
-       GtkTreeModel  *model;
-       gchar         *value;
-       gchar        **vlanguages;
-
-       if (!empathy_conf_get_string (empathy_conf_get (),
-                                     EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
-                                     &value) || !value) {
-               return;
-       }
-
-       vlanguages = g_strsplit (value, ",", -1);
-       g_free (value);
-
-       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
-       model = gtk_tree_view_get_model (view);
-
-       gtk_tree_model_foreach (model,
-                               (GtkTreeModelForeachFunc) preferences_languages_load_foreach,
-                               vlanguages);
-
-       g_strfreev (vlanguages);
-}
-
-static gboolean
-preferences_languages_load_foreach (GtkTreeModel  *model,
-                                   GtkTreePath   *path,
-                                   GtkTreeIter   *iter,
-                                   gchar        **languages)
-{
-       gchar    *code;
-       gchar    *lang;
-       gint      i;
-       gboolean  found = FALSE;
-
-       if (!languages) {
-               return TRUE;
-       }
-
-       gtk_tree_model_get (model, iter, COL_LANG_CODE, &code, -1);
-       if (!code) {
-               return FALSE;
-       }
-
-       for (i = 0, lang = languages[i]; lang; lang = languages[++i]) {
-               if (strcmp (lang, code) == 0) {
-                       found = TRUE;
-               }
-       }
-
-       gtk_list_store_set (GTK_LIST_STORE (model), iter, COL_LANG_ENABLED, found, -1);
-       return FALSE;
-}
-
-static void
-preferences_languages_cell_toggled_cb (GtkCellRendererToggle *cell,
-                                      gchar                 *path_string,
-                                      EmpathyPreferences     *preferences)
-{
-       GtkTreeView  *view;
-       GtkTreeModel *model;
-       GtkListStore *store;
-       GtkTreePath  *path;
-       GtkTreeIter   iter;
-       gboolean      enabled;
-
-       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
-       model = gtk_tree_view_get_model (view);
-       store = GTK_LIST_STORE (model);
-
-       path = gtk_tree_path_new_from_string (path_string);
-
-       gtk_tree_model_get_iter (model, &iter, path);
-       gtk_tree_model_get (model, &iter, COL_LANG_ENABLED, &enabled, -1);
-
-       enabled ^= 1;
-
-       gtk_list_store_set (store, &iter, COL_LANG_ENABLED, enabled, -1);
-       gtk_tree_path_free (path);
-
-       preferences_languages_save (preferences);
-}
-
-static void
-preferences_themes_setup (EmpathyPreferences *preferences)
-{
-       GtkComboBox   *combo;
-       GtkListStore  *model;
-       GtkTreeIter    iter;
-       const gchar  **themes;
-       gint           i;
-
-       combo = GTK_COMBO_BOX (preferences->combobox_chat_theme);
-
-       model = gtk_list_store_new (COL_COMBO_COUNT,
-                                   G_TYPE_STRING,
-                                   G_TYPE_STRING);
-
-       themes = empathy_theme_manager_get_themes ();
-       for (i = 0; themes[i]; i += 2) {
-               gtk_list_store_append (model, &iter);
-               gtk_list_store_set (model, &iter,
-                                   COL_COMBO_VISIBLE_NAME, _(themes[i + 1]),
-                                   COL_COMBO_NAME, themes[i],
-                                   -1);
-       }
-
-       gtk_combo_box_set_model (combo, GTK_TREE_MODEL (model));
-       g_object_unref (model);
-}
-
-static void
-preferences_widget_sync_bool (const gchar *key, GtkWidget *widget)
-{
-       gboolean value;
-
-       if (empathy_conf_get_bool (empathy_conf_get (), key, &value)) {
-               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
-       }
-}
-
-static void
-preferences_widget_sync_int (const gchar *key, GtkWidget *widget)
-{
-       gint value;
-
-       if (empathy_conf_get_int (empathy_conf_get (), key, &value)) {
-               if (GTK_IS_SPIN_BUTTON (widget)) {
-                       gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
-               }
-       }
-}
-
-static void
-preferences_widget_sync_string (const gchar *key, GtkWidget *widget)
-{
-       gchar *value;
-
-       if (empathy_conf_get_string (empathy_conf_get (), key, &value) && value) {
-               if (GTK_IS_ENTRY (widget)) {
-                       gtk_entry_set_text (GTK_ENTRY (widget), value);
-               } else if (GTK_IS_RADIO_BUTTON (widget)) {
-                       if (strcmp (key, EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM) == 0) {
-                               GType        type;
-                               GEnumClass  *enum_class;
-                               GEnumValue  *enum_value;
-                               GSList      *list;
-                               GtkWidget   *toggle_widget;
-                               
-                               /* Get index from new string */
-                               type = empathy_contact_list_store_sort_get_type ();
-                               enum_class = G_ENUM_CLASS (g_type_class_peek (type));
-                               enum_value = g_enum_get_value_by_nick (enum_class, value);
-                               
-                               if (enum_value) { 
-                                       list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
-                                       toggle_widget = g_slist_nth_data (list, enum_value->value);
-                                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_widget), TRUE);
-                               }
-                       } else {
-                               g_warning ("Unhandled key:'%s' just had string change", key);
-                       }
-               }
-
-               g_free (value);
-       }
-}
-
-static void
-preferences_widget_sync_string_combo (const gchar *key, GtkWidget *widget)
-{
-       gchar        *value;
-       GtkTreeModel *model;
-       GtkTreeIter   iter;
-       gboolean      found;
-
-       if (!empathy_conf_get_string (empathy_conf_get (), key, &value)) {
-               return;
-       }
-
-       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
-
-       found = FALSE;
-       if (value && gtk_tree_model_get_iter_first (model, &iter)) {
-               gchar *name;
-
-               do {
-                       gtk_tree_model_get (model, &iter,
-                                           COL_COMBO_NAME, &name,
-                                           -1);
-
-                       if (strcmp (name, value) == 0) {
-                               found = TRUE;
-                               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
-                               break;
-                       } else {
-                               found = FALSE;
-                       }
-
-                       g_free (name);
-               } while (gtk_tree_model_iter_next (model, &iter));
-       }
-
-       /* Fallback to the first one. */
-       if (!found) {
-               if (gtk_tree_model_get_iter_first (model, &iter)) {
-                       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
-               }
-       }
-
-       g_free (value);
-}
-
-static void
-preferences_notify_int_cb (EmpathyConf  *conf,
-                          const gchar *key,
-                          gpointer     user_data)
-{
-       preferences_widget_sync_int (key, user_data);   
-}
-
-static void
-preferences_notify_string_cb (EmpathyConf  *conf,
-                             const gchar *key,
-                             gpointer     user_data)
-{
-       preferences_widget_sync_string (key, user_data);
-}
-
-static void
-preferences_notify_string_combo_cb (EmpathyConf  *conf,
-                                   const gchar *key,
-                                   gpointer     user_data)
-{
-       preferences_widget_sync_string_combo (key, user_data);
-}
-
-static void
-preferences_notify_bool_cb (EmpathyConf  *conf,
-                           const gchar *key,
-                           gpointer     user_data)
-{
-       preferences_widget_sync_bool (key, user_data);
-}
-
-static void
-preferences_notify_sensitivity_cb (EmpathyConf  *conf,
-                                  const gchar *key,
-                                  gpointer     user_data)
-{
-       gboolean value;
-
-       if (empathy_conf_get_bool (conf, key, &value)) {
-               gtk_widget_set_sensitive (GTK_WIDGET (user_data), value);
-       }
-}
-
-static void
-preferences_hookup_spin_button (EmpathyPreferences *preferences,
-                               const gchar       *key,
-                               GtkWidget         *widget)
-{
-       guint id;
-
-       /* Silence warning. */
-       if (0) {
-               preferences_hookup_spin_button (preferences, key, widget);
-       }
-
-       preferences_widget_sync_int (key, widget);
-
-       g_object_set_data_full (G_OBJECT (widget), "key",
-                               g_strdup (key), g_free);
-
-       g_signal_connect (widget,
-                         "value_changed",
-                         G_CALLBACK (preferences_spin_button_value_changed_cb),
-                         NULL);
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                     key,
-                                     preferences_notify_int_cb,
-                                     widget);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-}
-
-static void
-preferences_hookup_entry (EmpathyPreferences *preferences,
-                         const gchar       *key,
-                         GtkWidget         *widget)
-{
-       guint id;
-
-       if (0) {  /* Silent warning before we use this function. */
-               preferences_hookup_entry (preferences, key, widget);
-       }
-
-       preferences_widget_sync_string (key, widget);
-
-       g_object_set_data_full (G_OBJECT (widget), "key",
-                               g_strdup (key), g_free);
-
-       g_signal_connect (widget,
-                         "changed",
-                         G_CALLBACK (preferences_entry_value_changed_cb),
-                         NULL);
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                     key,
-                                     preferences_notify_string_cb,
-                                     widget);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-}
-
-static void
-preferences_hookup_toggle_button (EmpathyPreferences *preferences,
-                                 const gchar       *key,
-                                 GtkWidget         *widget)
-{
-       guint id;
-
-       preferences_widget_sync_bool (key, widget);
-
-       g_object_set_data_full (G_OBJECT (widget), "key",
-                               g_strdup (key), g_free);
-
-       g_signal_connect (widget,
-                         "toggled",
-                         G_CALLBACK (preferences_toggle_button_toggled_cb),
-                         NULL);
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                    key,
-                                    preferences_notify_bool_cb,
-                                    widget);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-}
-
-static void
-preferences_hookup_radio_button (EmpathyPreferences *preferences,
-                                const gchar       *key,
-                                GtkWidget         *widget)
-{
-       GSList *group, *l;
-       guint   id;
-
-       preferences_widget_sync_string (key, widget);
-
-       group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
-       for (l = group; l; l = l->next) {
-               g_signal_connect (l->data,
-                                 "toggled",
-                                 G_CALLBACK (preferences_radio_button_toggled_cb),
-                                 NULL);
-
-               g_object_set_data_full (G_OBJECT (l->data), "key",
-                                       g_strdup (key), g_free);
-       }
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                    key,
-                                    preferences_notify_string_cb,
-                                    widget);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-}
-
-static void
-preferences_hookup_string_combo (EmpathyPreferences *preferences,
-                                const gchar       *key,
-                                GtkWidget         *widget)
-{
-       guint id;
-
-       preferences_widget_sync_string_combo (key, widget);
-
-       g_object_set_data_full (G_OBJECT (widget), "key",
-                               g_strdup (key), g_free);
-
-       g_signal_connect (widget,
-                         "changed",
-                         G_CALLBACK (preferences_string_combo_changed_cb),
-                         NULL);
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                     key,
-                                     preferences_notify_string_combo_cb,
-                                     widget);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-}
-
-static void
-preferences_hookup_sensitivity (EmpathyPreferences *preferences,
-                               const gchar       *key,
-                               GtkWidget         *widget)
-{
-       gboolean value;
-       guint    id;
-
-       if (empathy_conf_get_bool (empathy_conf_get (), key, &value)) {
-               gtk_widget_set_sensitive (widget, value);
-       }
-
-       id = empathy_conf_notify_add (empathy_conf_get (),
-                                     key,
-                                     preferences_notify_sensitivity_cb,
-                                     widget);
-       if (id) {
-               preferences_add_id (preferences, id);
-       }
-}
-
-static void
-preferences_spin_button_value_changed_cb (GtkWidget *button,
-                                         gpointer   user_data)
-{
-       const gchar *key;
-
-       key = g_object_get_data (G_OBJECT (button), "key");
-
-       empathy_conf_set_int (empathy_conf_get (),
-                             key,
-                             gtk_spin_button_get_value (GTK_SPIN_BUTTON (button)));
-}
-
-static void
-preferences_entry_value_changed_cb (GtkWidget *entry,
-                                   gpointer   user_data)
-{
-       const gchar *key;
-
-       key = g_object_get_data (G_OBJECT (entry), "key");
-
-       empathy_conf_set_string (empathy_conf_get (),
-                                key,
-                                gtk_entry_get_text (GTK_ENTRY (entry)));
-}
-
-static void
-preferences_toggle_button_toggled_cb (GtkWidget *button,
-                                     gpointer   user_data)
-{
-       const gchar *key;
-
-       key = g_object_get_data (G_OBJECT (button), "key");
-
-       empathy_conf_set_bool (empathy_conf_get (),
-                              key,
-                              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
-}
-
-static void
-preferences_radio_button_toggled_cb (GtkWidget *button,
-                                    gpointer   user_data)
-{
-       const gchar *key;
-       const gchar *value = NULL;
-
-       if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
-               return;
-       }
-
-       key = g_object_get_data (G_OBJECT (button), "key");
-
-       if (key && strcmp (key, EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM) == 0) {
-               GSList      *group;
-               GType        type;
-               GEnumClass  *enum_class;
-               GEnumValue  *enum_value;
-               
-               group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
-               
-               /* Get string from index */
-               type = empathy_contact_list_store_sort_get_type ();
-               enum_class = G_ENUM_CLASS (g_type_class_peek (type));
-               enum_value = g_enum_get_value (enum_class, g_slist_index (group, button));
-               
-               if (!enum_value) {
-                       g_warning ("No GEnumValue for EmpathyContactListSort with GtkRadioButton index:%d", 
-                                  g_slist_index (group, button));
-                       return;
-               }
-
-               value = enum_value->value_nick;
-       }
-
-       empathy_conf_set_string (empathy_conf_get (), key, value);
-}
-
-static void
-preferences_string_combo_changed_cb (GtkWidget *combo,
-                                    gpointer   user_data)
-{
-       const gchar  *key;
-       GtkTreeModel *model;
-       GtkTreeIter   iter;
-       gchar        *name;
-
-       key = g_object_get_data (G_OBJECT (combo), "key");
-
-       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) {
-               model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
-
-               gtk_tree_model_get (model, &iter,
-                                   COL_COMBO_NAME, &name,
-                                   -1);
-               empathy_conf_set_string (empathy_conf_get (), key, name);
-               g_free (name);
-       }
-}
-
-static void
-preferences_response_cb (GtkWidget         *widget,
-                        gint               response,
-                        EmpathyPreferences *preferences)
-{
-       gtk_widget_destroy (widget);
-}
-
-static void
-preferences_destroy_cb (GtkWidget         *widget,
-                       EmpathyPreferences *preferences)
-{
-       GList *l;
-
-       for (l = preferences->notify_ids; l; l = l->next) {
-               guint id;
-
-               id = GPOINTER_TO_UINT (l->data);
-               empathy_conf_notify_remove (empathy_conf_get (), id);
-       }
-
-       g_list_free (preferences->notify_ids);
-       g_free (preferences);
-}
-
-GtkWidget *
-empathy_preferences_show (GtkWindow *parent)
-{
-       static EmpathyPreferences *preferences;
-       GladeXML                 *glade;
-
-       if (preferences) {
-               gtk_window_present (GTK_WINDOW (preferences->dialog));
-               return preferences->dialog;
-       }
-
-       preferences = g_new0 (EmpathyPreferences, 1);
-
-       glade = empathy_glade_get_file (
-               "empathy-preferences.glade",
-               "preferences_dialog",
-               NULL,
-               "preferences_dialog", &preferences->dialog,
-               "notebook", &preferences->notebook,
-               "checkbutton_show_avatars", &preferences->checkbutton_show_avatars,
-               "checkbutton_compact_contact_list", &preferences->checkbutton_compact_contact_list,
-               "checkbutton_show_smileys", &preferences->checkbutton_show_smileys,
-               "combobox_chat_theme", &preferences->combobox_chat_theme,
-               "checkbutton_theme_chat_room", &preferences->checkbutton_theme_chat_room,
-               "checkbutton_separate_chat_windows", &preferences->checkbutton_separate_chat_windows,
-               "checkbutton_autoconnect", &preferences->checkbutton_autoconnect,
-               "radiobutton_contact_list_sort_by_name", &preferences->radiobutton_contact_list_sort_by_name,
-               "radiobutton_contact_list_sort_by_state", &preferences->radiobutton_contact_list_sort_by_state,
-               "checkbutton_sounds_for_messages", &preferences->checkbutton_sounds_for_messages,
-               "checkbutton_sounds_when_busy", &preferences->checkbutton_sounds_when_busy,
-               "checkbutton_sounds_when_away", &preferences->checkbutton_sounds_when_away,
-               "checkbutton_popups_when_available", &preferences->checkbutton_popups_when_available,
-               "treeview_spell_checker", &preferences->treeview_spell_checker,
-               NULL);
-
-       empathy_glade_connect (glade,
-                             preferences,
-                             "preferences_dialog", "destroy", preferences_destroy_cb,
-                             "preferences_dialog", "response", preferences_response_cb,
-                             NULL);
-
-       g_object_unref (glade);
-
-       g_object_add_weak_pointer (G_OBJECT (preferences->dialog), (gpointer) &preferences);
-
-       preferences_themes_setup (preferences);
-
-       preferences_setup_widgets (preferences);
-
-       preferences_languages_setup (preferences);
-       preferences_languages_add (preferences);
-       preferences_languages_load (preferences);
-
-       if (empathy_spell_supported ()) {
-               GtkWidget *page;
-
-               page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (preferences->notebook), 2);
-               gtk_widget_show (page);
-       }
-
-       if (parent) {
-               gtk_window_set_transient_for (GTK_WINDOW (preferences->dialog),
-                                             GTK_WINDOW (parent));
-       }
-
-       gtk_widget_show (preferences->dialog);
-
-       return preferences->dialog;
-}
-
diff --git a/libempathy-gtk/empathy-preferences.glade b/libempathy-gtk/empathy-preferences.glade
deleted file mode 100644 (file)
index bf03da6..0000000
+++ /dev/null
@@ -1,644 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--*- mode: xml -*-->
-<glade-interface>
-  <widget class="GtkDialog" id="preferences_dialog">
-    <property name="border_width">5</property>
-    <property name="title" translatable="yes">Preferences</property>
-    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
-    <property name="icon_name">gtk-preferences</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="has_separator">False</property>
-    <child internal-child="vbox">
-      <widget class="GtkVBox" id="dialog-vbox5">
-        <property name="visible">True</property>
-        <property name="spacing">2</property>
-        <child>
-          <widget class="GtkNotebook" id="notebook">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="border_width">5</property>
-            <child>
-              <widget class="GtkVBox" id="vbox197">
-                <property name="visible">True</property>
-                <property name="border_width">12</property>
-                <property name="spacing">18</property>
-                <child>
-                  <widget class="GtkFrame" id="frame3">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment11">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox199">
-                            <property name="visible">True</property>
-                            <property name="spacing">6</property>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_compact_contact_list">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Show co_mpact contact list</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_show_avatars">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="tooltip" translatable="yes">Avatars are user chosen images shown in the contact list</property>
-                                <property name="label" translatable="yes">Show _avatars</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="active">True</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_show_smileys">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Show _smileys as images</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="active">True</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label611">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Appearance&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkFrame" id="frame4">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment12">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox218">
-                            <property name="visible">True</property>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_separate_chat_windows">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">_Open new chats in separate windows</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_autoconnect">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Automatically _connect on startup </property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="active">True</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label612">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Behaviour&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkFrame" id="frame13">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment31">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox217">
-                            <property name="visible">True</property>
-                            <child>
-                              <widget class="GtkRadioButton" id="radiobutton_contact_list_sort_by_name">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Sort by _name</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkRadioButton" id="radiobutton_contact_list_sort_by_state">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Sort by s_tate</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                                <property name="group">radiobutton_contact_list_sort_by_name</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label644">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Contact List&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </widget>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label602">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">General</property>
-              </widget>
-              <packing>
-                <property name="type">tab</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkVBox" id="outer_vbox">
-                <property name="visible">True</property>
-                <property name="border_width">12</property>
-                <property name="spacing">18</property>
-                <child>
-                  <widget class="GtkFrame" id="frame5">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment13">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox106">
-                            <property name="visible">True</property>
-                            <property name="spacing">6</property>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_sounds_for_messages">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">_Play sound when messages arrive</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_sounds_when_busy">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Enable sounds when _busy</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <widget class="GtkCheckButton" id="checkbutton_sounds_when_away">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="label" translatable="yes">Enable sounds when _away</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="fill">False</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label613">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Audio&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkFrame" id="frame6">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment14">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkCheckButton" id="checkbutton_popups_when_available">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="label" translatable="yes">Display notifications when contacts come _online</property>
-                            <property name="use_underline">True</property>
-                            <property name="response_id">0</property>
-                            <property name="draw_indicator">True</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label614">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Visual&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label607">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Notifications</property>
-              </widget>
-              <packing>
-                <property name="type">tab</property>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkVBox" id="vbox168">
-                <property name="border_width">12</property>
-                <property name="spacing">18</property>
-                <child>
-                  <widget class="GtkFrame" id="frame7">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment15">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox201">
-                            <property name="visible">True</property>
-                            <property name="spacing">6</property>
-                            <child>
-                              <widget class="GtkHBox" id="hbox153">
-                                <property name="visible">True</property>
-                                <child>
-                                  <widget class="GtkHBox" id="hbox154">
-                                    <property name="visible">True</property>
-                                    <property name="spacing">6</property>
-                                    <child>
-                                      <widget class="GtkScrolledWindow" id="scrolledwindow18">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">False</property>
-                                        <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                                        <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                                        <property name="shadow_type">GTK_SHADOW_IN</property>
-                                        <child>
-                                          <widget class="GtkTreeView" id="treeview_spell_checker">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="headers_visible">False</property>
-                                          </widget>
-                                        </child>
-                                      </widget>
-                                    </child>
-                                  </widget>
-                                </child>
-                              </widget>
-                            </child>
-                            <child>
-                              <widget class="GtkHBox" id="hbox155">
-                                <property name="visible">True</property>
-                                <property name="spacing">6</property>
-                                <child>
-                                  <widget class="GtkImage" id="image422">
-                                    <property name="visible">True</property>
-                                    <property name="yalign">0</property>
-                                    <property name="stock">gtk-dialog-info</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <widget class="GtkLabel" id="label616">
-                                    <property name="visible">True</property>
-                                    <property name="xalign">0</property>
-                                    <property name="label" translatable="yes">&lt;small&gt;The list of languages reflects only the languages for which you have a dictionary installed.&lt;/small&gt;</property>
-                                    <property name="use_markup">True</property>
-                                    <property name="wrap">True</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </widget>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label615">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Enable spell checking for languages:&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                </child>
-                <child>
-                  <placeholder/>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">2</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label567">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Spell Checking</property>
-              </widget>
-              <packing>
-                <property name="type">tab</property>
-                <property name="position">2</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkVBox" id="vbox206">
-                <property name="visible">True</property>
-                <property name="border_width">12</property>
-                <property name="spacing">18</property>
-                <child>
-                  <widget class="GtkFrame" id="frame11">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment19">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkVBox" id="vbox207">
-                            <property name="visible">True</property>
-                            <property name="spacing">6</property>
-                            <child>
-                              <widget class="GtkHBox" id="hbox139">
-                                <property name="visible">True</property>
-                                <property name="spacing">12</property>
-                                <child>
-                                  <widget class="GtkLabel" id="label586">
-                                    <property name="visible">True</property>
-                                    <property name="label" translatable="yes">Chat Th_eme:</property>
-                                    <property name="use_underline">True</property>
-                                    <property name="mnemonic_widget">combobox_chat_theme</property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <widget class="GtkComboBox" id="combobox_chat_theme">
-                                    <property name="visible">True</property>
-                                    <property name="items" translatable="yes"></property>
-                                  </widget>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </widget>
-                            </child>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label626">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Appearance&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <widget class="GtkFrame" id="frame12">
-                    <property name="visible">True</property>
-                    <property name="label_xalign">0</property>
-                    <property name="shadow_type">GTK_SHADOW_NONE</property>
-                    <child>
-                      <widget class="GtkAlignment" id="alignment20">
-                        <property name="visible">True</property>
-                        <property name="top_padding">6</property>
-                        <property name="left_padding">12</property>
-                        <child>
-                          <widget class="GtkCheckButton" id="checkbutton_theme_chat_room">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="label" translatable="yes">_Use for chat rooms</property>
-                            <property name="use_underline">True</property>
-                            <property name="response_id">0</property>
-                            <property name="draw_indicator">True</property>
-                          </widget>
-                        </child>
-                      </widget>
-                    </child>
-                    <child>
-                      <widget class="GtkLabel" id="label627">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">&lt;b&gt;Options&lt;/b&gt;</property>
-                        <property name="use_markup">True</property>
-                      </widget>
-                      <packing>
-                        <property name="type">label_item</property>
-                      </packing>
-                    </child>
-                  </widget>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-              </widget>
-              <packing>
-                <property name="position">3</property>
-              </packing>
-            </child>
-            <child>
-              <widget class="GtkLabel" id="label624">
-                <property name="visible">True</property>
-                <property name="label" translatable="yes">Themes</property>
-              </widget>
-              <packing>
-                <property name="type">tab</property>
-                <property name="position">3</property>
-                <property name="tab_fill">False</property>
-              </packing>
-            </child>
-          </widget>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child internal-child="action_area">
-          <widget class="GtkHButtonBox" id="dialog-action_area5">
-            <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
-            <child>
-              <widget class="GtkButton" id="button_close">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="label">gtk-close</property>
-                <property name="use_stock">True</property>
-                <property name="response_id">-6</property>
-              </widget>
-            </child>
-          </widget>
-          <packing>
-            <property name="expand">False</property>
-            <property name="pack_type">GTK_PACK_END</property>
-          </packing>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/libempathy-gtk/empathy-preferences.h b/libempathy-gtk/empathy-preferences.h
deleted file mode 100644 (file)
index 750666b..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2003-2007 Imendio AB
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors: Mikael Hallendal <micke@imendio.com>
- *          Richard Hult <richard@imendio.com>
- *          Martyn Russell <martyn@imendio.com>
- */
-
-#ifndef __EMPATHY_PREFERENCES_H__
-#define __EMPATHY_PREFERENCES_H__
-
-#include <gtk/gtkwindow.h>
-
-G_BEGIN_DECLS
-
-#define EMPATHY_PREFS_PATH "/apps/empathy"
-
-#define EMPATHY_PREFS_SOUNDS_FOR_MESSAGES          EMPATHY_PREFS_PATH "/notifications/sounds_for_messages"
-#define EMPATHY_PREFS_SOUNDS_WHEN_AWAY             EMPATHY_PREFS_PATH "/notifications/sounds_when_away"
-#define EMPATHY_PREFS_SOUNDS_WHEN_BUSY             EMPATHY_PREFS_PATH "/notifications/sounds_when_busy"
-#define EMPATHY_PREFS_POPUPS_WHEN_AVAILABLE        EMPATHY_PREFS_PATH "/notifications/popups_when_available"
-#define EMPATHY_PREFS_CHAT_SHOW_SMILEYS            EMPATHY_PREFS_PATH "/conversation/graphical_smileys"
-#define EMPATHY_PREFS_CHAT_THEME                   EMPATHY_PREFS_PATH "/conversation/theme"
-#define EMPATHY_PREFS_CHAT_THEME_CHAT_ROOM         EMPATHY_PREFS_PATH "/conversation/theme_chat_room"
-#define EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES EMPATHY_PREFS_PATH "/conversation/spell_checker_languages"
-#define EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED   EMPATHY_PREFS_PATH "/conversation/spell_checker_enabled"
-#define EMPATHY_PREFS_CHAT_NICK_COMPLETION_CHAR    EMPATHY_PREFS_PATH "/conversation/nick_completion_char"
-#define EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS     EMPATHY_PREFS_PATH "/ui/separate_chat_windows"
-#define EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN        EMPATHY_PREFS_PATH "/ui/main_window_hidden"
-#define EMPATHY_PREFS_UI_AVATAR_DIRECTORY          EMPATHY_PREFS_PATH "/ui/avatar_directory"
-#define EMPATHY_PREFS_UI_SHOW_AVATARS              EMPATHY_PREFS_PATH "/ui/show_avatars"
-#define EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST      EMPATHY_PREFS_PATH "/ui/compact_contact_list"
-#define EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE        EMPATHY_PREFS_PATH "/contacts/show_offline"
-#define EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM      EMPATHY_PREFS_PATH "/contacts/sort_criterium"
-#define EMPATHY_PREFS_HINTS_CLOSE_MAIN_WINDOW      EMPATHY_PREFS_PATH "/hints/close_main_window"
-#define EMPATHY_PREFS_SALUT_ACCOUNT_CREATED        EMPATHY_PREFS_PATH "/accounts/salut_created"
-#define EMPATHY_PREFS_USE_NM                       EMPATHY_PREFS_PATH "/use_nm"
-#define EMPATHY_PREFS_AUTOCONNECT                  EMPATHY_PREFS_PATH "/autoconnect"
-
-GtkWidget * empathy_preferences_show (GtkWindow *parent);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_PREFERENCES_H__ */
-
-
index 9f84c1273db1bfa3b2d47826a50bffb7b33ec800..a9fe6357bf3ca773671144d67976f96faee5c4fd 100644 (file)
@@ -45,7 +45,6 @@
 #include "empathy-private-chat.h"
 #include "empathy-chat-view.h"
 #include "empathy-chat.h"
-#include "empathy-preferences.h"
 //#include "empathy-sound.h"
 #include "empathy-images.h"
 #include "empathy-ui-utils.h"
index b6620118ad8e91ddb289388786a1a8dc88081715..db32332943b5b2211b5f27f377d17030984d8974 100644 (file)
@@ -36,7 +36,6 @@
 
 #include "empathy-spell.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 
 #define DEBUG_DOMAIN "Spell"
 
diff --git a/libempathy-gtk/empathy-status-icon.c b/libempathy-gtk/empathy-status-icon.c
deleted file mode 100644 (file)
index 241a284..0000000
+++ /dev/null
@@ -1,862 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007-2008 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-#include <glib/gi18n.h>
-
-#include <libmissioncontrol/mission-control.h>
-
-#include <libempathy/empathy-contact-list.h>
-#include <libempathy/empathy-contact-manager.h>
-#include <libempathy/empathy-contact.h>
-#include <libempathy/empathy-tp-chat.h>
-#include <libempathy/empathy-debug.h>
-#include <libempathy/empathy-utils.h>
-#include <libempathy/empathy-idle.h>
-#include <libempathy/empathy-filter.h>
-
-#include "empathy-status-icon.h"
-#include "empathy-contact-dialogs.h"
-#include "empathy-presence-chooser.h"
-#include "empathy-conf.h"
-#include "empathy-preferences.h"
-#include "empathy-ui-utils.h"
-#include "empathy-accounts-dialog.h"
-#include "empathy-images.h"
-#include "empathy-new-message-dialog.h"
-
-
-#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
-                      EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconPriv))
-
-#define DEBUG_DOMAIN "StatusIcon"
-
-/* Number of ms to wait when blinking */
-#define BLINK_TIMEOUT 500
-
-typedef struct _StatusIconEvent StatusIconEvent;
-
-struct _EmpathyStatusIconPriv {
-       GtkStatusIcon         *icon;
-       EmpathyContactManager *manager;
-       EmpathyFilter         *text_filter;
-       EmpathyFilter         *call_filter;
-       EmpathyIdle           *idle;
-       MissionControl        *mc;
-       GList                 *events;
-       gboolean               showing_event_icon;
-       StatusIconEvent       *flash_state_event;
-       guint                  blink_timeout;
-
-       GtkWindow             *window;
-       GtkWidget             *popup_menu;
-       GtkWidget             *show_window_item;
-       GtkWidget             *message_item;
-       GtkWidget             *status_item;
-};
-
-typedef void (*EventActivatedFunc) (StatusIconEvent *event);
-
-struct _StatusIconEvent {
-       gchar              *icon_name;
-       gchar              *message;
-       EventActivatedFunc  func;
-       gpointer            user_data;
-};
-
-
-static void       empathy_status_icon_class_init  (EmpathyStatusIconClass *klass);
-static void       empathy_status_icon_init        (EmpathyStatusIcon      *icon);
-static void       status_icon_finalize            (GObject                *object);
-static void       status_icon_text_filter_new_channel (EmpathyFilter          *filter,
-                                                  TpConn                 *tp_conn,
-                                                  TpChan                 *tp_chan,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_call_filter_new_channel (EmpathyFilter          *filter,
-                                                  TpConn                 *tp_conn,
-                                                  TpChan                 *tp_chan,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_message_received_cb (EmpathyTpChat          *tp_chat,
-                                                  EmpathyMessage         *message,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_idle_notify_cb      (EmpathyStatusIcon      *icon);
-static void       status_icon_update_tooltip      (EmpathyStatusIcon      *icon);
-static void       status_icon_set_from_state      (EmpathyStatusIcon      *icon);
-static void       status_icon_set_visibility      (EmpathyStatusIcon      *icon,
-                                                  gboolean                visible,
-                                                  gboolean                store);
-static void       status_icon_toggle_visibility   (EmpathyStatusIcon      *icon);
-static void       status_icon_activate_cb         (GtkStatusIcon          *status_icon,
-                                                  EmpathyStatusIcon      *icon);
-static gboolean   status_icon_delete_event_cb     (GtkWidget              *widget,
-                                                  GdkEvent               *event,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_popup_menu_cb       (GtkStatusIcon          *status_icon,
-                                                  guint                   button,
-                                                  guint                   activate_time,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_create_menu         (EmpathyStatusIcon      *icon);
-static void       status_icon_new_message_cb      (GtkWidget              *widget,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_quit_cb             (GtkWidget              *window,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_show_hide_window_cb (GtkWidget              *widget,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_pendings_changed_cb (EmpathyContactManager  *manager,
-                                                  EmpathyContact         *contact,
-                                                  EmpathyContact         *actor,
-                                                  guint                   reason,
-                                                  gchar                  *message,
-                                                  gboolean                is_pending,
-                                                  EmpathyStatusIcon      *icon);
-static void       status_icon_event_subscribe_cb  (StatusIconEvent        *event);
-static void       status_icon_event_flash_state_cb (StatusIconEvent       *event);
-static void       status_icon_event_msg_cb        (StatusIconEvent        *event);
-static StatusIconEvent * status_icon_event_new    (EmpathyStatusIcon      *icon,
-                                                  const gchar            *icon_name,
-                                                  const gchar            *message);
-static void       status_icon_event_remove        (EmpathyStatusIcon      *icon,
-                                                  StatusIconEvent        *event);
-static gboolean   status_icon_event_timeout_cb    (EmpathyStatusIcon      *icon);
-static void       status_icon_event_free          (StatusIconEvent        *event);
-
-G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
-
-static void
-status_icon_notify_use_nm_cb (EmpathyConf  *conf,
-                             const gchar *key,
-                             gpointer     user_data)
-{
-       EmpathyStatusIconPriv *priv = GET_PRIV (user_data);
-       gboolean               use_nm;
-
-       if (empathy_conf_get_bool (conf, key, &use_nm)) {
-               empathy_idle_set_use_nm (priv->idle, use_nm);
-       }
-}
-
-static void
-status_icon_notify_visibility_cb (EmpathyConf *conf,
-                                 const gchar *key,
-                                 gpointer     user_data)
-{
-       EmpathyStatusIcon *icon = user_data;
-       gboolean           hidden = FALSE;
-
-       if (empathy_conf_get_bool (conf, key, &hidden)) {
-               status_icon_set_visibility (icon, !hidden, FALSE);
-       }
-}
-
-static void
-empathy_status_icon_class_init (EmpathyStatusIconClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       object_class->finalize = status_icon_finalize;
-
-       g_type_class_add_private (object_class, sizeof (EmpathyStatusIconPriv));
-}
-
-static void
-empathy_status_icon_init (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       GList                 *pendings, *l;
-       gboolean               use_nm;
-
-       priv = GET_PRIV (icon);
-
-       priv->icon = gtk_status_icon_new ();
-       priv->manager = empathy_contact_manager_new ();
-       priv->mc = empathy_mission_control_new ();
-       priv->text_filter = empathy_filter_new ("org.gnome.Empathy.ChatFilter",
-                                               "/org/gnome/Empathy/ChatFilter",
-                                               TP_IFACE_CHANNEL_TYPE_TEXT,
-                                               MC_FILTER_PRIORITY_DIALOG,
-                                               MC_FILTER_FLAG_INCOMING);
-       priv->call_filter = empathy_filter_new ("org.gnome.Empathy.CallFilter",
-                                               "/org/gnome/Empathy/CallFilter",
-                                               TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
-                                               MC_FILTER_PRIORITY_DIALOG,
-                                               MC_FILTER_FLAG_INCOMING);
-
-       /* Setup EmpathyIdle */
-       priv->idle = empathy_idle_new ();
-       empathy_conf_get_bool (empathy_conf_get (),
-                              EMPATHY_PREFS_USE_NM,
-                              &use_nm);
-       empathy_conf_notify_add (empathy_conf_get (),
-                                EMPATHY_PREFS_USE_NM,
-                                status_icon_notify_use_nm_cb,
-                                icon);
-       empathy_idle_set_auto_away (priv->idle, TRUE);
-       empathy_idle_set_use_nm (priv->idle, use_nm);
-
-       /* make icon listen and respond to MAIN_WINDOW_HIDDEN changes */
-       empathy_conf_notify_add (empathy_conf_get (),
-                                EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
-                                status_icon_notify_visibility_cb,
-                                icon);
-
-       status_icon_create_menu (icon);
-       status_icon_idle_notify_cb (icon);
-
-       g_signal_connect (priv->text_filter, "new-channel",
-                         G_CALLBACK (status_icon_text_filter_new_channel),
-                         icon);
-       g_signal_connect (priv->call_filter, "new-channel",
-                         G_CALLBACK (status_icon_call_filter_new_channel),
-                         icon);
-       g_signal_connect_swapped (priv->idle, "notify",
-                                 G_CALLBACK (status_icon_idle_notify_cb),
-                                 icon);
-       g_signal_connect (priv->icon, "activate",
-                         G_CALLBACK (status_icon_activate_cb),
-                         icon);
-       g_signal_connect (priv->icon, "popup-menu",
-                         G_CALLBACK (status_icon_popup_menu_cb),
-                         icon);
-       g_signal_connect (priv->manager, "pendings-changed",
-                         G_CALLBACK (status_icon_pendings_changed_cb),
-                         icon);
-
-       pendings = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (priv->manager));
-       for (l = pendings; l; l = l->next) {
-               EmpathyPendingInfo *info;
-
-               info = l->data;
-               status_icon_pendings_changed_cb (priv->manager,
-                                                info->member,
-                                                info->actor,
-                                                0,
-                                                info->message,
-                                                TRUE,
-                                                icon);
-               empathy_pending_info_free (info);
-       }
-       g_list_free (pendings);
-}
-
-static void
-status_icon_finalize (GObject *object)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (object);
-
-       g_list_foreach (priv->events, (GFunc) status_icon_event_free, NULL);
-       g_list_free (priv->events);
-
-       if (priv->blink_timeout) {
-               g_source_remove (priv->blink_timeout);
-       }
-
-       g_object_unref (priv->icon);
-       g_object_unref (priv->window);
-       g_object_unref (priv->idle);
-       g_object_unref (priv->manager);
-       g_object_unref (priv->mc);
-       g_object_unref (priv->text_filter);
-       g_object_unref (priv->call_filter);
-}
-
-EmpathyStatusIcon *
-empathy_status_icon_new (GtkWindow *window)
-{
-       EmpathyStatusIconPriv *priv;
-       EmpathyStatusIcon     *icon;
-       gboolean               should_hide;
-
-       g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
-
-       icon = g_object_new (EMPATHY_TYPE_STATUS_ICON, NULL);
-       priv = GET_PRIV (icon);
-
-       priv->window = g_object_ref (window);
-
-       g_signal_connect (priv->window, "delete-event",
-                         G_CALLBACK (status_icon_delete_event_cb),
-                         icon);
-
-       empathy_conf_get_bool (empathy_conf_get (),
-                             EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
-                             &should_hide);
-
-       if (gtk_window_is_active (priv->window) == should_hide) {
-               status_icon_set_visibility (icon, !should_hide, FALSE);
-       }
-
-       return icon;
-}
-
-static void
-status_icon_text_filter_new_channel (EmpathyFilter     *filter,
-                                    TpConn            *tp_conn,
-                                    TpChan            *tp_chan,
-                                    EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       McAccount             *account;
-       EmpathyTpChat         *tp_chat;
-
-       priv = GET_PRIV (icon);
-
-       account = mission_control_get_account_for_connection (priv->mc, tp_conn, NULL);
-
-       empathy_debug (DEBUG_DOMAIN, "New text channel to be filtered for contact %s",
-                      empathy_inspect_channel (account, tp_chan));
-
-       tp_chat = empathy_tp_chat_new (account, tp_chan);
-       g_object_set_data (G_OBJECT (tp_chat), "filter", filter);
-       g_object_unref (account);
-
-       g_signal_connect (tp_chat, "message-received",
-                         G_CALLBACK (status_icon_message_received_cb),
-                         icon);
-}
-
-static void
-status_icon_message_received_cb (EmpathyTpChat     *tp_chat,
-                                EmpathyMessage    *message,
-                                EmpathyStatusIcon *icon)
-{
-       EmpathyContact  *sender;
-       gchar           *msg;
-       StatusIconEvent *event;
-
-       empathy_debug (DEBUG_DOMAIN, "Message received, add event");
-
-       g_signal_handlers_disconnect_by_func (tp_chat,
-                                             status_icon_message_received_cb,
-                                             icon);
-
-       sender = empathy_message_get_sender (message);
-       msg = g_strdup_printf (_("New message from %s:\n%s"),
-                              empathy_contact_get_name (sender),
-                              empathy_message_get_body (message));
-
-       event = status_icon_event_new (icon, EMPATHY_IMAGE_NEW_MESSAGE, msg);
-       event->func = status_icon_event_msg_cb;
-       event->user_data = tp_chat;
-       g_free (msg);
-}
-
-static void
-status_icon_call_member_added_cb (EmpathyTpGroup    *group,
-                                 EmpathyContact    *member,
-                                 EmpathyContact    *actor,
-                                 guint              reason,
-                                 const gchar       *message,
-                                 EmpathyStatusIcon *icon)
-{
-       EmpathyFilter *filter;
-
-       if (empathy_contact_is_user (member)) {
-               /* We are member, it's an outgoing call, we can dispatch
-                * the channel without asking the user */
-               empathy_debug (DEBUG_DOMAIN, "Process OUTGOING call channel");
-               filter = g_object_get_data (G_OBJECT (group), "filter");
-               empathy_filter_process (filter,
-                                       empathy_tp_group_get_channel (group),
-                                       TRUE);
-               g_object_unref (group);
-       }
-}
-
-static void
-status_icon_event_call_cb (StatusIconEvent *event)
-{
-       EmpathyFilter  *filter;
-       EmpathyTpGroup *group;
-
-       empathy_debug (DEBUG_DOMAIN, "Dispatching call channel");
-
-       group = event->user_data;
-       filter = g_object_get_data (G_OBJECT (group), "filter");
-       empathy_filter_process (filter,
-                               empathy_tp_group_get_channel (group),
-                               TRUE);
-       g_object_unref (group);
-}
-
-static void
-status_icon_call_local_pending_cb (EmpathyTpGroup    *group,
-                                  EmpathyContact    *member,
-                                  EmpathyContact    *actor,
-                                  guint              reason,
-                                  const gchar       *message,
-                                  EmpathyStatusIcon *icon)
-{
-       StatusIconEvent *event;
-
-       if (empathy_contact_is_user (member)) {
-               gchar *msg;
-
-               /* We are local pending, it's an incoming call, we need to ask
-                * the user if he wants to accept the call. */
-               empathy_contact_run_until_ready (member,
-                                                EMPATHY_CONTACT_READY_NAME,
-                                                NULL);
-
-               empathy_debug (DEBUG_DOMAIN, "INCOMING call, add event");
-
-               msg = g_strdup_printf (_("Incoming call from %s:\n%s"),
-                                      empathy_contact_get_name (member),
-                                      message);
-
-               event = status_icon_event_new (icon, EMPATHY_IMAGE_VOIP, msg);
-               event->func = status_icon_event_call_cb;
-               event->user_data = group;
-               g_free (msg);
-       }
-}
-
-static void
-status_icon_call_filter_new_channel (EmpathyFilter     *filter,
-                                    TpConn            *tp_conn,
-                                    TpChan            *tp_chan,
-                                    EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       McAccount             *account;
-       EmpathyTpGroup        *group;
-
-       priv = GET_PRIV (icon);
-
-       account = mission_control_get_account_for_connection (priv->mc, tp_conn, NULL);
-
-       empathy_debug (DEBUG_DOMAIN, "New media channel to be filtered");
-
-       /* FIXME: We have to check if the user is member or local-pending to
-        * know if it's an incoming or outgoing call because of the way we
-        * request media channels MC can't know if it's incoming or outgoing */
-       group = empathy_tp_group_new (account, tp_chan);
-       g_object_set_data (G_OBJECT (group), "filter", filter);
-       g_object_unref (account);
-
-       g_signal_connect (group, "member-added",
-                         G_CALLBACK (status_icon_call_member_added_cb),
-                         icon);
-       g_signal_connect (group, "local-pending",
-                         G_CALLBACK (status_icon_call_local_pending_cb),
-                         icon);
-}
-
-static void
-status_icon_idle_notify_cb (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       McPresence             flash_state;
-
-       priv = GET_PRIV (icon);
-
-       flash_state = empathy_idle_get_flash_state (priv->idle);
-       if (flash_state != MC_PRESENCE_UNSET) {
-               const gchar *icon_name;
-
-               icon_name = empathy_icon_name_for_presence (flash_state);
-               if (!priv->flash_state_event) {
-                       /* We are now flashing */
-                       priv->flash_state_event = status_icon_event_new (icon, icon_name, NULL);
-                       priv->flash_state_event->user_data = icon;
-                       priv->flash_state_event->func = status_icon_event_flash_state_cb;
-               } else {
-                       /* We are still flashing but with another state */
-                       g_free (priv->flash_state_event->icon_name);
-                       priv->flash_state_event->icon_name = g_strdup (icon_name);
-               }
-       }
-       else if (priv->flash_state_event) {
-               /* We are no more flashing */
-               status_icon_event_remove (icon, priv->flash_state_event);
-               priv->flash_state_event = NULL;
-       }
-
-       if (!priv->showing_event_icon) {
-               status_icon_set_from_state (icon);
-       }
-
-       status_icon_update_tooltip (icon);
-}
-
-static void
-status_icon_update_tooltip (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       const gchar           *tooltip = NULL;
-
-       priv = GET_PRIV (icon);
-
-       if (priv->events) {
-               StatusIconEvent *event;
-
-               event = priv->events->data;
-               tooltip = event->message;
-       }
-
-       if (!tooltip) {
-               tooltip = empathy_idle_get_status (priv->idle);
-       }
-
-       gtk_status_icon_set_tooltip (priv->icon, tooltip);      
-}
-
-static void
-status_icon_set_from_state (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       McPresence             state;
-       const gchar           *icon_name;
-
-       priv = GET_PRIV (icon);
-
-       state = empathy_idle_get_state (priv->idle);
-       icon_name = empathy_icon_name_for_presence (state);
-       gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
-}
-
-static void
-status_icon_set_visibility (EmpathyStatusIcon *icon,
-                           gboolean           visible,
-                           gboolean           store)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (icon);
-
-       if (store) {
-               empathy_conf_set_bool (empathy_conf_get (),
-                                      EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN, !visible);
-       }
-
-       if (!visible) {
-               empathy_window_iconify (priv->window, priv->icon);
-       } else {
-               GList *accounts;
-
-               empathy_window_present (GTK_WINDOW (priv->window), TRUE);
-       
-               /* Show the accounts dialog if there is no enabled accounts */
-               accounts = mc_accounts_list_by_enabled (TRUE);
-               if (accounts) {
-                       mc_accounts_list_free (accounts);
-               } else {
-                       empathy_debug (DEBUG_DOMAIN,
-                                     "No enabled account, Showing account dialog");
-                       empathy_accounts_dialog_show (GTK_WINDOW (priv->window));
-               }
-       }
-}
-
-static void
-status_icon_toggle_visibility (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv = GET_PRIV (icon);
-       gboolean               visible;
-
-       visible = gtk_window_is_active (priv->window);
-       status_icon_set_visibility (icon, !visible, TRUE);
-}
-
-static void
-status_icon_activate_cb (GtkStatusIcon     *status_icon,
-                        EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (icon);
-
-       empathy_debug (DEBUG_DOMAIN, "Activated: %s",
-                      priv->events ? "event" : "toggle");
-
-       if (priv->events) {
-               status_icon_event_remove (icon, priv->events->data);
-       } else {
-               status_icon_toggle_visibility (icon);
-       }
-}
-
-static gboolean
-status_icon_delete_event_cb (GtkWidget         *widget,
-                            GdkEvent          *event,
-                            EmpathyStatusIcon *icon)
-{
-       status_icon_set_visibility (icon, FALSE, TRUE);
-
-       return TRUE;
-}
-
-static void
-status_icon_popup_menu_cb (GtkStatusIcon     *status_icon,
-                          guint              button,
-                          guint              activate_time,
-                          EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       GtkWidget             *submenu;
-       gboolean               show;
-
-       priv = GET_PRIV (icon);
-
-       show = empathy_window_get_is_visible (GTK_WINDOW (priv->window));
-
-       g_signal_handlers_block_by_func (priv->show_window_item,
-                                        status_icon_show_hide_window_cb,
-                                        icon);
-       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (priv->show_window_item),
-                                       show);
-       g_signal_handlers_unblock_by_func (priv->show_window_item,
-                                          status_icon_show_hide_window_cb,
-                                          icon);
-
-       submenu = empathy_presence_chooser_create_menu ();
-       gtk_menu_item_set_submenu (GTK_MENU_ITEM (priv->status_item),
-                                  submenu);
-
-       gtk_menu_popup (GTK_MENU (priv->popup_menu),
-                       NULL, NULL,
-                       gtk_status_icon_position_menu,
-                       priv->icon,
-                       button,
-                       activate_time);
-}
-
-static void
-status_icon_create_menu (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       GladeXML              *glade;
-
-       priv = GET_PRIV (icon);
-
-       glade = empathy_glade_get_file ("empathy-status-icon.glade",
-                                      "tray_menu",
-                                      NULL,
-                                      "tray_menu", &priv->popup_menu,
-                                      "tray_show_list", &priv->show_window_item,
-                                      "tray_new_message", &priv->message_item,
-                                      "tray_status", &priv->status_item,
-                                      NULL);
-
-       empathy_glade_connect (glade,
-                             icon,
-                             "tray_show_list", "toggled", status_icon_show_hide_window_cb,
-                             "tray_new_message", "activate", status_icon_new_message_cb,
-                             "tray_quit", "activate", status_icon_quit_cb,
-                             NULL);
-
-       g_object_unref (glade);
-}
-
-static void
-status_icon_new_message_cb (GtkWidget         *widget,
-                           EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (icon);
-
-       empathy_new_message_dialog_show (NULL);
-}
-
-static void
-status_icon_quit_cb (GtkWidget         *window,
-                    EmpathyStatusIcon *icon)
-{
-       gtk_main_quit ();
-}
-
-static void
-status_icon_show_hide_window_cb (GtkWidget         *widget,
-                                EmpathyStatusIcon *icon)
-{
-       gboolean visible;
-
-       visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
-       status_icon_set_visibility (icon, visible, TRUE);
-}
-
-static void
-status_icon_pendings_changed_cb (EmpathyContactManager *manager,
-                                EmpathyContact        *contact,
-                                EmpathyContact        *actor,
-                                guint                  reason,
-                                gchar                 *message,
-                                gboolean               is_pending,
-                                EmpathyStatusIcon     *icon)
-{
-       EmpathyStatusIconPriv *priv;
-       StatusIconEvent       *event;
-       GString               *str;
-
-       priv = GET_PRIV (icon);
-
-       if (!is_pending) {
-               /* FIXME: We should remove the event */
-               return;
-       }
-
-       empathy_contact_run_until_ready (contact,
-                                        EMPATHY_CONTACT_READY_NAME,
-                                        NULL);
-
-       str = g_string_new (NULL);
-       g_string_printf (str, _("Subscription requested by %s"),
-                        empathy_contact_get_name (contact));   
-       if (!G_STR_EMPTY (message)) {
-               g_string_append_printf (str, _("\nMessage: %s"), message);
-       }
-
-       event = status_icon_event_new (icon, GTK_STOCK_DIALOG_QUESTION, str->str);
-       event->user_data = g_object_ref (contact);
-       event->func = status_icon_event_subscribe_cb;
-
-       g_string_free (str, TRUE);
-}
-
-static void
-status_icon_event_subscribe_cb (StatusIconEvent *event)
-{
-       EmpathyContact *contact;
-
-       contact = EMPATHY_CONTACT (event->user_data);
-
-       empathy_subscription_dialog_show (contact, NULL);
-
-       g_object_unref (contact);
-}
-
-static void
-status_icon_event_flash_state_cb (StatusIconEvent *event)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (event->user_data);
-
-       empathy_idle_set_flash_state (priv->idle, MC_PRESENCE_UNSET);
-}
-
-static void
-status_icon_event_msg_cb (StatusIconEvent *event)
-{
-       EmpathyFilter *filter;
-       EmpathyTpChat *tp_chat;
-
-       empathy_debug (DEBUG_DOMAIN, "Dispatching text channel");
-
-       tp_chat = event->user_data;
-       filter = g_object_get_data (G_OBJECT (tp_chat), "filter");
-       empathy_filter_process (filter,
-                               empathy_tp_chat_get_channel (tp_chat),
-                               TRUE);
-
-       g_object_unref (tp_chat);
-}
-
-static StatusIconEvent *
-status_icon_event_new (EmpathyStatusIcon *icon,
-                      const gchar       *icon_name,
-                      const gchar       *message)
-{
-       EmpathyStatusIconPriv *priv;
-       StatusIconEvent       *event;
-
-       priv = GET_PRIV (icon);
-
-       event = g_slice_new0 (StatusIconEvent);
-       event->icon_name = g_strdup (icon_name);        
-       event->message = g_strdup (message);
-
-       priv->events = g_list_append (priv->events, event);
-       if (!priv->blink_timeout) {
-               priv->showing_event_icon = FALSE;
-               priv->blink_timeout = g_timeout_add (BLINK_TIMEOUT,
-                                                    (GSourceFunc) status_icon_event_timeout_cb,
-                                                    icon);
-               status_icon_event_timeout_cb (icon);
-               status_icon_update_tooltip (icon);
-       }
-
-       return event;
-}
-
-static void
-status_icon_event_remove (EmpathyStatusIcon *icon,
-                         StatusIconEvent   *event)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (icon);
-
-       if (event->func) {
-               event->func (event);
-       }
-       priv->events = g_list_remove (priv->events, event);
-       status_icon_event_free (event);
-       priv->showing_event_icon = FALSE;
-       status_icon_update_tooltip (icon);
-       status_icon_set_from_state (icon);
-
-       if (priv->events) {
-               return;
-       }
-
-       if (priv->blink_timeout) {
-               g_source_remove (priv->blink_timeout);
-               priv->blink_timeout = 0;
-       }
-}
-
-static gboolean
-status_icon_event_timeout_cb (EmpathyStatusIcon *icon)
-{
-       EmpathyStatusIconPriv *priv;
-
-       priv = GET_PRIV (icon);
-
-       priv->showing_event_icon = !priv->showing_event_icon;
-
-       if (!priv->showing_event_icon) {
-               status_icon_set_from_state (icon);
-       } else {
-               StatusIconEvent *event;
-
-               event = priv->events->data;
-               gtk_status_icon_set_from_icon_name (priv->icon, event->icon_name);
-       }
-
-       return TRUE;
-}
-
-static void
-status_icon_event_free (StatusIconEvent *event)
-{
-       g_free (event->icon_name);
-       g_free (event->message);
-       g_slice_free (StatusIconEvent, event);
-}
-
diff --git a/libempathy-gtk/empathy-status-icon.glade b/libempathy-gtk/empathy-status-icon.glade
deleted file mode 100644 (file)
index ab0f09f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--*- mode: xml -*-->
-<glade-interface>
-  <widget class="GtkMenu" id="tray_menu">
-    <child>
-      <widget class="GtkCheckMenuItem" id="tray_show_list">
-        <property name="visible">True</property>
-        <property name="label" translatable="yes">_Show Contact List</property>
-        <property name="use_underline">True</property>
-      </widget>
-    </child>
-    <child>
-      <widget class="GtkSeparatorMenuItem" id="avskiljare5">
-        <property name="visible">True</property>
-      </widget>
-    </child>
-    <child>
-      <widget class="GtkImageMenuItem" id="tray_new_message">
-        <property name="visible">True</property>
-        <property name="label" translatable="yes">_New Conversation...</property>
-        <property name="use_underline">True</property>
-        <child internal-child="image">
-          <widget class="GtkImage" id="image599">
-            <property name="visible">True</property>
-            <property name="icon_size">1</property>
-            <property name="icon_name">im-message-new</property>
-          </widget>
-        </child>
-      </widget>
-    </child>
-    <child>
-      <widget class="GtkMenuItem" id="tray_status">
-        <property name="visible">True</property>
-        <property name="label" translatable="yes">Status</property>
-        <property name="use_underline">True</property>
-      </widget>
-    </child>
-    <child>
-      <widget class="GtkSeparatorMenuItem" id="avskiljare6">
-        <property name="visible">True</property>
-      </widget>
-    </child>
-    <child>
-      <widget class="GtkImageMenuItem" id="tray_quit">
-        <property name="visible">True</property>
-        <property name="label" translatable="yes">_Quit</property>
-        <property name="use_underline">True</property>
-        <child internal-child="image">
-          <widget class="GtkImage" id="image600">
-            <property name="visible">True</property>
-            <property name="stock">gtk-quit</property>
-            <property name="icon_size">1</property>
-          </widget>
-        </child>
-      </widget>
-    </child>
-  </widget>
-</glade-interface>
diff --git a/libempathy-gtk/empathy-status-icon.h b/libempathy-gtk/empathy-status-icon.h
deleted file mode 100644 (file)
index a7ca3c3..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Authors: Xavier Claessens <xclaesse@gmail.com>
- */
-
-#ifndef __EMPATHY_STATUS_ICON_H__
-#define __EMPATHY_STATUS_ICON_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-#define EMPATHY_TYPE_STATUS_ICON         (empathy_status_icon_get_type ())
-#define EMPATHY_STATUS_ICON(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIcon))
-#define EMPATHY_STATUS_ICON_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconClass))
-#define EMPATHY_IS_STATUS_ICON(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_STATUS_ICON))
-#define EMPATHY_IS_STATUS_ICON_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_STATUS_ICON))
-#define EMPATHY_STATUS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconClass))
-
-typedef struct _EmpathyStatusIcon      EmpathyStatusIcon;
-typedef struct _EmpathyStatusIconClass EmpathyStatusIconClass;
-typedef struct _EmpathyStatusIconPriv  EmpathyStatusIconPriv;
-
-struct _EmpathyStatusIcon {
-       GObject      parent;
-};
-
-struct _EmpathyStatusIconClass {
-       GObjectClass parent_class;
-};
-
-GType              empathy_status_icon_get_type (void) G_GNUC_CONST;
-EmpathyStatusIcon *empathy_status_icon_new      (GtkWindow *window);
-
-G_END_DECLS
-
-#endif /* __EMPATHY_STATUS_ICON_H__ */
index ebbc18e173422865d0a1d967e04d78679dcd19e5..797cb432496da4e0b3d12837d7db2ed383d430f3 100644 (file)
@@ -28,7 +28,6 @@
 #include <libempathy/empathy-debug.h>
 
 #include "empathy-ui-utils.h"
-#include "empathy-main-window.h"
 #include "empathy-theme-boxes.h"
 
 #define DEBUG_DOMAIN "FancyTheme"
index 94276c964a5155cb0a56361e2a9df2eb00c5d5d6..490fe6ace87faa9c28e83c9e2e69be6a9b4c8eb6 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "empathy-chat-view.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 #include "empathy-theme.h"
 #include "empathy-theme-boxes.h"
 #include "empathy-theme-irc.h"
index dae690b5c002c37052ee52b7f30e5861533610be..5d8e1b80a3ecfcf4ba47538e525b5ee6bdebbe9f 100644 (file)
@@ -29,7 +29,6 @@
 
 #include "empathy-chat.h"
 #include "empathy-conf.h"
-#include "empathy-preferences.h"
 #include "empathy-theme.h"
 #include "empathy-smiley-manager.h"
 
diff --git a/libempathy-gtk/ephy-spinner.c b/libempathy-gtk/ephy-spinner.c
deleted file mode 100644 (file)
index a8f371d..0000000
+++ /dev/null
@@ -1,977 +0,0 @@
-/* 
- * Copyright © 2000 Eazel, Inc.
- * Copyright © 2002-2004 Marco Pesenti Gritti
- * Copyright © 2004, 2006 Christian Persch
- *
- * Nautilus is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Nautilus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Andy Hertzfeld <andy@eazel.com>
- *
- * Ephy port by Marco Pesenti Gritti <marco@it.gnome.org>
- * 
- * $Id: ephy-spinner.c 2114 2006-12-25 12:15:00Z mr $
- */
-
-#include "config.h"
-
-#include "ephy-spinner.h"
-
-/* #include "ephy-debug.h" */
-#define LOG(msg, args...)
-#define START_PROFILER(name)
-#define STOP_PROFILER(name)
-
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <gtk/gtkicontheme.h>
-#include <gtk/gtkiconfactory.h>
-#include <gtk/gtksettings.h>
-
-/* Spinner cache implementation */
-
-#define EPHY_TYPE_SPINNER_CACHE                        (ephy_spinner_cache_get_type())
-#define EPHY_SPINNER_CACHE(object)             (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCache))
-#define EPHY_SPINNER_CACHE_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCacheClass))
-#define EPHY_IS_SPINNER_CACHE(object)          (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_SPINNER_CACHE))
-#define EPHY_IS_SPINNER_CACHE_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_SPINNER_CACHE))
-#define EPHY_SPINNER_CACHE_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCacheClass))
-
-typedef struct _EphySpinnerCache       EphySpinnerCache;
-typedef struct _EphySpinnerCacheClass  EphySpinnerCacheClass;
-typedef struct _EphySpinnerCachePrivate        EphySpinnerCachePrivate;
-
-struct _EphySpinnerCacheClass
-{
-       GObjectClass parent_class;
-};
-
-struct _EphySpinnerCache
-{
-       GObject parent_object;
-
-       /*< private >*/
-       EphySpinnerCachePrivate *priv;
-};
-
-#define EPHY_SPINNER_CACHE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCachePrivate))
-
-struct _EphySpinnerCachePrivate
-{
-       /* Hash table of GdkScreen -> EphySpinnerCacheData */
-       GHashTable *hash;
-};
-
-typedef struct
-{
-       guint ref_count;
-       GtkIconSize size;
-       int width;
-       int height;
-       GdkPixbuf **animation_pixbufs;
-       guint n_animation_pixbufs;
-} EphySpinnerImages;
-
-#define LAST_ICON_SIZE                 GTK_ICON_SIZE_DIALOG + 1
-#define SPINNER_ICON_NAME              "process-working"
-#define SPINNER_FALLBACK_ICON_NAME     "gnome-spinner"
-#define EPHY_SPINNER_IMAGES_INVALID    ((EphySpinnerImages *) 0x1)
-
-typedef struct
-{
-       GdkScreen *screen;
-       GtkIconTheme *icon_theme;
-       EphySpinnerImages *images[LAST_ICON_SIZE];
-} EphySpinnerCacheData;
-
-static void ephy_spinner_cache_class_init (EphySpinnerCacheClass *klass);
-static void ephy_spinner_cache_init      (EphySpinnerCache *cache);
-
-static GObjectClass *ephy_spinner_cache_parent_class;
-
-static GType
-ephy_spinner_cache_get_type (void)
-{
-       static GType type = 0;
-
-       if (G_UNLIKELY (type == 0))
-       {
-               const GTypeInfo our_info =
-               {
-                       sizeof (EphySpinnerCacheClass),
-                       NULL,
-                       NULL,
-                       (GClassInitFunc) ephy_spinner_cache_class_init,
-                       NULL,
-                       NULL,
-                       sizeof (EphySpinnerCache),
-                       0,
-                       (GInstanceInitFunc) ephy_spinner_cache_init
-               };
-
-               type = g_type_register_static (G_TYPE_OBJECT,
-                                              "EphySpinnerCache",
-                                              &our_info, 0);
-       }
-
-       return type;
-}
-
-static EphySpinnerImages *
-ephy_spinner_images_ref (EphySpinnerImages *images)
-{
-       g_return_val_if_fail (images != NULL, NULL);
-
-       images->ref_count++;
-
-       return images;
-}
-
-static void
-ephy_spinner_images_unref (EphySpinnerImages *images)
-{
-       g_return_if_fail (images != NULL);
-
-       images->ref_count--;
-       if (images->ref_count == 0)
-       {
-               guint i;
-
-               LOG ("Freeing spinner images %p for size %d", images, images->size);
-
-               for (i = 0; i < images->n_animation_pixbufs; ++i)
-               {
-                       g_object_unref (images->animation_pixbufs[i]);
-               }
-               g_free (images->animation_pixbufs);
-
-               g_free (images);
-       }
-}
-
-static void
-ephy_spinner_cache_data_unload (EphySpinnerCacheData *data)
-{
-       GtkIconSize size;
-       EphySpinnerImages *images;
-
-       g_return_if_fail (data != NULL);
-
-       LOG ("EphySpinnerDataCache unload for screen %p", data->screen);
-
-       for (size = GTK_ICON_SIZE_INVALID; size < LAST_ICON_SIZE; ++size)
-       {
-               images = data->images[size];
-               data->images[size] = NULL;
-
-               if (images != NULL && images != EPHY_SPINNER_IMAGES_INVALID)
-               {
-                       ephy_spinner_images_unref (images);
-               }
-       }
-}
-
-static GdkPixbuf *
-extract_frame (GdkPixbuf *grid_pixbuf,
-              int x,
-              int y,
-              int size)
-{
-       GdkPixbuf *pixbuf;
-
-       if (x + size > gdk_pixbuf_get_width (grid_pixbuf) ||
-           y + size > gdk_pixbuf_get_height (grid_pixbuf))
-       {
-               return NULL;
-       }
-
-       pixbuf = gdk_pixbuf_new_subpixbuf (grid_pixbuf,
-                                          x, y,
-                                          size, size);
-       g_return_val_if_fail (pixbuf != NULL, NULL);
-
-       return pixbuf;
-}
-
-static GdkPixbuf *
-scale_to_size (GdkPixbuf *pixbuf,
-              int dw,
-              int dh)
-{
-       GdkPixbuf *result;
-       int pw, ph;
-
-       g_return_val_if_fail (pixbuf != NULL, NULL);
-
-       pw = gdk_pixbuf_get_width (pixbuf);
-       ph = gdk_pixbuf_get_height (pixbuf);
-
-       if (pw != dw || ph != dh)
-       {
-               result = gdk_pixbuf_scale_simple (pixbuf, dw, dh,
-                                                 GDK_INTERP_BILINEAR);
-               g_object_unref (pixbuf);
-               return result;
-       }
-
-       return pixbuf;
-}
-
-static EphySpinnerImages *
-ephy_spinner_images_load (GdkScreen *screen,
-                         GtkIconTheme *icon_theme,
-                         GtkIconSize icon_size)
-{
-       EphySpinnerImages *images;
-       GdkPixbuf *icon_pixbuf, *pixbuf;
-       GtkIconInfo *icon_info = NULL;
-       int grid_width, grid_height, x, y, requested_size, size, isw, ish, n;
-       const char *icon;
-       GSList *list = NULL, *l;
-
-       LOG ("EphySpinnerCacheData loading for screen %p at size %d", screen, icon_size);
-
-       START_PROFILER ("loading spinner animation")
-
-       if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_for_screen (screen),
-                                               icon_size, &isw, &ish)) goto loser;
-
-       requested_size = MAX (ish, isw);
-
-       /* Load the animation. The 'rest icon' is the 0th frame */
-       icon_info = gtk_icon_theme_lookup_icon (icon_theme,
-                                               SPINNER_ICON_NAME,
-                                               requested_size, 0);
-       if (icon_info == NULL)
-       {
-               g_warning ("Throbber animation not found");
-       
-               /* If the icon naming spec compliant name wasn't found, try the old name */
-               icon_info = gtk_icon_theme_lookup_icon (icon_theme,
-                                                       SPINNER_FALLBACK_ICON_NAME,
-                                                       requested_size, 0);
-               if (icon_info == NULL)
-               {
-                       g_warning ("Throbber fallback animation not found either");
-                       goto loser;
-               }
-       }
-       g_assert (icon_info != NULL);
-
-       size = gtk_icon_info_get_base_size (icon_info);
-       icon = gtk_icon_info_get_filename (icon_info);
-       if (icon == NULL) goto loser;
-
-       icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL);
-       gtk_icon_info_free (icon_info);
-       icon_info = NULL;
-
-       if (icon_pixbuf == NULL)
-       {
-               g_warning ("Could not load the spinner file");
-               goto loser;
-       }
-
-       grid_width = gdk_pixbuf_get_width (icon_pixbuf);
-       grid_height = gdk_pixbuf_get_height (icon_pixbuf);
-
-       n = 0;
-       for (y = 0; y < grid_height; y += size)
-       {
-               for (x = 0; x < grid_width ; x += size)
-               {
-                       pixbuf = extract_frame (icon_pixbuf, x, y, size);
-
-                       if (pixbuf)
-                       {
-                               list = g_slist_prepend (list, pixbuf);
-                               ++n;
-                       }
-                       else
-                       {
-                               g_warning ("Cannot extract frame (%d, %d) from the grid\n", x, y);
-                       }
-               }
-       }
-
-       g_object_unref (icon_pixbuf);
-
-       if (list == NULL) goto loser;
-       g_assert (n > 0);
-
-       if (size > requested_size)
-       {
-               for (l = list; l != NULL; l = l->next)
-               {
-                       l->data = scale_to_size (l->data, isw, ish);
-               }
-       }
-
-       /* Now we've successfully got all the data */
-       images = g_new (EphySpinnerImages, 1);
-       images->ref_count = 1;
-
-       images->size = icon_size;
-       images->width = images->height = requested_size;
-
-       images->n_animation_pixbufs = n;
-       images->animation_pixbufs = g_new (GdkPixbuf *, n);
-
-       for (l = list; l != NULL; l = l->next)
-       {
-               g_assert (l->data != NULL);
-               images->animation_pixbufs[--n] = l->data;
-       }
-       g_assert (n == 0);
-
-       g_slist_free (list);
-
-       STOP_PROFILER ("loading spinner animation")
-
-       return images;
-
-loser:
-       if (icon_info)
-       {
-               gtk_icon_info_free (icon_info);
-       }
-       g_slist_foreach (list, (GFunc) g_object_unref, NULL);
-
-       STOP_PROFILER ("loading spinner animation")
-
-       return NULL;
-}
-
-static EphySpinnerCacheData *
-ephy_spinner_cache_data_new (GdkScreen *screen)
-{
-       EphySpinnerCacheData *data;
-
-       data = g_new0 (EphySpinnerCacheData, 1);
-
-       data->screen = screen;
-       data->icon_theme = gtk_icon_theme_get_for_screen (screen);
-       g_signal_connect_swapped (data->icon_theme, "changed",
-                                 G_CALLBACK (ephy_spinner_cache_data_unload),
-                                 data);
-
-       return data;
-}
-
-static void
-ephy_spinner_cache_data_free (EphySpinnerCacheData *data)
-{
-       g_return_if_fail (data != NULL);
-       g_return_if_fail (data->icon_theme != NULL);
-
-       g_signal_handlers_disconnect_by_func
-               (data->icon_theme,
-                G_CALLBACK (ephy_spinner_cache_data_unload), data);
-
-       ephy_spinner_cache_data_unload (data);
-
-       g_free (data);
-}
-
-static EphySpinnerImages *
-ephy_spinner_cache_get_images (EphySpinnerCache *cache,
-                              GdkScreen *screen,
-                              GtkIconSize icon_size)
-{
-       EphySpinnerCachePrivate *priv = cache->priv;
-       EphySpinnerCacheData *data;
-       EphySpinnerImages *images;
-
-       LOG ("Getting animation images for screen %p at size %d", screen, icon_size);
-
-       g_return_val_if_fail (icon_size >= 0 && icon_size < LAST_ICON_SIZE, NULL);
-
-       /* Backward compat: "invalid" meant "native" size which doesn't exist anymore */
-       if (icon_size == GTK_ICON_SIZE_INVALID)
-       {
-               icon_size = GTK_ICON_SIZE_DIALOG;
-       }
-
-       data = g_hash_table_lookup (priv->hash, screen);
-       if (data == NULL)
-       {
-               data = ephy_spinner_cache_data_new (screen);
-               /* FIXME: think about what happens when the screen's display is closed later on */
-               g_hash_table_insert (priv->hash, screen, data);
-       }
-
-       images = data->images[icon_size];
-       if (images == EPHY_SPINNER_IMAGES_INVALID)
-       {
-               /* Load failed, but don't try endlessly again! */
-               return NULL;
-       }
-
-       if (images != NULL)
-       {
-               /* Return cached data */
-               return ephy_spinner_images_ref (images);
-       }
-
-       images = ephy_spinner_images_load (screen, data->icon_theme, icon_size);
-
-       if (images == NULL)
-       {
-               /* Mark as failed-to-load */
-               data->images[icon_size] = EPHY_SPINNER_IMAGES_INVALID;
-
-               return NULL;
-       }
-
-       data->images[icon_size] = images;
-
-       return ephy_spinner_images_ref (images);
-}
-
-static void
-ephy_spinner_cache_init (EphySpinnerCache *cache)
-{
-       EphySpinnerCachePrivate *priv;
-
-       priv = cache->priv = EPHY_SPINNER_CACHE_GET_PRIVATE (cache);
-
-       LOG ("EphySpinnerCache initialising");
-
-       priv->hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-                                           NULL,
-                                           (GDestroyNotify) ephy_spinner_cache_data_free);
-}
-
-static void
-ephy_spinner_cache_finalize (GObject *object)
-{
-       EphySpinnerCache *cache = EPHY_SPINNER_CACHE (object); 
-       EphySpinnerCachePrivate *priv = cache->priv;
-
-       g_hash_table_destroy (priv->hash);
-
-       LOG ("EphySpinnerCache finalised");
-
-       G_OBJECT_CLASS (ephy_spinner_cache_parent_class)->finalize (object);
-}
-
-static void
-ephy_spinner_cache_class_init (EphySpinnerCacheClass *klass)
-{
-       GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-       ephy_spinner_cache_parent_class = g_type_class_peek_parent (klass);
-
-       object_class->finalize = ephy_spinner_cache_finalize;
-
-       g_type_class_add_private (object_class, sizeof (EphySpinnerCachePrivate));
-}
-
-static EphySpinnerCache *spinner_cache = NULL;
-
-static EphySpinnerCache *
-ephy_spinner_cache_ref (void)
-{
-       if (spinner_cache == NULL)
-       {
-               EphySpinnerCache **cache_ptr;
-
-               spinner_cache = g_object_new (EPHY_TYPE_SPINNER_CACHE, NULL);
-               cache_ptr = &spinner_cache;
-               g_object_add_weak_pointer (G_OBJECT (spinner_cache),
-                                          (gpointer *) cache_ptr);
-
-               return spinner_cache;
-       }
-               
-       return g_object_ref (spinner_cache);
-}
-
-/* Spinner implementation */
-
-#define SPINNER_TIMEOUT 125 /* ms */
-
-#define EPHY_SPINNER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SPINNER, EphySpinnerDetails))
-
-struct _EphySpinnerDetails
-{
-       GtkIconTheme *icon_theme;
-       EphySpinnerCache *cache;
-       GtkIconSize size;
-       EphySpinnerImages *images;
-       guint current_image;
-       guint timeout;
-       guint timer_task;
-       guint spinning : 1;
-       guint need_load : 1;
-};
-
-static void ephy_spinner_class_init (EphySpinnerClass *class);
-static void ephy_spinner_init      (EphySpinner *spinner);
-
-static GObjectClass *parent_class;
-
-GType
-ephy_spinner_get_type (void)
-{
-       static GType type = 0;
-
-       if (G_UNLIKELY (type == 0))
-       {
-               const GTypeInfo our_info =
-               {
-                       sizeof (EphySpinnerClass),
-                       NULL, /* base_init */
-                       NULL, /* base_finalize */
-                       (GClassInitFunc) ephy_spinner_class_init,
-                       NULL,
-                       NULL, /* class_data */
-                       sizeof (EphySpinner),
-                       0, /* n_preallocs */
-                       (GInstanceInitFunc) ephy_spinner_init
-               };
-
-               type = g_type_register_static (GTK_TYPE_WIDGET,
-                                              "EphySpinner",
-                                              &our_info, 0);
-       }
-
-       return type;
-}
-
-static gboolean
-ephy_spinner_load_images (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       if (details->need_load)
-       {
-               START_PROFILER ("ephy_spinner_load_images")
-
-               details->images =
-                       ephy_spinner_cache_get_images
-                               (details->cache,
-                                gtk_widget_get_screen (GTK_WIDGET (spinner)),
-                                details->size);
-
-               STOP_PROFILER ("ephy_spinner_load_images")
-
-               details->current_image = 0; /* 'rest' icon */
-               details->need_load = FALSE;
-       }
-
-       return details->images != NULL;
-}
-
-static void
-ephy_spinner_unload_images (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       if (details->images != NULL)
-       {
-               ephy_spinner_images_unref (details->images);
-               details->images = NULL;
-       }
-
-       details->current_image = 0;
-       details->need_load = TRUE;
-}
-
-static void
-icon_theme_changed_cb (GtkIconTheme *icon_theme,
-                      EphySpinner *spinner)
-{
-       ephy_spinner_unload_images (spinner);
-       gtk_widget_queue_resize (GTK_WIDGET (spinner));
-}
-
-static void
-ephy_spinner_init (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details;
-
-       details = spinner->details = EPHY_SPINNER_GET_PRIVATE (spinner);
-
-       GTK_WIDGET_SET_FLAGS (GTK_WIDGET (spinner), GTK_NO_WINDOW);
-
-       details->cache = ephy_spinner_cache_ref ();
-       details->size = GTK_ICON_SIZE_DIALOG;
-       details->spinning = FALSE;
-       details->timeout = SPINNER_TIMEOUT;
-       details->need_load = TRUE;
-}
-
-static int
-ephy_spinner_expose (GtkWidget *widget,
-                    GdkEventExpose *event)
-{
-       EphySpinner *spinner = EPHY_SPINNER (widget);
-       EphySpinnerDetails *details = spinner->details;
-       EphySpinnerImages *images;
-       GdkPixbuf *pixbuf;
-       GdkGC *gc;
-       int x_offset, y_offset, width, height;
-       GdkRectangle pix_area, dest;
-
-       if (!GTK_WIDGET_DRAWABLE (spinner))
-       {
-               return FALSE;
-       }
-
-       if (details->need_load &&
-           !ephy_spinner_load_images (spinner))
-       {
-               return FALSE;
-       }
-
-       images = details->images;
-       if (images == NULL)
-       {
-               return FALSE;
-       }
-
-       /* Otherwise |images| will be NULL anyway */
-       g_assert (images->n_animation_pixbufs > 0);
-               
-       g_assert (details->current_image >= 0 &&
-                 details->current_image < images->n_animation_pixbufs);
-
-       pixbuf = images->animation_pixbufs[details->current_image];
-
-       g_assert (pixbuf != NULL);
-
-       width = gdk_pixbuf_get_width (pixbuf);
-       height = gdk_pixbuf_get_height (pixbuf);
-
-       /* Compute the offsets for the image centered on our allocation */
-       x_offset = (widget->allocation.width - width) / 2;
-       y_offset = (widget->allocation.height - height) / 2;
-
-       pix_area.x = x_offset + widget->allocation.x;
-       pix_area.y = y_offset + widget->allocation.y;
-       pix_area.width = width;
-       pix_area.height = height;
-
-       if (!gdk_rectangle_intersect (&event->area, &pix_area, &dest))
-       {
-               return FALSE;
-       }
-
-       gc = gdk_gc_new (widget->window);
-       gdk_draw_pixbuf (widget->window, gc, pixbuf,
-                        dest.x - x_offset - widget->allocation.x,
-                        dest.y - y_offset - widget->allocation.y,
-                        dest.x, dest.y,
-                        dest.width, dest.height,
-                        GDK_RGB_DITHER_MAX, 0, 0);
-       g_object_unref (gc);
-
-       return FALSE;
-}
-
-static gboolean
-bump_spinner_frame_cb (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       /* This can happen when we've unloaded the images on a theme
-        * change, but haven't been in the queued size request yet.
-        * Just skip this update.
-        */
-       if (details->images == NULL) return TRUE;
-
-       details->current_image++;
-       if (details->current_image >= details->images->n_animation_pixbufs)
-       {
-               /* the 0th frame is the 'rest' icon */
-               details->current_image = MIN (1, details->images->n_animation_pixbufs);
-       }
-
-       gtk_widget_queue_draw (GTK_WIDGET (spinner));
-
-       /* run again */
-       return TRUE;
-}
-
-/**
- * ephy_spinner_start:
- * @spinner: a #EphySpinner
- *
- * Start the spinner animation.
- **/
-void
-ephy_spinner_start (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       details->spinning = TRUE;
-
-       if (GTK_WIDGET_MAPPED (GTK_WIDGET (spinner)) &&
-           details->timer_task == 0 &&
-           ephy_spinner_load_images (spinner))
-       {
-               /* the 0th frame is the 'rest' icon */
-               details->current_image = MIN (1, details->images->n_animation_pixbufs);
-
-               details->timer_task =
-                       g_timeout_add_full (G_PRIORITY_LOW,
-                                           details->timeout,
-                                           (GSourceFunc) bump_spinner_frame_cb,
-                                           spinner,
-                                           NULL);
-       }
-}
-
-static void
-ephy_spinner_remove_update_callback (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       if (details->timer_task != 0)
-       {
-               g_source_remove (details->timer_task);
-               details->timer_task = 0;
-       }
-}
-
-/**
- * ephy_spinner_stop:
- * @spinner: a #EphySpinner
- *
- * Stop the spinner animation.
- **/
-void
-ephy_spinner_stop (EphySpinner *spinner)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       details->spinning = FALSE;
-       details->current_image = 0;
-
-       if (details->timer_task != 0)
-       {
-               ephy_spinner_remove_update_callback (spinner);
-
-               if (GTK_WIDGET_MAPPED (GTK_WIDGET (spinner)))
-               {
-                       gtk_widget_queue_draw (GTK_WIDGET (spinner));
-               }
-       }
-}
-
-/*
- * ephy_spinner_set_size:
- * @spinner: a #EphySpinner
- * @size: the size of type %GtkIconSize
- *
- * Set the size of the spinner.
- **/
-void
-ephy_spinner_set_size (EphySpinner *spinner,
-                      GtkIconSize size)
-{
-       if (size == GTK_ICON_SIZE_INVALID)
-       {
-               size = GTK_ICON_SIZE_DIALOG;
-       }
-
-       if (size != spinner->details->size)
-       {
-               ephy_spinner_unload_images (spinner);
-
-               spinner->details->size = size;
-
-               gtk_widget_queue_resize (GTK_WIDGET (spinner));
-       }
-}
-
-#if 0
-/*
- * ephy_spinner_set_timeout:
- * @spinner: a #EphySpinner
- * @timeout: time delay between updates to the spinner.
- *
- * Sets the timeout delay for spinner updates.
- **/
-void
-ephy_spinner_set_timeout (EphySpinner *spinner,
-                         guint timeout)
-{
-       EphySpinnerDetails *details = spinner->details;
-
-       if (timeout != details->timeout)
-       {
-               ephy_spinner_stop (spinner);
-
-               details->timeout = timeout;
-
-               if (details->spinning)
-               {
-                       ephy_spinner_start (spinner);
-               }
-       }
-}
-#endif
-
-static void
-ephy_spinner_size_request (GtkWidget *widget,
-                          GtkRequisition *requisition)
-{
-       EphySpinner *spinner = EPHY_SPINNER (widget);
-       EphySpinnerDetails *details = spinner->details;
-
-       if ((details->need_load &&
-            !ephy_spinner_load_images (spinner)) ||
-            details->images == NULL)
-       {
-               requisition->width = requisition->height = 0;
-               gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
-                                                  details->size,
-                                                  &requisition->width,
-                                                  &requisition->height);
-               return;
-       }
-
-       requisition->width = details->images->width;
-       requisition->height = details->images->height;
-
-       /* FIXME fix this hack */
-       /* allocate some extra margin so we don't butt up against toolbar edges */
-       if (details->size != GTK_ICON_SIZE_MENU)
-       {
-               requisition->width += 2;
-               requisition->height += 2;
-       }
-}
-
-static void
-ephy_spinner_map (GtkWidget *widget)
-{
-       EphySpinner *spinner = EPHY_SPINNER (widget);
-       EphySpinnerDetails *details = spinner->details;
-
-       GTK_WIDGET_CLASS (parent_class)->map (widget);
-
-       if (details->spinning)
-       {
-               ephy_spinner_start (spinner);
-       }
-}
-
-static void
-ephy_spinner_unmap (GtkWidget *widget)
-{
-       EphySpinner *spinner = EPHY_SPINNER (widget);
-
-       ephy_spinner_remove_update_callback (spinner);
-
-       GTK_WIDGET_CLASS (parent_class)->unmap (widget);
-}
-
-static void
-ephy_spinner_dispose (GObject *object)
-{
-       EphySpinner *spinner = EPHY_SPINNER (object);
-
-       g_signal_handlers_disconnect_by_func
-                       (spinner->details->icon_theme,
-                G_CALLBACK (icon_theme_changed_cb), spinner);
-
-       G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static void
-ephy_spinner_finalize (GObject *object)
-{
-       EphySpinner *spinner = EPHY_SPINNER (object);
-
-       ephy_spinner_remove_update_callback (spinner);
-       ephy_spinner_unload_images (spinner);
-
-       g_object_unref (spinner->details->cache);
-
-       G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-ephy_spinner_screen_changed (GtkWidget *widget,
-                            GdkScreen *old_screen)
-{
-       EphySpinner *spinner = EPHY_SPINNER (widget);
-       EphySpinnerDetails *details = spinner->details;
-       GdkScreen *screen;
-
-       if (GTK_WIDGET_CLASS (parent_class)->screen_changed)
-       {
-               GTK_WIDGET_CLASS (parent_class)->screen_changed (widget, old_screen);
-       }
-
-       screen = gtk_widget_get_screen (widget);
-
-       /* FIXME: this seems to be happening when then spinner is destroyed!? */
-       if (old_screen == screen) return;
-
-       /* We'll get mapped again on the new screen, but not unmapped from
-        * the old screen, so remove timeout here.
-        */
-       ephy_spinner_remove_update_callback (spinner);
-
-       ephy_spinner_unload_images (spinner);
-
-       if (old_screen != NULL)
-       {
-               g_signal_handlers_disconnect_by_func
-                       (gtk_icon_theme_get_for_screen (old_screen),
-                        G_CALLBACK (icon_theme_changed_cb), spinner);
-       }
-
-       details->icon_theme = gtk_icon_theme_get_for_screen (screen);
-       g_signal_connect (details->icon_theme, "changed",
-                         G_CALLBACK (icon_theme_changed_cb), spinner);
-}
-
-static void
-ephy_spinner_class_init (EphySpinnerClass *class)
-{
-       GObjectClass *object_class =  G_OBJECT_CLASS (class);
-       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
-
-       parent_class = g_type_class_peek_parent (class);
-
-       object_class->dispose = ephy_spinner_dispose;
-       object_class->finalize = ephy_spinner_finalize;
-
-       widget_class->expose_event = ephy_spinner_expose;
-       widget_class->size_request = ephy_spinner_size_request;
-       widget_class->map = ephy_spinner_map;
-       widget_class->unmap = ephy_spinner_unmap;
-       widget_class->screen_changed = ephy_spinner_screen_changed;
-
-       g_type_class_add_private (object_class, sizeof (EphySpinnerDetails));
-}
-
-/*
- * ephy_spinner_new:
- *
- * Create a new #EphySpinner. The spinner is a widget
- * that gives the user feedback about network status with
- * an animated image.
- *
- * Return Value: the spinner #GtkWidget
- **/
-GtkWidget *
-ephy_spinner_new (void)
-{
-       return GTK_WIDGET (g_object_new (EPHY_TYPE_SPINNER, NULL));
-}
diff --git a/libempathy-gtk/ephy-spinner.h b/libempathy-gtk/ephy-spinner.h
deleted file mode 100644 (file)
index 4435fe3..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/*
- * Copyright © 2000 Eazel, Inc.
- * Copyright © 2004, 2006 Christian Persch
- *
- * Nautilus is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Nautilus is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Andy Hertzfeld <andy@eazel.com>
- *
- * $Id: ephy-spinner.h 2114 2006-12-25 12:15:00Z mr $
- */
-
-#ifndef EPHY_SPINNER_H
-#define EPHY_SPINNER_H
-
-#include <gtk/gtkwidget.h>
-#include <gtk/gtkenums.h>
-
-G_BEGIN_DECLS
-
-#define EPHY_TYPE_SPINNER              (ephy_spinner_get_type ())
-#define EPHY_SPINNER(o)                        (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_SPINNER, EphySpinner))
-#define EPHY_SPINNER_CLASS(k)          (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_SPINNER, EphySpinnerClass))
-#define EPHY_IS_SPINNER(o)             (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_SPINNER))
-#define EPHY_IS_SPINNER_CLASS(k)       (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_SPINNER))
-#define EPHY_SPINNER_GET_CLASS(o)      (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_SPINNER, EphySpinnerClass))
-
-typedef struct _EphySpinner            EphySpinner;
-typedef struct _EphySpinnerClass       EphySpinnerClass;
-typedef struct _EphySpinnerDetails     EphySpinnerDetails;
-
-struct _EphySpinner
-{
-       GtkWidget parent;
-
-       /*< private >*/
-       EphySpinnerDetails *details;
-};
-
-struct _EphySpinnerClass
-{
-       GtkWidgetClass parent_class;
-};
-
-GType          ephy_spinner_get_type   (void);
-
-GtkWidget      *ephy_spinner_new       (void);
-
-void           ephy_spinner_start      (EphySpinner *throbber);
-
-void           ephy_spinner_stop       (EphySpinner *throbber);
-
-void           ephy_spinner_set_size   (EphySpinner *spinner,
-                                        GtkIconSize size);
-
-G_END_DECLS
-
-#endif /* EPHY_SPINNER_H */
index e064945e804d77fb641d4cf464ce2ae40dd86457..7c70f78c2438bb9df3813f47ce9da07443606de0 100644 (file)
@@ -19,10 +19,18 @@ bin_PROGRAMS =                      \
        empathy-accounts        \
        empathy-logs
 
-empathy_SOURCES =                      \
-       empathy.c                       \
-       bacon-message-connection.c      \
-       bacon-message-connection.h
+empathy_SOURCES =                                                      \
+       empathy.c                                                       \
+       bacon-message-connection.c bacon-message-connection.h           \
+       empathy-chat-window.c empathy-chat-window.h                     \
+       empathy-new-chatroom-dialog.c empathy-new-chatroom-dialog.h     \
+       empathy-status-icon.c empathy-status-icon.h                     \
+       empathy-about-dialog.c empathy-about-dialog.h                   \
+       empathy-chatrooms-window.c empathy-chatrooms-window.h           \
+       empathy-main-window.c empathy-main-window.h                     \
+       empathy-preferences.c empathy-preferences.h                     \
+       ephy-spinner.c ephy-spinner.h
+
 empathy_accounts_SOURCES = empathy-accounts.c
 empathy_logs_SOURCES = empathy-logs.c
 
@@ -51,7 +59,9 @@ CLEANFILES = $(BUILT_SOURCES)
 
 if HAVE_VOIP
 libexec_PROGRAMS = empathy-call-chandler
-empathy_call_chandler_SOURCES = empathy-call-chandler.c
+empathy_call_chandler_SOURCES =                                \
+       empathy-call-chandler.c                         \
+       empathy-call-window.c empathy-call-window.h
 service_DATA +=        org.gnome.Empathy.Call.service
 chandler_DATA += empathy-call.chandler
 else
diff --git a/src/empathy-about-dialog.c b/src/empathy-about-dialog.c
new file mode 100644 (file)
index 0000000..13a8aa3
--- /dev/null
@@ -0,0 +1,113 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Martyn Russell <martyn@imendio.com>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtkaboutdialog.h>
+#include <gtk/gtksizegroup.h>
+#include <glade/glade.h>
+
+#include "empathy-about-dialog.h"
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#define WEB_SITE "http://live.gnome.org/Empathy"
+
+static void about_dialog_activate_link_cb (GtkAboutDialog  *about,
+                                          const gchar     *link,
+                                          gpointer         data);
+
+static const char *authors[] = {
+       "Mikael Hallendal",
+       "Richard Hult",
+       "Martyn Russell",
+       "Geert-Jan Van den Bogaerde",
+       "Kevin Dougherty",
+       "Eitan Isaacson",
+       "Xavier Claessens",
+       NULL
+};
+
+static const char *documenters[] = {
+       NULL
+};
+
+static const char *artists[] = {
+       "Andreas Nilsson <nisses.mail@home.se>",
+       "Vinicius Depizzol <vdepizzol@gmail.com>",
+       NULL
+};
+
+static const char *license[] = {
+       N_("Empathy is free software; you can redistribute it and/or modify "
+          "it under the terms of the GNU General Public License as published by "
+          "the Free Software Foundation; either version 2 of the License, or "
+          "(at your option) any later version."),
+       N_("Empathy is distributed in the hope that it will be useful, "
+          "but WITHOUT ANY WARRANTY; without even the implied warranty of "
+          "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
+          "GNU General Public License for more details."),
+       N_("You should have received a copy of the GNU General Public License "
+          "along with Empathy; if not, write to the Free Software Foundation, Inc., "
+          "51 Franklin Street, Fifth Floor, Boston, MA 02110-130159 USA")
+};
+
+static void
+about_dialog_activate_link_cb (GtkAboutDialog *about,
+                              const gchar    *link,
+                              gpointer        data)
+{
+       empathy_url_show (link);
+}
+
+void
+empathy_about_dialog_new (GtkWindow *parent)
+{
+       gchar *license_trans;
+
+       gtk_about_dialog_set_url_hook (about_dialog_activate_link_cb, NULL, NULL);
+
+       license_trans = g_strconcat (_(license[0]), "\n\n",
+                                    _(license[1]), "\n\n",
+                                    _(license[2]), "\n\n",
+                                    NULL);
+
+       gtk_show_about_dialog (parent,
+                              "artists", artists,
+                              "authors", authors,
+                              "comments", _("An Instant Messaging client for GNOME"),
+                              "license", license_trans,
+                              "wrap-license", TRUE,
+                              "copyright", "Imendio AB 2002-2007\nCollabora Ltd 2007",
+                              "documenters", documenters,
+                              "logo-icon-name", "empathy",
+                              "translator-credits", _("translator-credits"),
+                              "version", PACKAGE_VERSION,
+                              "website", WEB_SITE,
+                              NULL);
+
+       g_free (license_trans);
+}
+
+
diff --git a/src/empathy-about-dialog.h b/src/empathy-about-dialog.h
new file mode 100644 (file)
index 0000000..ff123ab
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Martyn Russell <martyn@imendio.com>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_ABOUT_DIALOG_H__
+#define __EMPATHY_ABOUT_DIALOG_H__
+
+#include <gtk/gtkwindow.h>
+
+G_BEGIN_DECLS
+
+void empathy_about_dialog_new (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /*  __EMPATHY_ABOUT_DIALOG_H__ */
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
new file mode 100644 (file)
index 0000000..c7f202e
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ *  Copyright (C) 2007 Elliot Fairweather
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
+ */
+
+#include <string.h>
+
+#include <libtelepathy/tp-chan.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mc-account-monitor.h>
+#include <libmissioncontrol/mission-control.h>
+
+#include <libempathy/empathy-contact.h>
+#include <libempathy/empathy-tp-call.h>
+#include <libempathy/empathy-chandler.h>
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-utils.h>
+
+#include <libempathy-gtk/empathy-call-window.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#define DEBUG_DOMAIN "CallWindow"
+
+typedef struct 
+{
+  GtkWidget *window;
+  GtkWidget *status_label;
+  GtkWidget *start_call_button;
+  GtkWidget *end_call_button;
+  GtkWidget *input_volume_scale;
+  GtkWidget *output_volume_scale;
+  GtkWidget *input_mute_button;
+  GtkWidget *output_mute_button;
+  GtkWidget *preview_video_frame;
+  GtkWidget *output_video_frame;
+  GtkWidget *preview_video_socket;
+  GtkWidget *output_video_socket;
+  GtkWidget *video_button;
+  GtkWidget *output_video_label;
+
+  EmpathyTpCall *call;
+
+  GTimeVal start_time;
+  guint timeout_event_id;
+
+  gboolean is_drawing;
+} EmpathyCallWindow;
+
+static gboolean
+call_window_update_timer (gpointer data)
+{
+  EmpathyCallWindow *window = data;
+  GTimeVal current;
+  gchar *str;
+  glong now, then;
+  glong time, seconds, minutes, hours;
+
+  g_get_current_time (&current);
+
+  now = current.tv_sec;
+  then = (window->start_time).tv_sec;
+
+  time = now - then;
+
+  seconds = time % 60;
+  time /= 60;
+  minutes = time % 60;
+  time /= 60;
+  hours = time % 60;
+
+  if (hours > 0)
+    {
+      str = g_strdup_printf ("Connected  -  %02ld : %02ld : %02ld", hours,
+          minutes, seconds);
+    }
+  else
+    {
+      str = g_strdup_printf ("Connected  -  %02ld : %02ld", minutes, seconds);
+    }
+
+  gtk_label_set_text (GTK_LABEL (window->status_label), str);
+
+  g_free (str);
+
+  return TRUE;
+}
+
+static void
+call_window_stop_timeout (EmpathyCallWindow *window)
+{
+  GMainContext *context;
+  GSource *source;
+
+  context = g_main_context_default ();
+
+  empathy_debug (DEBUG_DOMAIN, "Timer stopped");
+
+  if (window->timeout_event_id)
+    {
+      source = g_main_context_find_source_by_id (context,
+          window->timeout_event_id);
+      g_source_destroy (source);
+      window->timeout_event_id = 0;
+    }
+}
+
+static void
+call_window_set_output_video_is_drawing (EmpathyCallWindow *window,
+                                         gboolean is_drawing)
+{
+  GtkWidget* child;
+
+  child = gtk_bin_get_child (GTK_BIN (window->output_video_frame));
+
+  empathy_debug (DEBUG_DOMAIN,
+      "Setting output video is drawing - %d", is_drawing);
+
+  if (is_drawing)
+    {
+      if (!window->is_drawing)
+        {
+          if (child)
+            {
+              gtk_container_remove (GTK_CONTAINER (window->output_video_frame),
+                  child);
+            }
+          gtk_container_add (GTK_CONTAINER (window->output_video_frame),
+              window->output_video_socket);
+          gtk_widget_show (window->output_video_socket);
+          empathy_tp_call_add_output_video (window->call,
+              gtk_socket_get_id (GTK_SOCKET (window->output_video_socket)));
+          window->is_drawing = is_drawing;
+        }
+    }
+  else
+    {
+      if (window->is_drawing)
+        {
+          empathy_tp_call_add_output_video (window->call, 0);
+          if (child)
+            {
+              gtk_container_remove (GTK_CONTAINER (window->output_video_frame),
+                  child);
+            }
+          gtk_container_add (GTK_CONTAINER (window->output_video_frame),
+              window->output_video_label);
+          gtk_widget_show (window->output_video_label);
+          window->is_drawing = is_drawing;
+        }
+    }
+}
+
+static gboolean
+call_window_delete_event_cb (GtkWidget *widget,
+                             GdkEvent *event,
+                             EmpathyCallWindow *window)
+{
+  GtkWidget *dialog;
+  gint result;
+  guint status;
+
+  empathy_debug (DEBUG_DOMAIN, "Delete event occurred");
+
+  g_object_get (G_OBJECT (window->call), "status", &status, NULL);
+
+  if (status != EMPATHY_TP_CALL_STATUS_CLOSED)
+    {
+      dialog = gtk_message_dialog_new (GTK_WINDOW (window->window),
+          GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+          GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+          "This call will be ended. Continue?");
+
+      result = gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+
+      switch (result)
+        {
+        case GTK_RESPONSE_YES:
+          call_window_stop_timeout (window);
+          call_window_set_output_video_is_drawing (window, FALSE);
+          empathy_tp_call_close_channel (window->call);
+          empathy_tp_call_remove_preview_video (window->call,
+              gtk_socket_get_id (GTK_SOCKET (window->preview_video_socket)));
+          return FALSE;
+        default:
+          return TRUE;
+        }
+    }
+  else
+    {
+      empathy_tp_call_remove_preview_video (window->call,
+          gtk_socket_get_id (GTK_SOCKET (window->preview_video_socket)));
+      return FALSE;
+    }
+}
+
+static void
+call_window_video_button_toggled_cb (GtkWidget *button,
+                                     EmpathyCallWindow *window)
+{
+  gboolean is_sending;
+
+  is_sending = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+  empathy_debug (DEBUG_DOMAIN, "Send video toggled - %d", is_sending);
+
+  empathy_tp_call_request_video_stream_direction (window->call, is_sending);
+}
+
+static void
+call_window_status_changed_cb (EmpathyTpCall *call,
+                               EmpathyCallWindow *window)
+{
+  EmpathyContact *contact;
+  guint status;
+  guint stream_state;
+  EmpathyTpCallStream *audio_stream;
+  EmpathyTpCallStream *video_stream;
+  gboolean is_incoming;
+  gchar *title;
+
+  g_object_get (G_OBJECT (window->call), "status", &status, NULL);
+  g_object_get (G_OBJECT (window->call), "audio-stream", &audio_stream, NULL);
+  g_object_get (G_OBJECT (window->call), "video-stream", &video_stream, NULL);
+
+  if (video_stream->state > audio_stream->state)
+    {
+      stream_state = video_stream->state;
+    }
+  else
+    {
+      stream_state = audio_stream->state;
+    }
+
+  empathy_debug (DEBUG_DOMAIN, "Status changed - status: %d, stream state: %d",
+      status, stream_state);
+
+  if (window->timeout_event_id)
+    {
+      call_window_stop_timeout (window);
+    }
+
+  if (status == EMPATHY_TP_CALL_STATUS_CLOSED)
+    {
+      gtk_label_set_text (GTK_LABEL (window->status_label), "Closed");
+      gtk_widget_set_sensitive (window->end_call_button, FALSE);
+      gtk_widget_set_sensitive (window->start_call_button, FALSE);
+
+      call_window_set_output_video_is_drawing (window, FALSE);
+    }
+  else if (stream_state == TP_MEDIA_STREAM_STATE_DISCONNECTED)
+    {
+      gtk_label_set_text (GTK_LABEL (window->status_label), "Disconnected");
+    }
+  else if (status == EMPATHY_TP_CALL_STATUS_PENDING)
+    {
+      g_object_get (G_OBJECT (window->call), "contact", &contact, NULL);
+
+      title = g_strdup_printf ("%s - Empathy Call",
+          empathy_contact_get_name (contact));
+      gtk_window_set_title (GTK_WINDOW (window->window), title);
+
+      gtk_label_set_text (GTK_LABEL (window->status_label), "Ringing");
+      gtk_widget_set_sensitive (window->end_call_button, TRUE);
+      gtk_widget_set_sensitive (window->video_button, TRUE);
+
+      g_object_get (G_OBJECT (window->call), "is-incoming", &is_incoming, NULL);
+      if (is_incoming)
+        {
+          gtk_widget_set_sensitive (window->start_call_button, TRUE);
+        }
+      else
+        {
+          g_signal_connect (GTK_OBJECT (window->video_button), "toggled",
+              G_CALLBACK (call_window_video_button_toggled_cb),
+              window);
+        }
+    }
+  else if (status == EMPATHY_TP_CALL_STATUS_ACCEPTED)
+    {
+      if (stream_state == TP_MEDIA_STREAM_STATE_CONNECTING)
+        {
+          gtk_label_set_text (GTK_LABEL (window->status_label), "Connecting");
+        }
+      else if (stream_state == TP_MEDIA_STREAM_STATE_CONNECTED)
+        {
+          if ((window->start_time).tv_sec == 0)
+            {
+              g_get_current_time (&(window->start_time));
+            }
+          window->timeout_event_id = g_timeout_add (1000,
+              call_window_update_timer, window);
+          empathy_debug (DEBUG_DOMAIN, "Timer started");
+        }
+    }
+}
+
+static void
+call_window_receiving_video_cb (EmpathyTpCall *call,
+                                gboolean receiving_video,
+                                EmpathyCallWindow *window)
+{
+  empathy_debug (DEBUG_DOMAIN, "Receiving video signal received");
+
+  call_window_set_output_video_is_drawing (window, receiving_video);
+}
+
+static void
+call_window_sending_video_cb (EmpathyTpCall *call,
+                              gboolean sending_video,
+                              EmpathyCallWindow *window)
+{
+  empathy_debug (DEBUG_DOMAIN, "Sending video signal received");
+
+  g_signal_handlers_block_by_func (window->video_button,
+      call_window_video_button_toggled_cb, window);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->video_button),
+      sending_video);
+  g_signal_handlers_unblock_by_func (window->video_button,
+      call_window_video_button_toggled_cb, window);
+}
+
+static void
+call_window_socket_realized_cb (GtkWidget *widget,
+                                EmpathyCallWindow *window)
+{
+  if (widget == window->preview_video_socket)
+    {
+      empathy_debug (DEBUG_DOMAIN, "Preview socket realized");
+      empathy_tp_call_add_preview_video (window->call,
+          gtk_socket_get_id (GTK_SOCKET (window->preview_video_socket)));
+    }
+  else
+    {
+      empathy_debug (DEBUG_DOMAIN, "Output socket realized");
+    }
+}
+
+static void
+call_window_start_call_button_clicked_cb (GtkWidget *widget,
+                                          EmpathyCallWindow *window)
+{
+  gboolean send_video;
+  gboolean is_incoming;
+
+  empathy_debug (DEBUG_DOMAIN, "Start call clicked");
+
+  gtk_widget_set_sensitive (window->start_call_button, FALSE);
+  g_object_get (G_OBJECT (window->call), "is-incoming", &is_incoming, NULL);
+  if (is_incoming)
+    {
+      empathy_tp_call_accept_incoming_call (window->call);
+      send_video = gtk_toggle_button_get_active
+          (GTK_TOGGLE_BUTTON (window->video_button));
+      empathy_tp_call_request_video_stream_direction (window->call, send_video);
+      g_signal_connect (GTK_OBJECT (window->video_button), "toggled",
+          G_CALLBACK (call_window_video_button_toggled_cb), window);
+    }
+}
+
+static void
+call_window_end_call_button_clicked_cb (GtkWidget *widget,
+                                        EmpathyCallWindow *window)
+{
+  empathy_debug (DEBUG_DOMAIN, "End call clicked");
+
+  call_window_set_output_video_is_drawing (window, FALSE);
+  empathy_tp_call_close_channel (window->call);
+  gtk_widget_set_sensitive (window->end_call_button, FALSE);
+  gtk_widget_set_sensitive (window->start_call_button, FALSE);
+}
+
+static void
+call_window_output_volume_changed_cb (GtkWidget *scale,
+                                      EmpathyCallWindow *window)
+{
+  guint volume;
+
+  volume = (guint) gtk_range_get_value (GTK_RANGE (scale));
+
+  empathy_debug (DEBUG_DOMAIN, "Output volume changed - %u", volume);
+
+  empathy_tp_call_set_output_volume (window->call, volume);
+}
+
+static void
+call_window_output_mute_button_toggled_cb (GtkWidget *button,
+                                           EmpathyCallWindow *window)
+{
+  gboolean is_muted;
+
+  is_muted = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+  empathy_debug (DEBUG_DOMAIN, "Mute output toggled - %d", is_muted);
+
+  empathy_tp_call_mute_output (window->call, is_muted);
+}
+
+static void
+call_window_input_mute_button_toggled_cb (GtkWidget *button,
+                                          EmpathyCallWindow *window)
+{
+  gboolean is_muted;
+
+  is_muted = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+
+  empathy_debug (DEBUG_DOMAIN, "Mute input toggled - %d", is_muted);
+
+  empathy_tp_call_mute_input (window->call, is_muted);
+}
+
+static void
+call_window_destroy_cb (GtkWidget *widget,
+                        EmpathyCallWindow *window)
+{
+  g_signal_handlers_disconnect_by_func (window->call,
+      call_window_status_changed_cb, window);
+  g_signal_handlers_disconnect_by_func (window->call,
+      call_window_receiving_video_cb, window);
+  g_signal_handlers_disconnect_by_func (window->call,
+      call_window_sending_video_cb, window);
+
+  g_object_unref (window->call);
+  g_object_unref (window->output_video_socket);
+  g_object_unref (window->preview_video_socket);
+  g_object_unref (window->output_video_label);
+
+  g_slice_free (EmpathyCallWindow, window);
+}
+
+GtkWidget *
+empathy_call_window_new (EmpathyTpCall *call)
+{
+  EmpathyCallWindow *window;
+  GladeXML *glade;
+  guint status;
+
+  g_return_val_if_fail (EMPATHY_IS_TP_CALL (call), NULL);
+
+  window = g_slice_new0 (EmpathyCallWindow);
+  window->call = g_object_ref (call);
+
+  glade = empathy_glade_get_file ("empathy-call-window.glade",
+      "window",
+      NULL,
+      "window", &window->window,
+      "status_label", &window->status_label,
+      "start_call_button", &window->start_call_button,
+      "end_call_button", &window->end_call_button,
+      "input_volume_scale", &window->input_volume_scale,
+      "output_volume_scale", &window->output_volume_scale,
+      "input_mute_button", &window->input_mute_button,
+      "output_mute_button", &window->output_mute_button,
+      "preview_video_frame", &window->preview_video_frame,
+      "output_video_frame", &window->output_video_frame,
+      "video_button", &window->video_button,
+      NULL);
+
+  empathy_glade_connect (glade,
+      window,
+      "window", "destroy", call_window_destroy_cb,
+      "window", "delete_event", call_window_delete_event_cb,
+      "input_mute_button", "toggled", call_window_input_mute_button_toggled_cb,
+      "output_mute_button", "toggled", call_window_output_mute_button_toggled_cb,
+      "output_volume_scale", "value-changed", call_window_output_volume_changed_cb,
+      "start_call_button", "clicked", call_window_start_call_button_clicked_cb,
+      "end_call_button", "clicked", call_window_end_call_button_clicked_cb,
+      NULL);
+
+  g_object_unref (glade);
+
+  /* Output video label */
+  window->output_video_label = g_object_ref (gtk_label_new ("No video output"));
+  gtk_container_add (GTK_CONTAINER (window->output_video_frame),
+      window->output_video_label);
+  gtk_widget_show (window->output_video_label);
+
+  /* Output video socket */
+  window->output_video_socket = g_object_ref (gtk_socket_new ());
+  g_signal_connect (GTK_OBJECT (window->output_video_socket), "realize",
+      G_CALLBACK (call_window_socket_realized_cb), window);
+  gtk_widget_show (window->output_video_socket);
+
+  /* Preview video socket */
+  window->preview_video_socket = g_object_ref (gtk_socket_new ());
+  g_signal_connect (GTK_OBJECT (window->preview_video_socket), "realize",
+      G_CALLBACK (call_window_socket_realized_cb), window);
+  gtk_container_add (GTK_CONTAINER (window->preview_video_frame),
+      window->preview_video_socket);
+  gtk_widget_show (window->preview_video_socket);
+
+  g_signal_connect (G_OBJECT (window->call), "status-changed",
+      G_CALLBACK (call_window_status_changed_cb),
+      window);
+  g_signal_connect (G_OBJECT (window->call), "receiving-video",
+      G_CALLBACK (call_window_receiving_video_cb),
+      window);
+  g_signal_connect (G_OBJECT (window->call), "sending-video",
+      G_CALLBACK (call_window_sending_video_cb),
+      window);
+
+  window->is_drawing = FALSE;
+
+  g_object_get (G_OBJECT (window->call), "status", &status, NULL);
+
+  if (status == EMPATHY_TP_CALL_STATUS_READYING)
+    {
+      gtk_window_set_title (GTK_WINDOW (window->window), "Empathy Call");
+      gtk_label_set_text (GTK_LABEL (window->status_label), "Readying");
+    }
+
+  gtk_widget_show (window->window);
+
+  return window->window;
+}
+
diff --git a/src/empathy-call-window.glade b/src/empathy-call-window.glade
new file mode 100644 (file)
index 0000000..2eeea0d
--- /dev/null
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.1 on Wed Mar  5 15:38:49 2008 -->
+<glade-interface>
+  <widget class="GtkWindow" id="window">
+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+    <child>
+      <widget class="GtkVBox" id="vbox1">
+        <property name="visible">True</property>
+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+        <property name="border_width">10</property>
+        <property name="spacing">10</property>
+        <child>
+          <widget class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <child>
+              <widget class="GtkLabel" id="status_label">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHSeparator" id="hseparator1">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkHBox" id="hbox2">
+            <property name="visible">True</property>
+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+            <property name="spacing">10</property>
+            <child>
+              <widget class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <property name="label_xalign">0</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="xalign">0</property>
+                    <property name="yalign">0</property>
+                    <child>
+                      <widget class="GtkHBox" id="hbox3">
+                        <property name="visible">True</property>
+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                        <property name="homogeneous">True</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox4">
+                            <property name="visible">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <property name="extension_events">GDK_EXTENSION_EVENTS_CURSOR</property>
+                            <property name="resize_mode">GTK_RESIZE_QUEUE</property>
+                            <child>
+                              <widget class="GtkLabel" id="label2">
+                                <property name="visible">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="label" translatable="yes">Input</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">5</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkVScale" id="input_volume_scale">
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="adjustment">100 0 100 1 0 0</property>
+                                <property name="inverted">True</property>
+                                <property name="draw_value">False</property>
+                              </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkToggleButton" id="input_mute_button">
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="label" translatable="yes">Mute</property>
+                                <property name="response_id">0</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">5</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="padding">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkVBox" id="vbox5">
+                            <property name="visible">True</property>
+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                            <child>
+                              <widget class="GtkLabel" id="label3">
+                                <property name="visible">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="label" translatable="yes">Output</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">5</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkVScale" id="output_volume_scale">
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="adjustment">100 0 100 1 0 0</property>
+                                <property name="inverted">True</property>
+                                <property name="draw_value">False</property>
+                              </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkToggleButton" id="output_mute_button">
+                                <property name="visible">True</property>
+                                <property name="sensitive">False</property>
+                                <property name="can_focus">True</property>
+                                <property name="receives_default">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="label" translatable="yes">Mute</property>
+                                <property name="response_id">0</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="padding">5</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="padding">5</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Volume</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="vbox2">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <child>
+                  <widget class="GtkAspectFrame" id="output_video_frame">
+                    <property name="width_request">352</property>
+                    <property name="height_request">288</property>
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label_xalign">0</property>
+                    <property name="ratio">1.2200000286102295</property>
+                    <property name="obey_child">False</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="vbox3">
+                <property name="visible">True</property>
+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                <child>
+                  <widget class="GtkAspectFrame" id="preview_video_frame">
+                    <property name="width_request">176</property>
+                    <property name="height_request">144</property>
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label_xalign">0</property>
+                    <property name="ratio">1.2200000286102295</property>
+                    <property name="obey_child">False</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkCheckButton" id="video_button">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Send Video</property>
+                    <property name="response_id">0</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="padding">10</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkHSeparator" id="hseparator2">
+                    <property name="visible">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="padding">5</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkButton" id="start_call_button">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">Start Call</property>
+                    <property name="response_id">0</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="padding">10</property>
+                    <property name="pack_type">GTK_PACK_END</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkButton" id="end_call_button">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                    <property name="label" translatable="yes">End Call</property>
+                    <property name="response_id">0</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="pack_type">GTK_PACK_END</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="padding">10</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/src/empathy-call-window.h b/src/empathy-call-window.h
new file mode 100644 (file)
index 0000000..7d65aae
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2007 Elliot Fairweather
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ *  Authors: Elliot Fairweather <elliot.fairweather@collabora.co.uk>
+ */
+
+#ifndef __EMPATHY_CALL_WINDOW_H__
+#define __EMPATHY_CALL_WINDOW_H__
+
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-tp-call.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *empathy_call_window_new (EmpathyTpCall *call);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_CALL_WINDOW_H__ */
diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c
new file mode 100644 (file)
index 0000000..d0f881b
--- /dev/null
@@ -0,0 +1,1905 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003-2007 Imendio AB
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ *          Richard Hult <richard@imendio.com>
+ *          Martyn Russell <martyn@imendio.com>
+ *          Geert-Jan Van den Bogaerde <geertjan@gnome.org>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include <glade/glade.h>
+#include <glib/gi18n.h>
+
+#include <libmissioncontrol/mission-control.h>
+
+#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-log-manager.h>
+#include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-contact.h>
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-message.h>
+#include <libempathy/empathy-utils.h>
+
+#include <libempathy-gtk/empathy-images.h>
+#include <libempathy-gtk/empathy-conf.h>
+#include <libempathy-gtk/empathy-private-chat.h>
+#include <libempathy-gtk/empathy-group-chat.h>
+#include <libempathy-gtk/empathy-contact-dialogs.h>
+#include <libempathy-gtk/empathy-log-window.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#include "empathy-chat-window.h"
+#include "empathy-new-chatroom-dialog.h"
+#include "empathy-preferences.h"
+#include "empathy-about-dialog.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowPriv))
+
+#define DEBUG_DOMAIN "ChatWindow"
+
+struct _EmpathyChatWindowPriv {
+       EmpathyChatroomManager *chatroom_manager;
+       GList                 *chats;
+       GList                 *chats_new_msg;
+       GList                 *chats_composing;
+
+       EmpathyChat            *current_chat;
+
+       gboolean               page_added;
+       gboolean               dnd_same_window;
+
+       GtkWidget             *dialog;
+       GtkWidget             *notebook;
+
+       /* Menu items. */
+       GtkWidget             *menu_conv_clear;
+       GtkWidget             *menu_conv_insert_smiley;
+       GtkWidget             *menu_conv_call;
+       GtkWidget             *menu_conv_call_separator;
+       GtkWidget             *menu_conv_log;
+       GtkWidget             *menu_conv_separator;
+       GtkWidget             *menu_conv_add_contact;
+       GtkWidget             *menu_conv_info;
+       GtkWidget             *menu_conv_close;
+
+       GtkWidget             *menu_room;
+       GtkWidget             *menu_room_set_topic;
+       GtkWidget             *menu_room_join_new;
+       GtkWidget             *menu_room_invite;
+       GtkWidget             *menu_room_add;
+       GtkWidget             *menu_room_show_contacts;
+
+       GtkWidget             *menu_edit_cut;
+       GtkWidget             *menu_edit_copy;
+       GtkWidget             *menu_edit_paste;
+
+       GtkWidget             *menu_tabs_next;
+       GtkWidget             *menu_tabs_prev;
+       GtkWidget             *menu_tabs_left;
+       GtkWidget             *menu_tabs_right;
+       GtkWidget             *menu_tabs_detach;
+       
+       GtkWidget             *menu_help_contents;
+       GtkWidget             *menu_help_about;
+
+       guint                  save_geometry_id;
+};
+
+static void       empathy_chat_window_class_init         (EmpathyChatWindowClass *klass);
+static void       empathy_chat_window_init               (EmpathyChatWindow      *window);
+static void       empathy_chat_window_finalize           (GObject               *object);
+static void       chat_window_accel_cb                  (GtkAccelGroup         *accelgroup,
+                                                        GObject               *object,
+                                                        guint                  key,
+                                                        GdkModifierType        mod,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_close_clicked_cb          (GtkWidget             *button,
+                                                        EmpathyChat            *chat);
+static GtkWidget *chat_window_create_label              (EmpathyChatWindow      *window,
+                                                        EmpathyChat            *chat);
+static void       chat_window_update_status             (EmpathyChatWindow      *window,
+                                                        EmpathyChat            *chat);
+static void       chat_window_update_title              (EmpathyChatWindow      *window,
+                                                        EmpathyChat            *chat);
+static void       chat_window_update_menu               (EmpathyChatWindow      *window);
+static gboolean   chat_window_save_geometry_timeout_cb  (EmpathyChatWindow      *window);
+static gboolean   chat_window_configure_event_cb        (GtkWidget             *widget,
+                                                        GdkEventConfigure     *event,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_conv_activate_cb          (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_clear_activate_cb         (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_info_activate_cb          (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_add_contact_activate_cb   (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_call_activate_cb          (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_log_activate_cb           (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_show_contacts_toggled_cb  (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_edit_activate_cb          (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_insert_smiley_activate_cb (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_close_activate_cb         (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_room_set_topic_activate_cb(GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_room_join_new_activate_cb (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_room_invite_activate_cb   (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_room_add_activate_cb      (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_cut_activate_cb           (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_copy_activate_cb          (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_paste_activate_cb         (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_tabs_left_activate_cb     (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_tabs_right_activate_cb    (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_detach_activate_cb        (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_help_contents_cb          (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_help_about_cb             (GtkWidget             *menuitem,
+                                                        EmpathyChatWindow      *window);
+static gboolean   chat_window_delete_event_cb           (GtkWidget             *dialog,
+                                                        GdkEvent              *event,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_status_changed_cb         (EmpathyChat            *chat,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_update_tooltip            (EmpathyChatWindow      *window,
+                                                        EmpathyChat            *chat);
+static void       chat_window_name_changed_cb           (EmpathyChat            *chat,
+                                                        const gchar           *name,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_composing_cb              (EmpathyChat            *chat,
+                                                        gboolean               is_composing,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_new_message_cb            (EmpathyChat            *chat,
+                                                        EmpathyMessage         *message,
+                                                        gboolean               is_backlog,
+                                                        EmpathyChatWindow      *window);
+static GtkNotebook* chat_window_detach_hook             (GtkNotebook           *source,
+                                                        GtkWidget             *page,
+                                                        gint                   x,
+                                                        gint                   y,
+                                                        gpointer               user_data);
+static void       chat_window_page_switched_cb          (GtkNotebook           *notebook,
+                                                        GtkNotebookPage       *page,
+                                                        gint                   page_num,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_page_reordered_cb         (GtkNotebook           *notebook,
+                                                        GtkWidget             *widget,
+                                                        guint                  page_num,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_page_added_cb             (GtkNotebook           *notebook,
+                                                        GtkWidget             *child,
+                                                        guint                  page_num,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_page_removed_cb           (GtkNotebook           *notebook,
+                                                        GtkWidget             *child,
+                                                        guint                  page_num,
+                                                        EmpathyChatWindow      *window);
+static gboolean   chat_window_focus_in_event_cb         (GtkWidget             *widget,
+                                                        GdkEvent              *event,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_drag_data_received        (GtkWidget             *widget,
+                                                        GdkDragContext        *context,
+                                                        int                    x,
+                                                        int                    y,
+                                                        GtkSelectionData      *selection,
+                                                        guint                  info,
+                                                        guint                  time,
+                                                        EmpathyChatWindow      *window);
+static void       chat_window_set_urgency_hint          (EmpathyChatWindow      *window,
+                                                        gboolean               urgent);
+
+
+static GList *chat_windows = NULL;
+
+static const guint tab_accel_keys[] = {
+       GDK_1, GDK_2, GDK_3, GDK_4, GDK_5,
+       GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
+};
+
+typedef enum {
+       DND_DRAG_TYPE_CONTACT_ID,
+       DND_DRAG_TYPE_TAB
+} DndDragType;
+
+static const GtkTargetEntry drag_types_dest[] = {
+       { "text/contact-id", 0, DND_DRAG_TYPE_CONTACT_ID },
+       { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, DND_DRAG_TYPE_TAB },
+};
+
+G_DEFINE_TYPE (EmpathyChatWindow, empathy_chat_window, G_TYPE_OBJECT);
+
+static void
+empathy_chat_window_class_init (EmpathyChatWindowClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = empathy_chat_window_finalize;
+
+       g_type_class_add_private (object_class, sizeof (EmpathyChatWindowPriv));
+
+       /* Set up a style for the close button with no focus padding. */
+       gtk_rc_parse_string (
+               "style \"empathy-close-button-style\"\n"
+               "{\n"
+               "  GtkWidget::focus-padding = 0\n"
+               "  xthickness = 0\n"
+               "  ythickness = 0\n"
+               "}\n"
+               "widget \"*.empathy-close-button\" style \"empathy-close-button-style\"");
+
+       gtk_notebook_set_window_creation_hook (chat_window_detach_hook, NULL, NULL);
+}
+
+static void
+empathy_chat_window_init (EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       GladeXML             *glade;
+       GtkAccelGroup        *accel_group;
+       GtkWidget            *image;
+       GClosure             *closure;
+       GtkWidget            *menu_conv;
+       GtkWidget            *menu;
+       gint                  i;
+       GtkWidget            *chat_vbox;
+
+       priv = GET_PRIV (window);
+
+       glade = empathy_glade_get_file ("empathy-chat.glade",
+                                      "chat_window",
+                                      NULL,
+                                      "chat_window", &priv->dialog,
+                                      "chat_vbox", &chat_vbox,
+                                      "menu_conv", &menu_conv,
+                                      "menu_conv_clear", &priv->menu_conv_clear,
+                                      "menu_conv_insert_smiley", &priv->menu_conv_insert_smiley,
+                                      "menu_conv_call", &priv->menu_conv_call,
+                                      "menu_conv_call_separator", &priv->menu_conv_call_separator,
+                                      "menu_conv_log", &priv->menu_conv_log,
+                                      "menu_conv_separator", &priv->menu_conv_separator,
+                                      "menu_conv_add_contact", &priv->menu_conv_add_contact,
+                                      "menu_conv_info", &priv->menu_conv_info,
+                                      "menu_conv_close", &priv->menu_conv_close,
+                                      "menu_room", &priv->menu_room,
+                                      "menu_room_set_topic", &priv->menu_room_set_topic,
+                                      "menu_room_join_new", &priv->menu_room_join_new,
+                                      "menu_room_invite", &priv->menu_room_invite,
+                                      "menu_room_add", &priv->menu_room_add,
+                                      "menu_room_show_contacts", &priv->menu_room_show_contacts,
+                                      "menu_edit_cut", &priv->menu_edit_cut,
+                                      "menu_edit_copy", &priv->menu_edit_copy,
+                                      "menu_edit_paste", &priv->menu_edit_paste,
+                                      "menu_tabs_next", &priv->menu_tabs_next,
+                                      "menu_tabs_prev", &priv->menu_tabs_prev,
+                                      "menu_tabs_left", &priv->menu_tabs_left,
+                                      "menu_tabs_right", &priv->menu_tabs_right,
+                                      "menu_tabs_detach", &priv->menu_tabs_detach,
+                                      "menu_help_contents", &priv->menu_help_contents,
+                                      "menu_help_about", &priv->menu_help_about,
+                                      NULL);
+
+       empathy_glade_connect (glade,
+                             window,
+                             "chat_window", "configure-event", chat_window_configure_event_cb,
+                             "menu_conv", "activate", chat_window_conv_activate_cb,
+                             "menu_conv_clear", "activate", chat_window_clear_activate_cb,
+                             "menu_conv_call", "activate", chat_window_call_activate_cb,
+                             "menu_conv_log", "activate", chat_window_log_activate_cb,
+                             "menu_conv_add_contact", "activate", chat_window_add_contact_activate_cb,
+                             "menu_conv_info", "activate", chat_window_info_activate_cb,
+                             "menu_conv_close", "activate", chat_window_close_activate_cb,
+                             "menu_room_set_topic", "activate", chat_window_room_set_topic_activate_cb,
+                             "menu_room_join_new", "activate", chat_window_room_join_new_activate_cb,
+                             "menu_room_invite", "activate", chat_window_room_invite_activate_cb,
+                             "menu_room_add", "activate", chat_window_room_add_activate_cb,
+                             "menu_edit", "activate", chat_window_edit_activate_cb,
+                             "menu_edit_cut", "activate", chat_window_cut_activate_cb,
+                             "menu_edit_copy", "activate", chat_window_copy_activate_cb,
+                             "menu_edit_paste", "activate", chat_window_paste_activate_cb,
+                             "menu_tabs_left", "activate", chat_window_tabs_left_activate_cb,
+                             "menu_tabs_right", "activate", chat_window_tabs_right_activate_cb,
+                             "menu_tabs_detach", "activate", chat_window_detach_activate_cb,
+                             "menu_help_contents", "activate", chat_window_help_contents_cb,
+                             "menu_help_about", "activate", chat_window_help_about_cb,
+                             NULL);
+
+       g_object_unref (glade);
+
+       /* Set up chatroom manager */
+       priv->chatroom_manager = empathy_chatroom_manager_new ();
+       g_signal_connect_swapped (priv->chatroom_manager, "chatroom-added",
+                                 G_CALLBACK (chat_window_update_menu),
+                                 window);
+       g_signal_connect_swapped (priv->chatroom_manager, "chatroom-removed",
+                                 G_CALLBACK (chat_window_update_menu),
+                                 window);
+
+       priv->notebook = gtk_notebook_new ();
+       gtk_notebook_set_group (GTK_NOTEBOOK (priv->notebook), "EmpathyChatWindow"); 
+       gtk_box_pack_start (GTK_BOX (chat_vbox), priv->notebook, TRUE, TRUE, 0);
+       gtk_widget_show (priv->notebook);
+
+       /* Set up accels */
+       accel_group = gtk_accel_group_new ();
+       gtk_window_add_accel_group (GTK_WINDOW (priv->dialog), accel_group);
+
+       for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
+               closure =  g_cclosure_new (G_CALLBACK (chat_window_accel_cb),
+                                          window,
+                                          NULL);
+               gtk_accel_group_connect (accel_group,
+                                        tab_accel_keys[i],
+                                        GDK_MOD1_MASK,
+                                        0,
+                                        closure);
+       }
+
+       g_object_unref (accel_group);
+
+       /* Set the contact information menu item image to the Empathy
+        * stock image
+        */
+       image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (priv->menu_conv_info));
+       gtk_image_set_from_icon_name (GTK_IMAGE (image),
+                                     EMPATHY_IMAGE_CONTACT_INFORMATION,
+                                     GTK_ICON_SIZE_MENU);
+
+       /* Set up smiley menu */
+       menu = empathy_chat_view_get_smiley_menu (
+               G_CALLBACK (chat_window_insert_smiley_activate_cb),
+               window);
+       gtk_menu_item_set_submenu (GTK_MENU_ITEM (priv->menu_conv_insert_smiley), menu);
+
+       /* Set up signals we can't do with glade since we may need to
+        * block/unblock them at some later stage.
+        */
+
+       g_signal_connect (priv->dialog,
+                         "delete_event",
+                         G_CALLBACK (chat_window_delete_event_cb),
+                         window);
+
+       g_signal_connect (priv->menu_room_show_contacts,
+                         "toggled",
+                         G_CALLBACK (chat_window_show_contacts_toggled_cb),
+                         window);
+
+       g_signal_connect_swapped (priv->menu_tabs_prev,
+                                 "activate",
+                                 G_CALLBACK (gtk_notebook_prev_page),
+                                 priv->notebook);
+       g_signal_connect_swapped (priv->menu_tabs_next,
+                                 "activate",
+                                 G_CALLBACK (gtk_notebook_next_page),
+                                 priv->notebook);
+
+       g_signal_connect (priv->dialog,
+                         "focus_in_event",
+                         G_CALLBACK (chat_window_focus_in_event_cb),
+                         window);
+       g_signal_connect_after (priv->notebook,
+                               "switch_page",
+                               G_CALLBACK (chat_window_page_switched_cb),
+                               window);
+       g_signal_connect (priv->notebook,
+                         "page_reordered",
+                         G_CALLBACK (chat_window_page_reordered_cb),
+                         window);
+       g_signal_connect (priv->notebook,
+                         "page_added",
+                         G_CALLBACK (chat_window_page_added_cb),
+                         window);
+       g_signal_connect (priv->notebook,
+                         "page_removed",
+                         G_CALLBACK (chat_window_page_removed_cb),
+                         window);
+
+       /* Set up drag and drop */
+       gtk_drag_dest_set (GTK_WIDGET (priv->notebook),
+                          GTK_DEST_DEFAULT_ALL,
+                          drag_types_dest,
+                          G_N_ELEMENTS (drag_types_dest),
+                          GDK_ACTION_MOVE);
+
+       g_signal_connect (priv->notebook,
+                         "drag-data-received",
+                         G_CALLBACK (chat_window_drag_data_received),
+                         window);
+
+       chat_windows = g_list_prepend (chat_windows, window);
+
+       /* Set up private details */
+       priv->chats = NULL;
+       priv->chats_new_msg = NULL;
+       priv->chats_composing = NULL;
+       priv->current_chat = NULL;
+}
+
+/* Returns the window to open a new tab in if there is only one window
+ * visble, otherwise, returns NULL indicating that a new window should
+ * be added.
+ */
+EmpathyChatWindow *
+empathy_chat_window_get_default (void)
+{
+       GList    *l;
+       gboolean  separate_windows = TRUE;
+
+       empathy_conf_get_bool (empathy_conf_get (),
+                             EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS,
+                             &separate_windows);
+
+       if (separate_windows) {
+               /* Always create a new window */
+               return NULL;
+       }
+
+       for (l = chat_windows; l; l = l->next) {
+               EmpathyChatWindow *chat_window;
+               GtkWidget         *dialog;
+
+               chat_window = l->data;
+
+               dialog = empathy_chat_window_get_dialog (chat_window);
+               if (empathy_window_get_is_visible (GTK_WINDOW (GTK_WINDOW (dialog)))) {
+                       /* Found a visible window on this desktop */
+                       return chat_window;
+               }
+       }
+
+       return NULL;
+}
+
+static void
+empathy_chat_window_finalize (GObject *object)
+{
+       EmpathyChatWindow     *window;
+       EmpathyChatWindowPriv *priv;
+
+       window = EMPATHY_CHAT_WINDOW (object);
+       priv = GET_PRIV (window);
+
+       empathy_debug (DEBUG_DOMAIN, "Finalized: %p", object);
+
+       if (priv->save_geometry_id != 0) {
+               g_source_remove (priv->save_geometry_id);
+       }
+
+       chat_windows = g_list_remove (chat_windows, window);
+       gtk_widget_destroy (priv->dialog);
+
+       g_signal_handlers_disconnect_by_func (priv->chatroom_manager,
+                                             chat_window_update_menu,
+                                             window);
+       g_object_unref (priv->chatroom_manager);
+
+       G_OBJECT_CLASS (empathy_chat_window_parent_class)->finalize (object);
+}
+
+static void
+chat_window_accel_cb (GtkAccelGroup    *accelgroup,
+                     GObject          *object,
+                     guint             key,
+                     GdkModifierType   mod,
+                     EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       gint                  num = -1;
+       gint                  i;
+
+       priv = GET_PRIV (window);
+
+       for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
+               if (tab_accel_keys[i] == key) {
+                       num = i;
+                       break;
+               }
+       }
+
+       if (num != -1) {
+               gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), num);
+       }
+}
+
+static EmpathyChatWindow *
+chat_window_find_chat (EmpathyChat *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       GList                 *l, *ll;
+
+       for (l = chat_windows; l; l = l->next) {
+               priv = GET_PRIV (l->data);
+               ll = g_list_find (priv->chats, chat);
+               if (ll) {
+                       return l->data;
+               }
+       }
+
+       return NULL;
+}
+
+static void
+chat_window_close_clicked_cb (GtkWidget  *button,
+                             EmpathyChat *chat)
+{
+       EmpathyChatWindow *window;
+
+       window = chat_window_find_chat (chat);
+       empathy_chat_window_remove_chat (window, chat);
+}
+
+static void
+chat_window_close_button_style_set_cb (GtkWidget *button,
+                                      GtkStyle  *previous_style,
+                                      gpointer   user_data)
+{
+       gint h, w;
+
+       gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
+                                          GTK_ICON_SIZE_MENU, &w, &h);
+
+       gtk_widget_set_size_request (button, w, h);
+}
+
+static GtkWidget *
+chat_window_create_label (EmpathyChatWindow *window,
+                         EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       GtkWidget            *hbox;
+       GtkWidget            *name_label;
+       GtkWidget            *status_image;
+       GtkWidget            *close_button;
+       GtkWidget            *close_image;
+       GtkWidget            *event_box;
+       GtkWidget            *event_box_hbox;
+       PangoAttrList        *attr_list;
+       PangoAttribute       *attr;
+
+       priv = GET_PRIV (window);
+
+       /* The spacing between the button and the label. */
+       hbox = gtk_hbox_new (FALSE, 0);
+
+       event_box = gtk_event_box_new ();
+       gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
+
+       name_label = gtk_label_new (empathy_chat_get_name (chat));
+       gtk_label_set_ellipsize (GTK_LABEL (name_label), PANGO_ELLIPSIZE_END);
+
+       attr_list = pango_attr_list_new ();
+       attr = pango_attr_scale_new (1/1.2);
+       attr->start_index = 0;
+       attr->end_index = -1;
+       pango_attr_list_insert (attr_list, attr);
+       gtk_label_set_attributes (GTK_LABEL (name_label), attr_list);
+       pango_attr_list_unref (attr_list);
+
+       gtk_misc_set_padding (GTK_MISC (name_label), 2, 0);
+       gtk_misc_set_alignment (GTK_MISC (name_label), 0.0, 0.5);
+       g_object_set_data (G_OBJECT (chat), "chat-window-tab-label", name_label);
+
+       status_image = gtk_image_new ();
+
+       /* Spacing between the icon and label. */
+       event_box_hbox = gtk_hbox_new (FALSE, 0);
+
+       gtk_box_pack_start (GTK_BOX (event_box_hbox), status_image, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (event_box_hbox), name_label, TRUE, TRUE, 0);
+
+       g_object_set_data (G_OBJECT (chat), "chat-window-tab-image", status_image);
+       g_object_set_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget", event_box);
+
+       close_button = gtk_button_new ();
+       gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE);
+
+       /* We don't want focus/keynav for the button to avoid clutter, and
+        * Ctrl-W works anyway.
+        */
+       GTK_WIDGET_UNSET_FLAGS (close_button, GTK_CAN_FOCUS);
+       GTK_WIDGET_UNSET_FLAGS (close_button, GTK_CAN_DEFAULT);
+
+       /* Set the name to make the special rc style match. */
+       gtk_widget_set_name (close_button, "empathy-close-button");
+
+       close_image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
+
+       gtk_container_add (GTK_CONTAINER (close_button), close_image);
+
+       gtk_container_add (GTK_CONTAINER (event_box), event_box_hbox);
+       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, TRUE, 0);
+       gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0);
+
+       /* React to theme changes and also used to setup the initial size
+        * correctly.
+        */
+       g_signal_connect (close_button,
+                         "style-set",
+                         G_CALLBACK (chat_window_close_button_style_set_cb),
+                         chat);
+
+       g_signal_connect (close_button,
+                         "clicked",
+                         G_CALLBACK (chat_window_close_clicked_cb),
+                         chat);
+
+       /* Set up tooltip */
+       chat_window_update_tooltip (window, chat);
+
+       gtk_widget_show_all (hbox);
+
+       return hbox;
+}
+
+static void
+chat_window_update_status (EmpathyChatWindow *window,
+                          EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       GtkImage             *image;
+       const gchar          *icon_name = NULL;
+
+       priv = GET_PRIV (window);
+
+       if (g_list_find (priv->chats_new_msg, chat)) {
+               icon_name = EMPATHY_IMAGE_MESSAGE;
+       }
+       else if (g_list_find (priv->chats_composing, chat)) {
+               icon_name = EMPATHY_IMAGE_TYPING;
+       }
+       else {
+               icon_name = empathy_chat_get_status_icon_name (chat);
+       }
+       image = g_object_get_data (G_OBJECT (chat), "chat-window-tab-image");
+       gtk_image_set_from_icon_name (image, icon_name, GTK_ICON_SIZE_MENU);
+
+       chat_window_update_title (window, chat);
+       chat_window_update_tooltip (window, chat);
+}
+
+static void
+chat_window_update_title (EmpathyChatWindow *window,
+                         EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       gint                   n_chats;
+       
+       priv = GET_PRIV (window);
+       
+       n_chats = g_list_length (priv->chats);
+       if (n_chats == 1) {
+               gtk_window_set_title (GTK_WINDOW (priv->dialog),
+                                     empathy_chat_get_name (priv->current_chat));
+       } else {
+               gchar *title;
+
+               title = g_strdup_printf (_("Conversations (%d)"), n_chats);
+               gtk_window_set_title (GTK_WINDOW (priv->dialog), title);
+               g_free (title);
+       }
+
+       if (priv->chats_new_msg) {
+               gtk_window_set_icon_name (GTK_WINDOW (priv->dialog),
+                                         EMPATHY_IMAGE_MESSAGE);
+       } else {
+               gtk_window_set_icon_name (GTK_WINDOW (priv->dialog), NULL);
+       }
+}
+
+static void
+chat_window_update_menu (EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       gboolean              first_page;
+       gboolean              last_page;
+       gboolean              is_connected;
+       gint                  num_pages;
+       gint                  page_num;
+
+       priv = GET_PRIV (window);
+
+       /* Notebook pages */
+       page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
+       num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
+       first_page = (page_num == 0);
+       last_page = (page_num == (num_pages - 1));
+
+       gtk_widget_set_sensitive (priv->menu_tabs_next, !last_page);
+       gtk_widget_set_sensitive (priv->menu_tabs_prev, !first_page);
+       gtk_widget_set_sensitive (priv->menu_tabs_detach, num_pages > 1);
+       gtk_widget_set_sensitive (priv->menu_tabs_left, !first_page);
+       gtk_widget_set_sensitive (priv->menu_tabs_right, !last_page);
+
+       is_connected = empathy_chat_is_connected (priv->current_chat);
+
+       if (empathy_chat_is_group_chat (priv->current_chat)) {
+               EmpathyGroupChat *group_chat;
+               EmpathyChatroom  *chatroom;
+               gboolean         show_contacts;
+
+               group_chat = EMPATHY_GROUP_CHAT (priv->current_chat);
+
+               /* Show / Hide widgets */
+               gtk_widget_show (priv->menu_room);
+
+               gtk_widget_hide (priv->menu_conv_add_contact);
+               gtk_widget_hide (priv->menu_conv_info);
+               gtk_widget_hide (priv->menu_conv_separator);
+
+               /* Can we add this room to our favourites and are we
+                * connected to the room?
+                */
+               chatroom = empathy_chatroom_manager_find (priv->chatroom_manager,
+                                                         empathy_chat_get_account (priv->current_chat),
+                                                         empathy_chat_get_id (priv->current_chat));
+
+               gtk_widget_set_sensitive (priv->menu_room_add, chatroom == NULL);
+               gtk_widget_set_sensitive (priv->menu_conv_insert_smiley, is_connected);
+               gtk_widget_set_sensitive (priv->menu_room_join_new, is_connected);
+               gtk_widget_set_sensitive (priv->menu_room_invite, is_connected);
+
+               /* We need to block the signal here because all we are
+                * really trying to do is check or uncheck the menu
+                * item. If we don't do this we get funny behaviour
+                * with 2 or more group chat windows where showing
+                * contacts doesn't do anything.
+                */
+               show_contacts = empathy_group_chat_get_show_contacts (group_chat);
+
+               g_signal_handlers_block_by_func (priv->menu_room_show_contacts,
+                                                chat_window_show_contacts_toggled_cb,
+                                                window);
+
+               g_object_set (priv->menu_room_show_contacts,
+                             "active", show_contacts,
+                             NULL);
+
+               g_signal_handlers_unblock_by_func (priv->menu_room_show_contacts,
+                                                  chat_window_show_contacts_toggled_cb,
+                                                  window);
+       } else {
+               EmpathyPrivateChat *chat;
+               EmpathyContact     *contact;
+               McPresence          presence;
+
+               chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
+
+               /* Show / Hide widgets */
+               gtk_widget_hide (priv->menu_room);
+
+               /* Unset presence means this contact refuses to send us his
+                * presence. By adding the contact we ask the contact to accept
+                * to send his presence. */
+               contact = empathy_private_chat_get_contact (chat);
+               presence = empathy_contact_get_presence (contact);
+               if (presence == MC_PRESENCE_UNSET) {
+                       gtk_widget_show (priv->menu_conv_add_contact);
+               } else {
+                       gtk_widget_hide (priv->menu_conv_add_contact);
+               }
+
+               gtk_widget_show (priv->menu_conv_separator);
+               gtk_widget_show (priv->menu_conv_info);
+
+               /* Are we connected? */
+               gtk_widget_set_sensitive (priv->menu_conv_insert_smiley, is_connected);
+               gtk_widget_set_sensitive (priv->menu_conv_add_contact, is_connected);
+               gtk_widget_set_sensitive (priv->menu_conv_info, is_connected);
+       }
+}
+
+static void
+chat_window_insert_smiley_activate_cb (GtkWidget         *menuitem,
+                                      EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChat           *chat;
+       GtkTextBuffer        *buffer;
+       GtkTextIter           iter;
+       const gchar          *smiley;
+
+       priv = GET_PRIV (window);
+
+       chat = priv->current_chat;
+
+       smiley = g_object_get_data (G_OBJECT (menuitem), "smiley_text");
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (chat->input_text_view));
+       gtk_text_buffer_get_end_iter (buffer, &iter);
+       gtk_text_buffer_insert (buffer, &iter,
+                               smiley, -1);
+}
+
+static void
+chat_window_clear_activate_cb (GtkWidget        *menuitem,
+                              EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       empathy_chat_clear (priv->current_chat);
+}
+
+static void
+chat_window_add_contact_activate_cb (GtkWidget        *menuitem,
+                                    EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       //EmpathyContact        *contact;
+
+       priv = GET_PRIV (window);
+
+       //contact = empathy_chat_get_contact (priv->current_chat);
+
+       // FIXME: empathy_add_contact_dialog_show (NULL, contact);
+}
+
+static void
+chat_window_call_activate_cb (GtkWidget         *menuitem,
+                             EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       if (!empathy_chat_is_group_chat (priv->current_chat)) {
+               EmpathyPrivateChat *chat;
+               EmpathyContact     *contact;
+
+               chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
+               contact = empathy_private_chat_get_contact (chat);
+
+               empathy_call_with_contact (contact);
+       }
+}
+
+static void
+chat_window_log_activate_cb (GtkWidget        *menuitem,
+                            EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       empathy_log_window_show (empathy_chat_get_account (priv->current_chat),
+                                empathy_chat_get_id (priv->current_chat),
+                                empathy_chat_is_group_chat (priv->current_chat),
+                                GTK_WINDOW (priv->dialog));
+}
+
+static void
+chat_window_info_activate_cb (GtkWidget        *menuitem,
+                             EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyContact        *contact;
+
+       priv = GET_PRIV (window);
+
+       contact = empathy_private_chat_get_contact (EMPATHY_PRIVATE_CHAT (priv->current_chat));
+
+       empathy_contact_information_dialog_show (contact,
+                                                GTK_WINDOW (priv->dialog),
+                                                FALSE, FALSE);
+}
+
+static gboolean
+chat_window_save_geometry_timeout_cb (EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       gint                  x, y, w, h;
+
+       priv = GET_PRIV (window);
+
+       gtk_window_get_size (GTK_WINDOW (priv->dialog), &w, &h);
+       gtk_window_get_position (GTK_WINDOW (priv->dialog), &x, &y);
+
+       empathy_chat_save_geometry (priv->current_chat, x, y, w, h);
+
+       priv->save_geometry_id = 0;
+
+       return FALSE;
+}
+
+static gboolean
+chat_window_configure_event_cb (GtkWidget         *widget,
+                               GdkEventConfigure *event,
+                               EmpathyChatWindow  *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       if (priv->save_geometry_id != 0) {
+               g_source_remove (priv->save_geometry_id);
+       }
+
+       priv->save_geometry_id =
+               g_timeout_add_seconds (1,
+                                      (GSourceFunc) chat_window_save_geometry_timeout_cb,
+                                      window);
+
+       return FALSE;
+}
+
+static void
+chat_window_conv_activate_cb (GtkWidget         *menuitem,
+                             EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyLogManager     *manager;
+       gboolean              log_exists = FALSE;
+       gboolean              can_voip = FALSE;
+
+       priv = GET_PRIV (window);
+
+       manager = empathy_log_manager_new ();
+       log_exists = empathy_log_manager_exists (manager,
+                                                empathy_chat_get_account (priv->current_chat),
+                                                empathy_chat_get_id (priv->current_chat),
+                                                empathy_chat_is_group_chat (priv->current_chat));
+       g_object_unref (manager);
+
+       if (!empathy_chat_is_group_chat (priv->current_chat)) {
+               EmpathyPrivateChat *chat;
+               EmpathyContact     *contact;
+
+               chat = EMPATHY_PRIVATE_CHAT (priv->current_chat);
+               contact = empathy_private_chat_get_contact (chat);
+               can_voip = empathy_contact_can_voip (contact);
+       }
+
+       gtk_widget_set_sensitive (priv->menu_conv_log, log_exists);
+#ifdef HAVE_VOIP
+       gtk_widget_set_sensitive (priv->menu_conv_call, can_voip);
+#else 
+       g_object_set (priv->menu_conv_call, "visible", FALSE, NULL);
+       g_object_set (priv->menu_conv_call_separator, "visible", FALSE, NULL);
+#endif
+}
+
+static void
+chat_window_show_contacts_toggled_cb (GtkWidget        *menuitem,
+                                     EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       gboolean              show;
+
+       priv = GET_PRIV (window);
+
+       g_return_if_fail (priv->current_chat != NULL);
+
+       show = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (priv->menu_room_show_contacts));
+       empathy_group_chat_set_show_contacts (EMPATHY_GROUP_CHAT (priv->current_chat), show);
+}
+
+static void
+chat_window_close_activate_cb (GtkWidget        *menuitem,
+                              EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       g_return_if_fail (priv->current_chat != NULL);
+
+       empathy_chat_window_remove_chat (window, priv->current_chat);
+}
+
+static void
+chat_window_room_set_topic_activate_cb (GtkWidget        *menuitem,
+                                       EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv = GET_PRIV (window);
+       
+       if (empathy_chat_is_group_chat (priv->current_chat)) {
+               empathy_group_chat_set_topic (EMPATHY_GROUP_CHAT (priv->current_chat));
+       }
+}
+
+static void
+chat_window_room_join_new_activate_cb (GtkWidget        *menuitem,
+                                      EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       empathy_new_chatroom_dialog_show (GTK_WINDOW (priv->dialog));
+}
+
+static void
+chat_window_room_invite_activate_cb (GtkWidget        *menuitem,
+                                    EmpathyChatWindow *window)
+{
+/* FIXME:
+       EmpathyChatWindowPriv *priv;
+       EmpathyContact        *own_contact;
+       EmpathyChatroomId      id = 0;
+
+       priv = GET_PRIV (window);
+       own_contact = empathy_chat_get_own_contact (priv->current_chat);
+
+       if (empathy_chat_is_group_chat (priv->current_chat)) {
+               EmpathyGroupChat *group_chat;
+
+               group_chat = EMPATHY_GROUP_CHAT (priv->current_chat);
+               id = empathy_group_chat_get_chatroom_id (group_chat);
+       }
+
+       empathy_chat_invite_dialog_show (own_contact, id);
+*/
+}
+
+static void
+chat_window_room_add_activate_cb (GtkWidget        *menuitem,
+                                 EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv  *priv;
+       EmpathyChatroomManager *manager;
+       EmpathyChatroom        *chatroom;
+
+       priv = GET_PRIV (window);
+
+       g_return_if_fail (priv->current_chat != NULL);
+
+       if (!empathy_chat_is_group_chat (priv->current_chat)) {
+               return;
+       }
+
+       chatroom = empathy_chatroom_new_full (empathy_chat_get_account (priv->current_chat),
+                                             empathy_chat_get_id (priv->current_chat),
+                                             empathy_chat_get_name (priv->current_chat),
+                                             FALSE);
+
+       manager = empathy_chatroom_manager_new ();
+       empathy_chatroom_manager_add (manager, chatroom);
+       chat_window_update_menu (window);
+
+       g_object_unref (chatroom);
+       g_object_unref (manager);
+}
+
+static void
+chat_window_edit_activate_cb (GtkWidget        *menuitem,
+                             EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       GtkClipboard         *clipboard;
+       GtkTextBuffer        *buffer;
+       gboolean              text_available;
+
+       priv = GET_PRIV (window);
+
+       g_return_if_fail (priv->current_chat != NULL);
+
+       if (!empathy_chat_is_connected (priv->current_chat)) {
+               gtk_widget_set_sensitive (priv->menu_edit_copy, FALSE);
+               gtk_widget_set_sensitive (priv->menu_edit_cut, FALSE);
+               gtk_widget_set_sensitive (priv->menu_edit_paste, FALSE);
+               return;
+       }
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->current_chat->input_text_view));
+       if (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL)) {
+               gtk_widget_set_sensitive (priv->menu_edit_copy, TRUE);
+               gtk_widget_set_sensitive (priv->menu_edit_cut, TRUE);
+       } else {
+               gboolean selection;
+
+               selection = empathy_chat_view_get_selection_bounds (priv->current_chat->view, 
+                                                                  NULL, NULL);
+
+               gtk_widget_set_sensitive (priv->menu_edit_cut, FALSE);
+               gtk_widget_set_sensitive (priv->menu_edit_copy, selection);
+       }
+
+       clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+       text_available = gtk_clipboard_wait_is_text_available (clipboard);
+       gtk_widget_set_sensitive (priv->menu_edit_paste, text_available);
+}
+
+static void
+chat_window_cut_activate_cb (GtkWidget        *menuitem,
+                            EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
+
+       priv = GET_PRIV (window);
+
+       empathy_chat_cut (priv->current_chat);
+}
+
+static void
+chat_window_copy_activate_cb (GtkWidget        *menuitem,
+                             EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
+
+       priv = GET_PRIV (window);
+
+       empathy_chat_copy (priv->current_chat);
+}
+
+static void
+chat_window_paste_activate_cb (GtkWidget        *menuitem,
+                              EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (window));
+
+       priv = GET_PRIV (window);
+
+       empathy_chat_paste (priv->current_chat);
+}
+
+static void
+chat_window_tabs_left_activate_cb (GtkWidget        *menuitem,
+                                  EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChat           *chat;
+       gint                  index;
+
+       priv = GET_PRIV (window);
+
+       chat = priv->current_chat;
+       index = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
+       if (index <= 0) {
+               return;
+       }
+
+       gtk_notebook_reorder_child (GTK_NOTEBOOK (priv->notebook),
+                                   empathy_chat_get_widget (chat),
+                                   index - 1);
+
+       chat_window_update_menu (window);
+       chat_window_update_status (window, chat);
+}
+
+static void
+chat_window_tabs_right_activate_cb (GtkWidget        *menuitem,
+                                   EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChat           *chat;
+       gint                  index;
+
+       priv = GET_PRIV (window);
+
+       chat = priv->current_chat;
+       index = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
+
+       gtk_notebook_reorder_child (GTK_NOTEBOOK (priv->notebook),
+                                   empathy_chat_get_widget (chat),
+                                   index + 1);
+
+       chat_window_update_menu (window);
+       chat_window_update_status (window, chat);
+}
+
+static void
+chat_window_detach_activate_cb (GtkWidget        *menuitem,
+                               EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChatWindow     *new_window;
+       EmpathyChat           *chat;
+
+       priv = GET_PRIV (window);
+
+       chat = priv->current_chat;
+       new_window = empathy_chat_window_new ();
+
+       empathy_chat_window_move_chat (window, new_window, chat);
+
+       priv = GET_PRIV (new_window);
+       gtk_widget_show (priv->dialog);
+}
+
+static void
+chat_window_help_contents_cb (GtkWidget         *menuitem,
+                             EmpathyChatWindow *window)
+{
+       //empathy_help_show ();
+}
+
+static void
+chat_window_help_about_cb (GtkWidget         *menuitem,
+                          EmpathyChatWindow *window)
+{
+       empathy_about_dialog_new (GTK_WINDOW (window));
+}
+
+static gboolean
+chat_window_delete_event_cb (GtkWidget        *dialog,
+                            GdkEvent         *event,
+                            EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       GList                *list;
+       GList                *l;
+
+       priv = GET_PRIV (window);
+
+       empathy_debug (DEBUG_DOMAIN, "Delete event received");
+
+       list = g_list_copy (priv->chats);
+
+       for (l = list; l; l = l->next) {
+               empathy_chat_window_remove_chat (window, l->data);
+       }
+
+       g_list_free (list);
+
+       return TRUE;
+}
+
+static void
+chat_window_status_changed_cb (EmpathyChat       *chat,
+                              EmpathyChatWindow *window)
+{
+       chat_window_update_menu (window);
+       chat_window_update_status (window, chat);
+}
+
+static void
+chat_window_update_tooltip (EmpathyChatWindow *window,
+                           EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       GtkWidget            *widget;
+       gchar                *current_tooltip;
+       gchar                *str;
+
+       priv = GET_PRIV (window);
+
+       current_tooltip = empathy_chat_get_tooltip (chat);
+
+       if (g_list_find (priv->chats_composing, chat)) {
+               str = g_strconcat (current_tooltip, "\n", _("Typing a message."), NULL);
+               g_free (current_tooltip);
+       } else {
+               str = current_tooltip;
+       }
+
+       widget = g_object_get_data (G_OBJECT (chat), "chat-window-tab-tooltip-widget");
+       gtk_widget_set_tooltip_text (widget, str);
+
+       g_free (str);
+}
+
+static void
+chat_window_name_changed_cb (EmpathyChat       *chat,
+                            const gchar      *name,
+                            EmpathyChatWindow *window)
+{
+       GtkLabel *label;
+
+       label = g_object_get_data (G_OBJECT (chat), "chat-window-tab-label");
+
+       gtk_label_set_text (label, name);
+}
+
+static void
+chat_window_composing_cb (EmpathyChat       *chat,
+                         gboolean          is_composing,
+                         EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       if (is_composing && !g_list_find (priv->chats_composing, chat)) {
+               priv->chats_composing = g_list_prepend (priv->chats_composing, chat);
+       } else {
+               priv->chats_composing = g_list_remove (priv->chats_composing, chat);
+       }
+
+       chat_window_update_status (window, chat);
+}
+
+static void
+chat_window_new_message_cb (EmpathyChat       *chat,
+                           EmpathyMessage    *message,
+                           gboolean          is_backlog,
+                           EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       gboolean              has_focus;
+       gboolean              needs_urgency;
+
+       priv = GET_PRIV (window);
+
+       has_focus = empathy_chat_window_has_focus (window);
+       
+       if (has_focus && priv->current_chat == chat) {
+               empathy_debug (DEBUG_DOMAIN, "New message, we have focus");
+               return;
+       }
+       
+       empathy_debug (DEBUG_DOMAIN, "New message, no focus");
+
+       needs_urgency = FALSE;
+       if (empathy_chat_is_group_chat (chat)) {                
+               if (!is_backlog && 
+                   empathy_chat_should_highlight_nick (message)) {
+                       empathy_debug (DEBUG_DOMAIN, "Highlight this nick");
+                       needs_urgency = TRUE;
+               }
+       } else {
+               needs_urgency = TRUE;
+       }
+
+       if (needs_urgency && !has_focus) {
+               chat_window_set_urgency_hint (window, TRUE);
+       }
+
+       if (!is_backlog && 
+           !g_list_find (priv->chats_new_msg, chat)) {
+               priv->chats_new_msg = g_list_prepend (priv->chats_new_msg, chat);
+               chat_window_update_status (window, chat);
+       }
+}
+
+static GtkNotebook *
+chat_window_detach_hook (GtkNotebook *source,
+                        GtkWidget   *page,
+                        gint         x,
+                        gint         y,
+                        gpointer     user_data)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChatWindow     *window, *new_window;
+       EmpathyChat           *chat;
+
+       chat = g_object_get_data (G_OBJECT (page), "chat");
+       window = chat_window_find_chat (chat);
+
+       new_window = empathy_chat_window_new ();
+       priv = GET_PRIV (new_window);
+
+       empathy_debug (DEBUG_DOMAIN, "Detach hook called");
+
+       empathy_chat_window_move_chat (window, new_window, chat);
+
+       gtk_window_move (GTK_WINDOW (priv->dialog), x, y);
+       gtk_widget_show (priv->dialog);
+
+       return NULL;
+}
+
+static void
+chat_window_page_switched_cb (GtkNotebook      *notebook,
+                             GtkNotebookPage  *page,
+                             gint              page_num,
+                             EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChat           *chat;
+       GtkWidget            *child;
+
+       empathy_debug (DEBUG_DOMAIN, "Page switched");
+
+       priv = GET_PRIV (window);
+
+       child = gtk_notebook_get_nth_page (notebook, page_num);
+       chat = g_object_get_data (G_OBJECT (child), "chat");
+
+       if (priv->page_added) {
+               priv->page_added = FALSE;
+               empathy_chat_scroll_down (chat);
+       }
+       else if (priv->current_chat == chat) {
+               return;
+       }
+
+       priv->current_chat = chat;
+       priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
+
+       chat_window_update_menu (window);
+       chat_window_update_status (window, chat);
+}
+
+static void
+chat_window_page_reordered_cb (GtkNotebook      *notebook,
+                              GtkWidget        *widget,
+                              guint             page_num,
+                              EmpathyChatWindow *window)
+{
+       empathy_debug (DEBUG_DOMAIN, "Page reordered");
+       
+       chat_window_update_menu (window);
+}
+
+static void
+chat_window_page_added_cb (GtkNotebook      *notebook,
+                          GtkWidget        *child,
+                          guint             page_num,
+                          EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChat           *chat;
+
+       priv = GET_PRIV (window);
+
+       /* If we just received DND to the same window, we don't want
+        * to do anything here like removing the tab and then readding
+        * it, so we return here and in "page-added".
+        */
+       if (priv->dnd_same_window) {
+               empathy_debug (DEBUG_DOMAIN, "Page added (back to the same window)");
+               priv->dnd_same_window = FALSE;
+               return;
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Page added");
+
+       /* Get chat object */
+       chat = g_object_get_data (G_OBJECT (child), "chat");
+
+       /* Connect chat signals for this window */
+       g_signal_connect (chat, "status-changed",
+                         G_CALLBACK (chat_window_status_changed_cb),
+                         window);
+       g_signal_connect (chat, "name-changed",
+                         G_CALLBACK (chat_window_name_changed_cb),
+                         window);
+       g_signal_connect (chat, "composing",
+                         G_CALLBACK (chat_window_composing_cb),
+                         window);
+       g_signal_connect (chat, "new-message",
+                         G_CALLBACK (chat_window_new_message_cb),
+                         window);
+
+       /* Set flag so we know to perform some special operations on
+        * switch page due to the new page being added.
+        */
+       priv->page_added = TRUE;
+
+       /* Get list of chats up to date */
+       priv->chats = g_list_append (priv->chats, chat);
+}
+
+static void
+chat_window_page_removed_cb (GtkNotebook      *notebook,
+                            GtkWidget        *child,
+                            guint             page_num,
+                            EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       EmpathyChat           *chat;
+
+       priv = GET_PRIV (window);
+
+       /* If we just received DND to the same window, we don't want
+        * to do anything here like removing the tab and then readding
+        * it, so we return here and in "page-added".
+        */
+       if (priv->dnd_same_window) {
+               empathy_debug (DEBUG_DOMAIN, "Page removed (and will be readded to same window)");
+               return;
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Page removed");
+
+       /* Get chat object */
+       chat = g_object_get_data (G_OBJECT (child), "chat");
+
+       /* Disconnect all signal handlers for this chat and this window */
+       g_signal_handlers_disconnect_by_func (chat,
+                                             G_CALLBACK (chat_window_status_changed_cb),
+                                             window);
+       g_signal_handlers_disconnect_by_func (chat,
+                                             G_CALLBACK (chat_window_name_changed_cb),
+                                             window);
+       g_signal_handlers_disconnect_by_func (chat,
+                                             G_CALLBACK (chat_window_composing_cb),
+                                             window);
+       g_signal_handlers_disconnect_by_func (chat,
+                                             G_CALLBACK (chat_window_new_message_cb),
+                                             window);
+
+       /* Keep list of chats up to date */
+       priv->chats = g_list_remove (priv->chats, chat);
+       priv->chats_new_msg = g_list_remove (priv->chats_new_msg, chat);
+       priv->chats_composing = g_list_remove (priv->chats_composing, chat);
+
+       if (priv->chats == NULL) {
+               g_object_unref (window);
+       } else {
+               chat_window_update_menu (window);
+               chat_window_update_title (window, NULL);
+       }
+}
+
+static gboolean
+chat_window_focus_in_event_cb (GtkWidget        *widget,
+                              GdkEvent         *event,
+                              EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       empathy_debug (DEBUG_DOMAIN, "Focus in event, updating title");
+
+       priv = GET_PRIV (window);
+
+       priv->chats_new_msg = g_list_remove (priv->chats_new_msg, priv->current_chat);
+
+       chat_window_set_urgency_hint (window, FALSE);
+       
+       /* Update the title, since we now mark all unread messages as read. */
+       chat_window_update_status (window, priv->current_chat);
+
+       return FALSE;
+}
+
+static void
+chat_window_drag_data_received (GtkWidget        *widget,
+                               GdkDragContext   *context,
+                               int               x,
+                               int               y,
+                               GtkSelectionData *selection,
+                               guint             info,
+                               guint             time,
+                               EmpathyChatWindow *window)
+{
+       if (info == DND_DRAG_TYPE_CONTACT_ID) {
+               EmpathyChat           *chat;
+               EmpathyChatWindow     *old_window;
+               McAccount             *account;
+               const gchar           *id = NULL;
+               gchar                **strv;
+
+               if (selection) {
+                       id = (const gchar*) selection->data;
+               }
+
+               empathy_debug (DEBUG_DOMAIN, "DND contact from roster with id:'%s'", id);
+               
+               strv = g_strsplit (id, "/", 2);
+               account = mc_account_lookup (strv[0]);
+               chat = empathy_chat_window_find_chat (account, strv[1]);
+
+               if (!chat) {
+                       empathy_chat_with_contact_id (account, strv[2]);
+                       g_object_unref (account);
+                       g_strfreev (strv);
+                       return;
+               }
+               g_object_unref (account);
+               g_strfreev (strv);
+
+               old_window = chat_window_find_chat (chat);              
+               if (old_window) {
+                       if (old_window == window) {
+                               gtk_drag_finish (context, TRUE, FALSE, time);
+                               return;
+                       }
+                       
+                       empathy_chat_window_move_chat (old_window, window, chat);
+               } else {
+                       empathy_chat_window_add_chat (window, chat);
+               }
+               
+               /* Added to take care of any outstanding chat events */
+               empathy_chat_window_present_chat (chat);
+
+               /* We should return TRUE to remove the data when doing
+                * GDK_ACTION_MOVE, but we don't here otherwise it has
+                * weird consequences, and we handle that internally
+                * anyway with add_chat() and remove_chat().
+                */
+               gtk_drag_finish (context, TRUE, FALSE, time);
+       }
+       else if (info == DND_DRAG_TYPE_TAB) {
+               EmpathyChat        *chat = NULL;
+               EmpathyChatWindow  *old_window;
+               GtkWidget        **child = NULL;
+
+               empathy_debug (DEBUG_DOMAIN, "DND tab");
+
+               if (selection) {
+                       child = (void*) selection->data;
+               }
+
+               if (child) {
+                       chat = g_object_get_data (G_OBJECT (*child), "chat");
+               }
+
+               old_window = chat_window_find_chat (chat);
+               if (old_window) {
+                       EmpathyChatWindowPriv *priv;
+
+                       priv = GET_PRIV (window);
+
+                       if (old_window == window) {
+                               empathy_debug (DEBUG_DOMAIN, "DND tab (within same window)");
+                               priv->dnd_same_window = TRUE;
+                               gtk_drag_finish (context, TRUE, FALSE, time);
+                               return;
+                       }
+                       
+                       priv->dnd_same_window = FALSE;
+               }
+
+               /* We should return TRUE to remove the data when doing
+                * GDK_ACTION_MOVE, but we don't here otherwise it has
+                * weird consequences, and we handle that internally
+                * anyway with add_chat() and remove_chat().
+                */
+               gtk_drag_finish (context, TRUE, FALSE, time);
+       } else {
+               empathy_debug (DEBUG_DOMAIN, "DND from unknown source");
+               gtk_drag_finish (context, FALSE, FALSE, time);
+       }
+}
+
+static void
+chat_window_set_urgency_hint (EmpathyChatWindow *window,
+                             gboolean          urgent)
+{
+       EmpathyChatWindowPriv *priv;
+
+       priv = GET_PRIV (window);
+
+       empathy_debug (DEBUG_DOMAIN, "Turning %s urgency hint",
+                      urgent ? "on" : "off");
+       gtk_window_set_urgency_hint (GTK_WINDOW (priv->dialog), urgent);
+}
+
+EmpathyChatWindow *
+empathy_chat_window_new (void)
+{
+       return EMPATHY_CHAT_WINDOW (g_object_new (EMPATHY_TYPE_CHAT_WINDOW, NULL));
+}
+
+GtkWidget *
+empathy_chat_window_get_dialog (EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+
+       g_return_val_if_fail (window != NULL, NULL);
+
+       priv = GET_PRIV (window);
+
+       return priv->dialog;
+}
+
+void
+empathy_chat_window_add_chat (EmpathyChatWindow *window,
+                             EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       GtkWidget             *label;
+       GtkWidget             *child;
+       gint                   x, y, w, h;
+
+       g_return_if_fail (window != NULL);
+       g_return_if_fail (EMPATHY_IS_CHAT (chat));
+
+       priv = GET_PRIV (window);
+
+       /* Reference the chat object */
+       g_object_ref (chat);
+
+       empathy_chat_load_geometry (chat, &x, &y, &w, &h);
+
+       if (x >= 0 && y >= 0) {
+               /* Let the window manager position it if we don't have
+                * good x, y coordinates.
+                */
+               gtk_window_move (GTK_WINDOW (priv->dialog), x, y);
+       }
+
+       if (w > 0 && h > 0) {
+               /* Use the defaults from the glade file if we don't have
+                * good w, h geometry.
+                */
+               gtk_window_resize (GTK_WINDOW (priv->dialog), w, h);
+       }
+
+       child = empathy_chat_get_widget (chat);
+       label = chat_window_create_label (window, chat); 
+
+       gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), child, label);
+       gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
+       gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook), child, TRUE);
+       gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (priv->notebook), child,
+                                           TRUE, TRUE, GTK_PACK_START); 
+
+       empathy_debug (DEBUG_DOMAIN, 
+                     "Chat added (%d references)",
+                     G_OBJECT (chat)->ref_count);
+}
+
+void
+empathy_chat_window_remove_chat (EmpathyChatWindow *window,
+                                EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       gint                  position;
+
+       g_return_if_fail (window != NULL);
+       g_return_if_fail (EMPATHY_IS_CHAT (chat));
+
+       priv = GET_PRIV (window);
+
+       position = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
+                                         empathy_chat_get_widget (chat));
+       gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), position);
+
+       empathy_debug (DEBUG_DOMAIN, 
+                     "Chat removed (%d references)", 
+                     G_OBJECT (chat)->ref_count - 1);
+
+       g_object_unref (chat);
+}
+
+void
+empathy_chat_window_move_chat (EmpathyChatWindow *old_window,
+                              EmpathyChatWindow *new_window,
+                              EmpathyChat       *chat)
+{
+       GtkWidget *widget;
+
+       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (old_window));
+       g_return_if_fail (EMPATHY_IS_CHAT_WINDOW (new_window));
+       g_return_if_fail (EMPATHY_IS_CHAT (chat));
+
+       widget = empathy_chat_get_widget (chat);
+
+       empathy_debug (DEBUG_DOMAIN,
+                     "Chat moving with widget:%p (%d references)", 
+                     widget,
+                     G_OBJECT (widget)->ref_count);
+
+       /* We reference here to make sure we don't loose the widget
+        * and the EmpathyChat object during the move.
+        */
+       g_object_ref (chat);
+       g_object_ref (widget);
+
+       empathy_chat_window_remove_chat (old_window, chat);
+       empathy_chat_window_add_chat (new_window, chat);
+
+       g_object_unref (widget);
+       g_object_unref (chat);
+}
+
+void
+empathy_chat_window_switch_to_chat (EmpathyChatWindow *window,
+                                   EmpathyChat       *chat)
+{
+       EmpathyChatWindowPriv *priv;
+       gint                  page_num;
+
+       g_return_if_fail (window != NULL);
+       g_return_if_fail (EMPATHY_IS_CHAT (chat));
+
+       priv = GET_PRIV (window);
+
+       page_num = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook),
+                                         empathy_chat_get_widget (chat));
+       gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
+                                      page_num);
+}
+
+gboolean
+empathy_chat_window_has_focus (EmpathyChatWindow *window)
+{
+       EmpathyChatWindowPriv *priv;
+       gboolean              has_focus;
+
+       g_return_val_if_fail (EMPATHY_IS_CHAT_WINDOW (window), FALSE);
+
+       priv = GET_PRIV (window);
+
+       g_object_get (priv->dialog, "has-toplevel-focus", &has_focus, NULL);
+
+       return has_focus;
+}
+
+EmpathyChat *
+empathy_chat_window_find_chat (McAccount   *account,
+                              const gchar *id)
+{
+       GList *l;
+
+       g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+       g_return_val_if_fail (!G_STR_EMPTY (id), NULL);
+
+       for (l = chat_windows; l; l = l->next) {
+               EmpathyChatWindowPriv *priv;
+               EmpathyChatWindow     *window;
+               GList                *ll;
+
+               window = l->data;
+               priv = GET_PRIV (window);
+
+               for (ll = priv->chats; ll; ll = ll->next) {
+                       EmpathyChat *chat;
+
+                       chat = ll->data;
+
+                       if (empathy_account_equal (account, empathy_chat_get_account (chat)) &&
+                           strcmp (id, empathy_chat_get_id (chat)) == 0) {
+                               return chat;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+void
+empathy_chat_window_present_chat (EmpathyChat *chat)
+{
+       EmpathyChatWindow     *window;
+       EmpathyChatWindowPriv *priv;
+
+       g_return_if_fail (EMPATHY_IS_CHAT (chat));
+
+       window = chat_window_find_chat (chat);
+
+       /* If the chat has no window, create one */
+       if (window == NULL) {
+               window = empathy_chat_window_get_default ();
+               if (!window) {
+                       window = empathy_chat_window_new ();
+               }
+
+               empathy_chat_window_add_chat (window, chat);
+       }
+
+       priv = GET_PRIV (window);
+       empathy_chat_window_switch_to_chat (window, chat);
+       empathy_window_present (GTK_WINDOW (priv->dialog), TRUE);
+
+       gtk_widget_grab_focus (chat->input_text_view); 
+}
+
diff --git a/src/empathy-chat-window.h b/src/empathy-chat-window.h
new file mode 100644 (file)
index 0000000..32ca13a
--- /dev/null
@@ -0,0 +1,76 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003-2007 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ *          Richard Hult <richard@imendio.com>
+ *          Martyn Russell <martyn@imendio.com>
+ *          Geert-Jan Van den Bogaerde <geertjan@gnome.org>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_CHAT_WINDOW_H__
+#define __EMPATHY_CHAT_WINDOW_H__
+
+#include <glib-object.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include <libempathy-gtk/empathy-chat.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_CHAT_WINDOW         (empathy_chat_window_get_type ())
+#define EMPATHY_CHAT_WINDOW(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindow))
+#define EMPATHY_CHAT_WINDOW_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowClass))
+#define EMPATHY_IS_CHAT_WINDOW(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_CHAT_WINDOW))
+#define EMPATHY_IS_CHAT_WINDOW_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_CHAT_WINDOW))
+#define EMPATHY_CHAT_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_CHAT_WINDOW, EmpathyChatWindowClass))
+
+typedef struct _EmpathyChatWindow      EmpathyChatWindow;
+typedef struct _EmpathyChatWindowClass EmpathyChatWindowClass;
+typedef struct _EmpathyChatWindowPriv  EmpathyChatWindowPriv;
+
+struct _EmpathyChatWindow {
+       GObject parent;
+};
+
+struct _EmpathyChatWindowClass {
+       GObjectClass parent_class;
+};
+
+GType              empathy_chat_window_get_type       (void);
+EmpathyChatWindow *empathy_chat_window_get_default    (void);
+EmpathyChatWindow *empathy_chat_window_new            (void);
+GtkWidget *        empathy_chat_window_get_dialog     (EmpathyChatWindow *window);
+void               empathy_chat_window_add_chat       (EmpathyChatWindow *window,
+                                                      EmpathyChat       *chat);
+void               empathy_chat_window_remove_chat    (EmpathyChatWindow *window,
+                                                      EmpathyChat       *chat);
+void               empathy_chat_window_move_chat      (EmpathyChatWindow *old_window,
+                                                      EmpathyChatWindow *new_window,
+                                                      EmpathyChat       *chat);
+void               empathy_chat_window_switch_to_chat (EmpathyChatWindow *window,
+                                                      EmpathyChat       *chat);
+gboolean           empathy_chat_window_has_focus      (EmpathyChatWindow *window);
+EmpathyChat *      empathy_chat_window_find_chat      (McAccount        *account,
+                                                      const gchar      *id);
+void               empathy_chat_window_present_chat   (EmpathyChat      *chat);
+G_END_DECLS
+
+#endif /* __EMPATHY_CHAT_WINDOW_H__ */
diff --git a/src/empathy-chatrooms-window.c b/src/empathy-chatrooms-window.c
new file mode 100644 (file)
index 0000000..0511098
--- /dev/null
@@ -0,0 +1,583 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ *          Martyn Russell <martyn@imendio.com>
+ *          Mikael Hallendal <micke@imendio.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-utils.h>
+
+#include <libempathy-gtk/empathy-account-chooser.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#include "empathy-chatrooms-window.h"
+#include "empathy-new-chatroom-dialog.h"
+
+typedef struct {
+       EmpathyChatroomManager *manager;
+
+       GtkWidget             *window;
+       GtkWidget             *hbox_account;
+       GtkWidget             *label_account;
+       GtkWidget             *account_chooser;
+       GtkWidget             *treeview;
+       GtkWidget             *button_remove;
+       GtkWidget             *button_edit;
+       GtkWidget             *button_close;
+
+       gint                   room_column;
+} EmpathyChatroomsWindow;
+
+static void             chatrooms_window_destroy_cb                      (GtkWidget             *widget,
+                                                                         EmpathyChatroomsWindow *window);
+static void             chatrooms_window_model_setup                     (EmpathyChatroomsWindow *window);
+static void             chatrooms_window_model_add_columns               (EmpathyChatroomsWindow *window);
+static void             chatrooms_window_model_refresh_data              (EmpathyChatroomsWindow *window,
+                                                                         gboolean               first_time);
+static void             chatrooms_window_model_add                       (EmpathyChatroomsWindow *window,
+                                                                         EmpathyChatroom        *chatroom,
+                                                                         gboolean               set_active);
+static void             chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
+                                                                         gchar                  *path_string,
+                                                                         EmpathyChatroomsWindow  *window);
+static EmpathyChatroom * chatrooms_window_model_get_selected              (EmpathyChatroomsWindow *window);
+static void             chatrooms_window_model_action_selected           (EmpathyChatroomsWindow *window);
+static void             chatrooms_window_row_activated_cb                (GtkTreeView           *tree_view,
+                                                                         GtkTreePath           *path,
+                                                                         GtkTreeViewColumn     *column,
+                                                                         EmpathyChatroomsWindow *window);
+static void             chatrooms_window_button_remove_clicked_cb        (GtkWidget             *widget,
+                                                                         EmpathyChatroomsWindow *window);
+static void             chatrooms_window_button_edit_clicked_cb          (GtkWidget             *widget,
+                                                                         EmpathyChatroomsWindow *window);
+static void             chatrooms_window_button_close_clicked_cb         (GtkWidget             *widget,
+                                                                         EmpathyChatroomsWindow *window);
+static void             chatrooms_window_chatroom_added_cb               (EmpathyChatroomManager *manager,
+                                                                         EmpathyChatroom        *chatroom,
+                                                                         EmpathyChatroomsWindow *window);
+static void             chatrooms_window_chatroom_removed_cb             (EmpathyChatroomManager *manager,
+                                                                         EmpathyChatroom        *chatroom,
+                                                                         EmpathyChatroomsWindow *window);
+static gboolean         chatrooms_window_remove_chatroom_foreach         (GtkTreeModel          *model,
+                                                                         GtkTreePath           *path,
+                                                                         GtkTreeIter           *iter,
+                                                                         EmpathyChatroom        *chatroom);
+static void             chatrooms_window_account_changed_cb              (GtkWidget             *combo_box,
+                                                                         EmpathyChatroomsWindow *window);
+
+enum {
+       COL_IMAGE,
+       COL_NAME,
+       COL_ROOM,
+       COL_AUTO_CONNECT,
+       COL_POINTER,
+       COL_COUNT
+};
+
+void
+empathy_chatrooms_window_show (GtkWindow *parent)
+{
+       static EmpathyChatroomsWindow *window = NULL;
+       GladeXML                     *glade;
+
+       if (window) {
+               gtk_window_present (GTK_WINDOW (window->window));
+               return;
+       }
+
+       window = g_new0 (EmpathyChatroomsWindow, 1);
+
+       glade = empathy_glade_get_file ("empathy-chatrooms-window.glade",
+                                      "chatrooms_window",
+                                      NULL,
+                                      "chatrooms_window", &window->window,
+                                      "hbox_account", &window->hbox_account,
+                                      "label_account", &window->label_account,
+                                      "treeview", &window->treeview,
+                                      "button_edit", &window->button_edit,
+                                      "button_remove", &window->button_remove,
+                                      "button_close", &window->button_close,
+                                      NULL);
+
+       empathy_glade_connect (glade,
+                             window,
+                             "chatrooms_window", "destroy", chatrooms_window_destroy_cb,
+                             "button_remove", "clicked", chatrooms_window_button_remove_clicked_cb,
+                             "button_edit", "clicked", chatrooms_window_button_edit_clicked_cb,
+                             "button_close", "clicked", chatrooms_window_button_close_clicked_cb,
+                             NULL);
+
+       g_object_unref (glade);
+
+       g_object_add_weak_pointer (G_OBJECT (window->window), (gpointer) &window);
+
+       /* Get the session and chat room manager */
+       window->manager = empathy_chatroom_manager_new ();
+
+       g_signal_connect (window->manager, "chatroom-added",
+                         G_CALLBACK (chatrooms_window_chatroom_added_cb),
+                         window);
+       g_signal_connect (window->manager, "chatroom-removed",
+                         G_CALLBACK (chatrooms_window_chatroom_removed_cb),
+                         window);
+
+       /* Account chooser for chat rooms */
+       window->account_chooser = empathy_account_chooser_new ();
+       empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser),
+                                           empathy_account_chooser_filter_is_connected,
+                                           NULL);
+       g_object_set (window->account_chooser, 
+                     "has-all-option", TRUE,
+                     NULL);
+       empathy_account_chooser_set_account (EMPATHY_ACCOUNT_CHOOSER (window->account_chooser), NULL);
+
+       gtk_box_pack_start (GTK_BOX (window->hbox_account),
+                           window->account_chooser,
+                           TRUE, TRUE, 0);
+
+       g_signal_connect (window->account_chooser, "changed",
+                         G_CALLBACK (chatrooms_window_account_changed_cb),
+                         window);
+
+       gtk_widget_show (window->account_chooser);
+
+       /* Set up chatrooms */
+       chatrooms_window_model_setup (window);
+
+       /* Set focus */
+       gtk_widget_grab_focus (window->treeview);
+
+       /* Last touches */
+       if (parent) {
+               gtk_window_set_transient_for (GTK_WINDOW (window->window),
+                                             GTK_WINDOW (parent));
+       }
+
+       gtk_widget_show (window->window);
+}
+
+static void
+chatrooms_window_destroy_cb (GtkWidget             *widget,
+                            EmpathyChatroomsWindow *window)
+{
+       g_signal_handlers_disconnect_by_func (window->manager,
+                                             chatrooms_window_chatroom_added_cb,
+                                             window);
+       g_signal_handlers_disconnect_by_func (window->manager,
+                                             chatrooms_window_chatroom_removed_cb,
+                                             window);
+       g_object_unref (window->manager);
+       g_free (window);
+}
+
+static void
+chatrooms_window_model_setup (EmpathyChatroomsWindow *window)
+{
+       GtkTreeView      *view;
+       GtkListStore     *store;
+       GtkTreeSelection *selection;
+
+       /* View */
+       view = GTK_TREE_VIEW (window->treeview);
+
+       g_signal_connect (view, "row-activated",
+                         G_CALLBACK (chatrooms_window_row_activated_cb),
+                         window);
+
+       /* Store */
+       store = gtk_list_store_new (COL_COUNT,
+                                   G_TYPE_STRING,         /* Image */
+                                   G_TYPE_STRING,         /* Name */
+                                   G_TYPE_STRING,         /* Room */
+                                   G_TYPE_BOOLEAN,        /* Auto start */
+                                   EMPATHY_TYPE_CHATROOM); /* Chatroom */
+
+       gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
+
+       /* Selection */ 
+       selection = gtk_tree_view_get_selection (view);
+       gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+       /* Columns */
+       chatrooms_window_model_add_columns (window);
+
+       /* Add data */
+       chatrooms_window_model_refresh_data (window, TRUE);
+
+       /* Clean up */
+       g_object_unref (store);
+}
+
+static void
+chatrooms_window_model_add_columns (EmpathyChatroomsWindow *window)
+{
+       GtkTreeView       *view;
+       GtkTreeModel      *model;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer   *cell;
+       gint               count;
+
+       view = GTK_TREE_VIEW (window->treeview);
+       model = gtk_tree_view_get_model (view);
+
+       gtk_tree_view_set_headers_visible (view, TRUE);
+       gtk_tree_view_set_headers_clickable (view, TRUE);
+
+       /* Name & Status */
+       column = gtk_tree_view_column_new ();
+       count = gtk_tree_view_append_column (view, column);
+
+       gtk_tree_view_column_set_title (column, _("Name"));
+       gtk_tree_view_column_set_expand (column, TRUE);
+       gtk_tree_view_column_set_sort_column_id (column, count - 1);
+
+       cell = gtk_cell_renderer_pixbuf_new ();
+       gtk_tree_view_column_pack_start (column, cell, FALSE);
+       gtk_tree_view_column_add_attribute (column, cell, "icon-name", COL_IMAGE);
+
+       cell = gtk_cell_renderer_text_new ();
+       g_object_set (cell,
+                     "xpad", 4,
+                     "ypad", 1,
+                     NULL);
+       gtk_tree_view_column_pack_start (column, cell, TRUE);
+       gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME);
+
+       /* Room */
+       cell = gtk_cell_renderer_text_new ();
+       column = gtk_tree_view_column_new_with_attributes (_("Room"), cell, 
+                                                          "text", COL_ROOM, 
+                                                          NULL);
+       count = gtk_tree_view_append_column (view, column);
+       gtk_tree_view_column_set_sort_column_id (column, count - 1);
+       window->room_column = count - 1;
+
+       /* Chatroom auto connect */
+       cell = gtk_cell_renderer_toggle_new ();
+       column = gtk_tree_view_column_new_with_attributes (_("Auto Connect"), cell,
+                                                          "active", COL_AUTO_CONNECT,
+                                                          NULL);
+       count = gtk_tree_view_append_column (view, column);
+       gtk_tree_view_column_set_sort_column_id (column, count - 1);
+
+       g_signal_connect (cell, "toggled",
+                         G_CALLBACK (chatrooms_window_model_cell_auto_connect_toggled),
+                         window);
+
+       /* Sort model */
+       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), 0, 
+                                             GTK_SORT_ASCENDING);
+}
+
+static void
+chatrooms_window_model_refresh_data (EmpathyChatroomsWindow *window,
+                                    gboolean               first_time)
+{
+       GtkTreeView           *view;
+       GtkTreeSelection      *selection;
+       GtkTreeModel          *model;
+       GtkListStore          *store;
+       GtkTreeIter            iter;
+       GtkTreeViewColumn     *column;
+       EmpathyAccountChooser  *account_chooser;
+       McAccount             *account;
+       GList                 *chatrooms, *l;
+
+       view = GTK_TREE_VIEW (window->treeview);
+       selection = gtk_tree_view_get_selection (view);
+       model = gtk_tree_view_get_model (view);
+       store = GTK_LIST_STORE (model);
+
+       /* Look up chatrooms */
+       account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
+       account = empathy_account_chooser_get_account (account_chooser);
+
+       chatrooms = empathy_chatroom_manager_get_chatrooms (window->manager, account);
+
+       /* Sort out columns, we only show the server column for
+        * selected protocol types, such as Jabber. 
+        */
+       if (account) {
+               column = gtk_tree_view_get_column (view, window->room_column);
+               gtk_tree_view_column_set_visible (column, TRUE);
+       } else {
+               column = gtk_tree_view_get_column (view, window->room_column);
+               gtk_tree_view_column_set_visible (column, FALSE);
+       }
+
+       /* Clean out the store */
+       gtk_list_store_clear (store);
+
+       /* Populate with chatroom list. */
+       for (l = chatrooms; l; l = l->next) {
+               chatrooms_window_model_add (window, l->data,  FALSE);
+       }
+
+       if (gtk_tree_model_get_iter_first (model, &iter)) {
+               gtk_tree_selection_select_iter (selection, &iter);
+       }
+
+       if (account) {
+               g_object_unref (account);
+       }
+
+       g_list_free (chatrooms);
+}
+
+static void
+chatrooms_window_model_add (EmpathyChatroomsWindow *window,
+                           EmpathyChatroom        *chatroom,
+                           gboolean               set_active)
+{
+       GtkTreeView      *view;
+       GtkTreeModel     *model;
+       GtkTreeSelection *selection;
+       GtkListStore     *store;
+       GtkTreeIter       iter;
+
+       view = GTK_TREE_VIEW (window->treeview);
+       selection = gtk_tree_view_get_selection (view);
+       model = gtk_tree_view_get_model (view);
+       store = GTK_LIST_STORE (model);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           COL_NAME, empathy_chatroom_get_name (chatroom),
+                           COL_ROOM, empathy_chatroom_get_room (chatroom),
+                           COL_AUTO_CONNECT, empathy_chatroom_get_auto_connect (chatroom),
+                           COL_POINTER, chatroom,
+                           -1);
+
+       if (set_active) {
+               gtk_tree_selection_select_iter (selection, &iter);
+       }
+}
+
+static void
+chatrooms_window_model_cell_auto_connect_toggled (GtkCellRendererToggle  *cell,
+                                                 gchar                  *path_string,
+                                                 EmpathyChatroomsWindow  *window)
+{
+       EmpathyChatroom *chatroom;
+       gboolean        enabled;
+       GtkTreeView    *view;
+       GtkTreeModel   *model;
+       GtkListStore   *store;
+       GtkTreePath    *path;
+       GtkTreeIter     iter;
+
+       view = GTK_TREE_VIEW (window->treeview);
+       model = gtk_tree_view_get_model (view);
+       store = GTK_LIST_STORE (model);
+
+       path = gtk_tree_path_new_from_string (path_string);
+
+       gtk_tree_model_get_iter (model, &iter, path);
+       gtk_tree_model_get (model, &iter,
+                           COL_AUTO_CONNECT, &enabled,
+                           COL_POINTER, &chatroom,
+                           -1);
+
+       enabled = !enabled;
+
+       empathy_chatroom_set_auto_connect (chatroom, enabled);
+       empathy_chatroom_manager_store (window->manager);
+
+       gtk_list_store_set (store, &iter, COL_AUTO_CONNECT, enabled, -1);
+       gtk_tree_path_free (path);
+       g_object_unref (chatroom);
+}
+
+static EmpathyChatroom *
+chatrooms_window_model_get_selected (EmpathyChatroomsWindow *window)
+{
+       GtkTreeView      *view;
+       GtkTreeModel     *model;
+       GtkTreeSelection *selection;
+       GtkTreeIter       iter;
+       EmpathyChatroom   *chatroom = NULL;
+
+       view = GTK_TREE_VIEW (window->treeview);
+       selection = gtk_tree_view_get_selection (view);
+
+       if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+               gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
+       }
+
+       return chatroom;
+}
+
+static void
+chatrooms_window_model_action_selected (EmpathyChatroomsWindow *window)
+{
+       EmpathyChatroom *chatroom;
+       GtkTreeView    *view;
+       GtkTreeModel   *model;
+
+       view = GTK_TREE_VIEW (window->treeview);
+       model = gtk_tree_view_get_model (view);
+
+       chatroom = chatrooms_window_model_get_selected (window);
+       if (!chatroom) {
+               return;
+       }
+
+       //empathy_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom);
+
+       g_object_unref (chatroom);
+}
+
+static void
+chatrooms_window_row_activated_cb (GtkTreeView           *tree_view,
+                                  GtkTreePath           *path,
+                                  GtkTreeViewColumn     *column,
+                                  EmpathyChatroomsWindow *window)
+{
+       if (GTK_WIDGET_IS_SENSITIVE (window->button_edit)) {
+               chatrooms_window_model_action_selected (window);
+       }
+}
+
+static void
+chatrooms_window_button_remove_clicked_cb (GtkWidget             *widget,
+                                          EmpathyChatroomsWindow *window)
+{
+       EmpathyChatroom        *chatroom;
+       GtkTreeView           *view;
+       GtkTreeModel          *model;
+       GtkTreeSelection      *selection;
+       GtkTreeIter            iter;
+
+       /* Remove from treeview */
+       view = GTK_TREE_VIEW (window->treeview);
+       selection = gtk_tree_view_get_selection (view);
+
+       if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+               return;
+       }
+
+       gtk_tree_model_get (model, &iter, COL_POINTER, &chatroom, -1);
+       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+
+       /* Remove from config */
+       empathy_chatroom_manager_remove (window->manager, chatroom);
+
+       g_object_unref (chatroom);
+}
+
+static void
+chatrooms_window_button_edit_clicked_cb (GtkWidget             *widget,
+                                        EmpathyChatroomsWindow *window)
+{
+       EmpathyChatroom *chatroom;
+
+       chatroom = chatrooms_window_model_get_selected (window);
+       if (!chatroom) {
+               return;
+       }
+
+       //empathy_edit_chatroom_dialog_show (GTK_WINDOW (window->window), chatroom);
+
+       g_object_unref (chatroom);
+}
+
+static void
+chatrooms_window_button_close_clicked_cb (GtkWidget             *widget,
+                                         EmpathyChatroomsWindow *window)
+{
+       gtk_widget_destroy (window->window);
+}
+
+static void
+chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager,
+                                   EmpathyChatroom        *chatroom,
+                                   EmpathyChatroomsWindow *window)
+{
+       EmpathyAccountChooser *account_chooser;
+       McAccount            *account;
+
+       account_chooser = EMPATHY_ACCOUNT_CHOOSER (window->account_chooser);
+       account = empathy_account_chooser_get_account (account_chooser);
+
+       if (!account) {
+               chatrooms_window_model_add (window, chatroom, FALSE);
+       } else {
+               if (empathy_account_equal (account, empathy_chatroom_get_account (chatroom))) {
+                       chatrooms_window_model_add (window, chatroom, FALSE);
+               }
+
+               g_object_unref (account);
+       }
+}
+
+static void
+chatrooms_window_chatroom_removed_cb (EmpathyChatroomManager *manager,
+                                     EmpathyChatroom        *chatroom,
+                                     EmpathyChatroomsWindow *window)
+{
+       GtkTreeModel *model;
+
+       model = gtk_tree_view_get_model (GTK_TREE_VIEW (window->treeview));
+
+       gtk_tree_model_foreach (model,
+                               (GtkTreeModelForeachFunc) chatrooms_window_remove_chatroom_foreach,
+                               chatroom);
+}
+
+static gboolean
+chatrooms_window_remove_chatroom_foreach (GtkTreeModel   *model,
+                                         GtkTreePath    *path,
+                                         GtkTreeIter    *iter,
+                                         EmpathyChatroom *chatroom)
+{
+       EmpathyChatroom *this_chatroom;
+
+       gtk_tree_model_get (model, iter, COL_POINTER, &this_chatroom, -1);
+
+       if (empathy_chatroom_equal (chatroom, this_chatroom)) {
+               gtk_list_store_remove (GTK_LIST_STORE (model), iter);
+               g_object_unref (this_chatroom);
+               return TRUE;
+       }
+
+       g_object_unref (this_chatroom);
+
+       return FALSE;
+}
+
+static void
+chatrooms_window_account_changed_cb (GtkWidget             *combo_box,
+                                    EmpathyChatroomsWindow *window)
+{
+       chatrooms_window_model_refresh_data (window, FALSE);
+}
+
diff --git a/src/empathy-chatrooms-window.glade b/src/empathy-chatrooms-window.glade
new file mode 100644 (file)
index 0000000..3316e6e
--- /dev/null
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+  <widget class="GtkDialog" id="edit_chatroom_dialog">
+    <property name="visible">True</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Edit Favorite Room</property>
+    <property name="resizable">False</property>
+    <property name="icon_name">gtk-edit</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox3">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkTable" id="table4">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="n_rows">5</property>
+            <property name="n_columns">2</property>
+            <property name="column_spacing">12</property>
+            <property name="row_spacing">6</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <widget class="GtkCheckButton" id="checkbutton_auto_connect">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="tooltip" translatable="yes">Join this chat room when Empathy starts and you are connected</property>
+                <property name="label" translatable="yes">Join room on start_up</property>
+                <property name="use_underline">True</property>
+                <property name="response_id">0</property>
+                <property name="draw_indicator">True</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">4</property>
+                <property name="bottom_attach">5</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="entry_name">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">*</property>
+                <property name="width_chars">25</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label_name">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">N_ame:</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">entry_name</property>
+              </widget>
+              <packing>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label_nickname">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">_Nickname:</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">entry_nickname</property>
+              </widget>
+              <packing>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label_server">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">S_erver:</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">entry_server</property>
+              </widget>
+              <packing>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label_room">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">_Room:</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">entry_room</property>
+              </widget>
+              <packing>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+                <property name="x_options">GTK_FILL</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="entry_nickname">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">*</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">1</property>
+                <property name="bottom_attach">2</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="entry_server">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">*</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">2</property>
+                <property name="bottom_attach">3</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkEntry" id="entry_room">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">*</property>
+              </widget>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="right_attach">2</property>
+                <property name="top_attach">3</property>
+                <property name="bottom_attach">4</property>
+                <property name="y_options"></property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area3">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button_cancel">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-cancel</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-6</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_save">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-save</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-5</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="GtkWindow" id="chatrooms_window">
+    <property name="visible">True</property>
+    <property name="border_width">12</property>
+    <property name="title" translatable="yes">Manage Favorite Rooms</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <child>
+      <widget class="GtkVBox" id="vbox12">
+        <property name="visible">True</property>
+        <property name="spacing">12</property>
+        <child>
+          <widget class="GtkVBox" id="vbox18">
+            <property name="visible">True</property>
+            <property name="spacing">18</property>
+            <child>
+              <widget class="GtkHBox" id="hbox_account">
+                <property name="visible">True</property>
+                <property name="spacing">12</property>
+                <child>
+                  <widget class="GtkLabel" id="label_account">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Account:</property>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </widget>
+              <packing>
+                <property name="expand">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="height_request">150</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+                <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                <property name="shadow_type">GTK_SHADOW_IN</property>
+                <child>
+                  <widget class="GtkTreeView" id="treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="has_focus">True</property>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+        </child>
+        <child>
+          <widget class="GtkHButtonBox" id="hbuttonbox3">
+            <property name="visible">True</property>
+            <property name="spacing">6</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button_remove">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-remove</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_edit">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-edit</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_close">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">0</property>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/src/empathy-chatrooms-window.h b/src/empathy-chatrooms-window.h
new file mode 100644 (file)
index 0000000..c931c78
--- /dev/null
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ *          Martyn Russell <martyn@imendio.com>
+ *          Mikael Hallendal <micke@imendio.com>
+ */
+
+#ifndef __EMPATHY_CHATROOMS_WINDOW_H__
+#define __EMPATHY_CHATROOMS_WINDOW_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+void empathy_chatrooms_window_show (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_CHATROOMS_WINDOW_H__ */
diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c
new file mode 100644 (file)
index 0000000..6f3ad54
--- /dev/null
@@ -0,0 +1,1167 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002-2007 Imendio AB
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <sys/stat.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <glib/gi18n.h>
+
+#include <libempathy/empathy-contact.h>
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-chatroom-manager.h>
+#include <libempathy/empathy-chatroom.h>
+#include <libempathy/empathy-contact-list.h>
+#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact-factory.h>
+#include <libempathy/empathy-status-presets.h>
+
+#include <libempathy-gtk/empathy-contact-dialogs.h>
+#include <libempathy-gtk/empathy-contact-list-store.h>
+#include <libempathy-gtk/empathy-contact-list-view.h>
+#include <libempathy-gtk/empathy-presence-chooser.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+#include <libempathy-gtk/empathy-geometry.h>
+#include <libempathy-gtk/empathy-conf.h>
+#include <libempathy-gtk/empathy-accounts-dialog.h>
+#include <libempathy-gtk/empathy-log-window.h>
+#include <libempathy-gtk/empathy-new-message-dialog.h>
+#include <libempathy-gtk/empathy-gtk-enum-types.h>
+
+#include "empathy-main-window.h"
+#include "ephy-spinner.h"
+#include "empathy-preferences.h"
+#include "empathy-about-dialog.h"
+#include "empathy-new-chatroom-dialog.h"
+#include "empathy-chatrooms-window.h"
+
+#define DEBUG_DOMAIN "MainWindow"
+
+/* Minimum width of roster window if something goes wrong. */
+#define MIN_WIDTH 50
+
+/* Accels (menu shortcuts) can be configured and saved */
+#define ACCELS_FILENAME "accels.txt"
+
+/* Name in the geometry file */
+#define GEOMETRY_NAME "main-window"
+
+typedef struct {
+       EmpathyContactListView  *list_view;
+       EmpathyContactListStore *list_store;
+       MissionControl          *mc;
+       EmpathyChatroomManager  *chatroom_manager;
+
+       GtkWidget              *window;
+       GtkWidget              *main_vbox;
+       GtkWidget              *throbber;
+       GtkWidget              *presence_toolbar;
+       GtkWidget              *presence_chooser;
+       GtkWidget              *errors_vbox;
+
+       GtkWidget              *room;
+       GtkWidget              *room_menu;
+       GtkWidget              *room_sep;
+       GtkWidget              *room_join_favorites;
+       GtkWidget              *edit_context;
+       GtkWidget              *edit_context_separator;
+
+       guint                   size_timeout_id;
+       GHashTable             *errors;
+
+       /* Widgets that are enabled when there is... */
+       GList                  *widgets_connected;      /* ... connected accounts */
+       GList                  *widgets_disconnected;   /* ... disconnected accounts */
+} EmpathyMainWindow;
+
+static void     main_window_destroy_cb                         (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_favorite_chatroom_menu_setup       (EmpathyMainWindow        *window);
+static void     main_window_favorite_chatroom_menu_added_cb    (EmpathyChatroomManager   *manager,
+                                                               EmpathyChatroom          *chatroom,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_favorite_chatroom_menu_removed_cb  (EmpathyChatroomManager   *manager,
+                                                               EmpathyChatroom          *chatroom,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem              *menu_item,
+                                                               EmpathyChatroom          *chatroom);
+static void     main_window_favorite_chatroom_menu_update      (EmpathyMainWindow        *window);
+static void     main_window_favorite_chatroom_menu_add         (EmpathyMainWindow        *window,
+                                                               EmpathyChatroom          *chatroom);
+static void     main_window_favorite_chatroom_join             (EmpathyChatroom          *chatroom);
+static void     main_window_chat_quit_cb                       (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_chat_new_message_cb                (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_chat_history_cb                    (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_room_join_new_cb                   (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_room_join_favorites_cb             (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_room_manage_favorites_cb           (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_chat_add_contact_cb                (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_chat_show_offline_cb               (GtkCheckMenuItem         *item,
+                                                               EmpathyMainWindow        *window);
+static gboolean main_window_edit_button_press_event_cb         (GtkWidget                *widget,
+                                                               GdkEventButton           *event,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_edit_accounts_cb                   (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_edit_personal_information_cb       (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_edit_preferences_cb                (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_help_about_cb                      (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_help_contents_cb                   (GtkWidget                *widget,
+                                                               EmpathyMainWindow        *window);
+static gboolean main_window_throbber_button_press_event_cb     (GtkWidget                *throbber_ebox,
+                                                               GdkEventButton           *event,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_status_changed_cb                  (MissionControl           *mc,
+                                                               TpConnectionStatus        status,
+                                                               McPresence                presence,
+                                                               TpConnectionStatusReason  reason,
+                                                               const gchar              *unique_name,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_update_status                      (EmpathyMainWindow        *window);
+static void     main_window_accels_load                        (void);
+static void     main_window_accels_save                        (void);
+static void     main_window_connection_items_setup             (EmpathyMainWindow        *window,
+                                                               GladeXML                 *glade);
+static gboolean main_window_configure_event_timeout_cb         (EmpathyMainWindow        *window);
+static gboolean main_window_configure_event_cb                 (GtkWidget                *widget,
+                                                               GdkEventConfigure        *event,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_notify_show_offline_cb             (EmpathyConf              *conf,
+                                                               const gchar              *key,
+                                                               gpointer                  check_menu_item);
+static void     main_window_notify_show_avatars_cb             (EmpathyConf              *conf,
+                                                               const gchar              *key,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_notify_compact_contact_list_cb     (EmpathyConf              *conf,
+                                                               const gchar              *key,
+                                                               EmpathyMainWindow        *window);
+static void     main_window_notify_sort_criterium_cb           (EmpathyConf              *conf,
+                                                               const gchar              *key,
+                                                               EmpathyMainWindow        *window);
+
+GtkWidget *
+empathy_main_window_show (void)
+{
+       static EmpathyMainWindow *window = NULL;
+       EmpathyContactList       *list_iface;
+       GladeXML                 *glade;
+       EmpathyConf               *conf;
+       GtkWidget                *sw;
+       GtkWidget                *show_offline_widget;
+       GtkWidget                *ebox;
+       GtkToolItem              *item;
+       gboolean                  show_offline;
+       gboolean                  show_avatars;
+       gboolean                  compact_contact_list;
+       gint                      x, y, w, h;
+
+       if (window) {
+               empathy_window_present (GTK_WINDOW (window->window), TRUE);
+               return window->window;
+       }
+
+       window = g_new0 (EmpathyMainWindow, 1);
+
+       /* Set up interface */
+       glade = empathy_glade_get_file ("empathy-main-window.glade",
+                                      "main_window",
+                                      NULL,
+                                      "main_window", &window->window,
+                                      "main_vbox", &window->main_vbox,
+                                      "errors_vbox", &window->errors_vbox,
+                                      "chat_show_offline", &show_offline_widget,
+                                      "room", &window->room,
+                                      "room_sep", &window->room_sep,
+                                      "room_join_favorites", &window->room_join_favorites,
+                                      "edit_context", &window->edit_context,
+                                      "edit_context_separator", &window->edit_context_separator,
+                                      "presence_toolbar", &window->presence_toolbar,
+                                      "roster_scrolledwindow", &sw,
+                                      NULL);
+
+       empathy_glade_connect (glade,
+                             window,
+                             "main_window", "destroy", main_window_destroy_cb,
+                             "main_window", "configure_event", main_window_configure_event_cb,
+                             "chat_quit", "activate", main_window_chat_quit_cb,
+                             "chat_new_message", "activate", main_window_chat_new_message_cb,
+                             "chat_history", "activate", main_window_chat_history_cb,
+                             "room_join_new", "activate", main_window_room_join_new_cb,
+                             "room_join_favorites", "activate", main_window_room_join_favorites_cb,
+                             "room_manage_favorites", "activate", main_window_room_manage_favorites_cb,
+                             "chat_add_contact", "activate", main_window_chat_add_contact_cb,
+                             "chat_show_offline", "toggled", main_window_chat_show_offline_cb,
+                             "edit", "button-press-event", main_window_edit_button_press_event_cb,
+                             "edit_accounts", "activate", main_window_edit_accounts_cb,
+                             "edit_personal_information", "activate", main_window_edit_personal_information_cb,
+                             "edit_preferences", "activate", main_window_edit_preferences_cb,
+                             "help_about", "activate", main_window_help_about_cb,
+                             "help_contents", "activate", main_window_help_contents_cb,
+                             NULL);
+
+       /* Set up connection related widgets. */
+       main_window_connection_items_setup (window, glade);
+       g_object_unref (glade);
+
+       window->mc = empathy_mission_control_new ();
+       dbus_g_proxy_connect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged",
+                                    G_CALLBACK (main_window_status_changed_cb),
+                                    window, NULL);
+
+       window->errors = g_hash_table_new_full (empathy_account_hash,
+                                               empathy_account_equal,
+                                               g_object_unref,
+                                               NULL);
+
+       /* Set up menu */
+       main_window_favorite_chatroom_menu_setup (window);
+
+       gtk_widget_hide (window->edit_context);
+       gtk_widget_hide (window->edit_context_separator);
+
+       /* Set up presence chooser */
+       window->presence_chooser = empathy_presence_chooser_new ();
+       gtk_widget_show (window->presence_chooser);
+       item = gtk_tool_item_new ();
+       gtk_widget_show (GTK_WIDGET (item));
+       gtk_container_add (GTK_CONTAINER (item), window->presence_chooser);
+       gtk_tool_item_set_is_important (item, TRUE);
+       gtk_tool_item_set_expand (item, TRUE);
+       gtk_toolbar_insert (GTK_TOOLBAR (window->presence_toolbar), item, -1);
+
+       /* Set up the throbber */
+       ebox = gtk_event_box_new ();
+       gtk_event_box_set_visible_window (GTK_EVENT_BOX (ebox), FALSE);
+       gtk_widget_set_tooltip_text (ebox, _("Show and edit accounts"));
+       g_signal_connect (ebox,
+                         "button-press-event",
+                         G_CALLBACK (main_window_throbber_button_press_event_cb),
+                         window);
+       gtk_widget_show (ebox);
+
+       window->throbber = ephy_spinner_new ();
+       ephy_spinner_set_size (EPHY_SPINNER (window->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR);
+       gtk_container_add (GTK_CONTAINER (ebox), window->throbber);
+       gtk_widget_show (window->throbber);
+
+       item = gtk_tool_item_new ();
+       gtk_container_add (GTK_CONTAINER (item), ebox);
+       gtk_toolbar_insert (GTK_TOOLBAR (window->presence_toolbar), item, -1);
+       gtk_widget_show (GTK_WIDGET (item));
+
+       /* Set up contact list. */
+       empathy_status_presets_get_all ();
+
+       list_iface = EMPATHY_CONTACT_LIST (empathy_contact_manager_new ());
+       window->list_store = empathy_contact_list_store_new (list_iface);
+       window->list_view = empathy_contact_list_view_new (window->list_store,
+                                                          EMPATHY_CONTACT_LIST_FEATURE_ALL);
+       g_object_unref (list_iface);
+
+       gtk_widget_show (GTK_WIDGET (window->list_view));
+       gtk_container_add (GTK_CONTAINER (sw),
+                          GTK_WIDGET (window->list_view));
+
+       /* Load user-defined accelerators. */
+       main_window_accels_load ();
+
+       /* Set window size. */
+       empathy_geometry_load (GEOMETRY_NAME, &x, &y, &w, &h);
+
+       if (w >= 1 && h >= 1) {
+               /* Use the defaults from the glade file if we
+                * don't have good w, h geometry.
+                */
+               empathy_debug (DEBUG_DOMAIN, "Configuring window default size w:%d, h:%d", w, h);
+               gtk_window_set_default_size (GTK_WINDOW (window->window), w, h);
+       }
+
+       if (x >= 0 && y >= 0) {
+               /* Let the window manager position it if we
+                * don't have good x, y coordinates.
+                */
+               empathy_debug (DEBUG_DOMAIN, "Configuring window default position x:%d, y:%d", x, y);
+               gtk_window_move (GTK_WINDOW (window->window), x, y);
+       }
+
+       conf = empathy_conf_get ();
+       
+       /* Show offline ? */
+       empathy_conf_get_bool (conf,
+                             EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE,
+                             &show_offline);
+       empathy_conf_notify_add (conf,
+                               EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE,
+                               main_window_notify_show_offline_cb,
+                               show_offline_widget);
+
+       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (show_offline_widget),
+                                       show_offline);
+
+       /* Show avatars ? */
+       empathy_conf_get_bool (conf,
+                             EMPATHY_PREFS_UI_SHOW_AVATARS,
+                             &show_avatars);
+       empathy_conf_notify_add (conf,
+                               EMPATHY_PREFS_UI_SHOW_AVATARS,
+                               (EmpathyConfNotifyFunc) main_window_notify_show_avatars_cb,
+                               window);
+       empathy_contact_list_store_set_show_avatars (window->list_store, show_avatars);
+
+       /* Is compact ? */
+       empathy_conf_get_bool (conf,
+                             EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
+                             &compact_contact_list);
+       empathy_conf_notify_add (conf,
+                               EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
+                               (EmpathyConfNotifyFunc) main_window_notify_compact_contact_list_cb,
+                               window);
+       empathy_contact_list_store_set_is_compact (window->list_store, compact_contact_list);
+
+       /* Sort criterium */
+       empathy_conf_notify_add (conf,
+                               EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
+                               (EmpathyConfNotifyFunc) main_window_notify_sort_criterium_cb,
+                               window);
+       main_window_notify_sort_criterium_cb (conf,
+                                             EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
+                                             window);
+
+       main_window_update_status (window);
+
+       return window->window;
+}
+
+static void
+main_window_destroy_cb (GtkWidget         *widget,
+                       EmpathyMainWindow *window)
+{
+       /* Save user-defined accelerators. */
+       main_window_accels_save ();
+
+       dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (window->mc), "AccountStatusChanged",
+                                       G_CALLBACK (main_window_status_changed_cb),
+                                       window);
+
+       if (window->size_timeout_id) {
+               g_source_remove (window->size_timeout_id);
+       }
+
+       g_list_free (window->widgets_connected);
+       g_list_free (window->widgets_disconnected);
+
+       g_object_unref (window->mc);
+       g_object_unref (window->list_store);
+       g_hash_table_destroy (window->errors);
+
+       g_free (window);
+}
+
+static void
+main_window_favorite_chatroom_menu_setup (EmpathyMainWindow *window)
+{
+       GList *chatrooms, *l;
+
+       window->chatroom_manager = empathy_chatroom_manager_new ();
+       chatrooms = empathy_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
+       window->room_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (window->room));
+
+       for (l = chatrooms; l; l = l->next) {
+               main_window_favorite_chatroom_menu_add (window, l->data);
+       }
+
+       if (!chatrooms) {
+               gtk_widget_hide (window->room_sep);
+       }
+
+       gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL);
+
+       g_signal_connect (window->chatroom_manager, "chatroom-added",
+                         G_CALLBACK (main_window_favorite_chatroom_menu_added_cb),
+                         window);
+       g_signal_connect (window->chatroom_manager, "chatroom-removed",
+                         G_CALLBACK (main_window_favorite_chatroom_menu_removed_cb),
+                         window);
+
+       g_list_free (chatrooms);
+}
+
+static void
+main_window_favorite_chatroom_menu_added_cb (EmpathyChatroomManager *manager,
+                                            EmpathyChatroom        *chatroom,
+                                            EmpathyMainWindow     *window)
+{
+       main_window_favorite_chatroom_menu_add (window, chatroom);
+       gtk_widget_show (window->room_sep);
+       gtk_widget_set_sensitive (window->room_join_favorites, TRUE);
+}
+
+static void
+main_window_favorite_chatroom_menu_removed_cb (EmpathyChatroomManager *manager,
+                                              EmpathyChatroom        *chatroom,
+                                              EmpathyMainWindow     *window)
+{
+       GtkWidget *menu_item;
+
+       menu_item = g_object_get_data (G_OBJECT (chatroom), "menu_item");
+
+       g_object_set_data (G_OBJECT (chatroom), "menu_item", NULL);
+       gtk_widget_destroy (menu_item);
+
+       main_window_favorite_chatroom_menu_update (window);
+}
+
+static void
+main_window_favorite_chatroom_menu_activate_cb (GtkMenuItem    *menu_item,
+                                               EmpathyChatroom *chatroom)
+{
+       main_window_favorite_chatroom_join (chatroom);
+}
+
+static void
+main_window_favorite_chatroom_menu_update (EmpathyMainWindow *window)
+{
+       GList *chatrooms;
+
+       chatrooms = empathy_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
+
+       if (chatrooms) {
+               gtk_widget_show (window->room_sep);
+       } else {
+               gtk_widget_hide (window->room_sep);
+       }
+
+       gtk_widget_set_sensitive (window->room_join_favorites, chatrooms != NULL);
+       g_list_free (chatrooms);
+}
+
+static void
+main_window_favorite_chatroom_menu_add (EmpathyMainWindow *window,
+                                       EmpathyChatroom    *chatroom)
+{
+       GtkWidget   *menu_item;
+       const gchar *name;
+
+       if (g_object_get_data (G_OBJECT (chatroom), "menu_item")) {
+               return;
+       }
+
+       name = empathy_chatroom_get_name (chatroom);
+       menu_item = gtk_menu_item_new_with_label (name);
+
+       g_object_set_data (G_OBJECT (chatroom), "menu_item", menu_item);
+       g_signal_connect (menu_item, "activate",
+                         G_CALLBACK (main_window_favorite_chatroom_menu_activate_cb),
+                         chatroom);
+
+       gtk_menu_shell_insert (GTK_MENU_SHELL (window->room_menu),
+                              menu_item, 3);
+
+       gtk_widget_show (menu_item);
+}
+
+static void
+main_window_favorite_chatroom_join (EmpathyChatroom *chatroom)
+{
+       MissionControl *mc;
+       McAccount      *account;
+       const gchar    *room;
+
+       mc = empathy_mission_control_new ();
+       account = empathy_chatroom_get_account (chatroom);
+       room = empathy_chatroom_get_room (chatroom);
+
+       empathy_debug (DEBUG_DOMAIN, "Requesting channel for '%s'", room);
+
+       mission_control_request_channel_with_string_handle (mc,
+                                                           account,
+                                                           TP_IFACE_CHANNEL_TYPE_TEXT,
+                                                           room,
+                                                           TP_HANDLE_TYPE_ROOM,
+                                                           NULL, NULL);        
+       g_object_unref (mc);
+}
+
+static void
+main_window_chat_quit_cb (GtkWidget         *widget,
+                         EmpathyMainWindow *window)
+{
+       gtk_main_quit ();
+}
+
+static void
+main_window_chat_new_message_cb (GtkWidget         *widget,
+                                EmpathyMainWindow *window)
+{
+       empathy_new_message_dialog_show (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_chat_history_cb (GtkWidget         *widget,
+                            EmpathyMainWindow *window)
+{
+       empathy_log_window_show (NULL, NULL, FALSE, GTK_WINDOW (window->window));
+}
+
+static void
+main_window_room_join_new_cb (GtkWidget         *widget,
+                             EmpathyMainWindow *window)
+{
+       empathy_new_chatroom_dialog_show (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_room_join_favorites_cb (GtkWidget         *widget,
+                                   EmpathyMainWindow *window)
+{
+       GList *chatrooms, *l;
+
+       chatrooms = empathy_chatroom_manager_get_chatrooms (window->chatroom_manager, NULL);
+       for (l = chatrooms; l; l = l->next) {
+               main_window_favorite_chatroom_join (l->data);
+       }
+       g_list_free (chatrooms);
+}
+
+static void
+main_window_room_manage_favorites_cb (GtkWidget         *widget,
+                                     EmpathyMainWindow *window)
+{
+       empathy_chatrooms_window_show (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_chat_add_contact_cb (GtkWidget         *widget,
+                                EmpathyMainWindow *window)
+{
+       empathy_new_contact_dialog_show (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_chat_show_offline_cb (GtkCheckMenuItem  *item,
+                                 EmpathyMainWindow *window)
+{
+       gboolean current;
+
+       current = gtk_check_menu_item_get_active (item);
+
+       empathy_conf_set_bool (empathy_conf_get (),
+                             EMPATHY_PREFS_CONTACTS_SHOW_OFFLINE,
+                             current);
+
+       /* Turn off sound just while we alter the contact list. */
+       // FIXME: empathy_sound_set_enabled (FALSE);
+       empathy_contact_list_store_set_show_offline (window->list_store, current);
+       //empathy_sound_set_enabled (TRUE);
+}
+
+static gboolean
+main_window_edit_button_press_event_cb (GtkWidget         *widget,
+                                       GdkEventButton    *event,
+                                       EmpathyMainWindow *window)
+{
+       EmpathyContact *contact;
+       gchar         *group;
+
+       if (!event->button == 1) {
+               return FALSE;
+       }
+
+       group = empathy_contact_list_view_get_selected_group (window->list_view);
+       if (group) {
+               GtkMenuItem *item;
+               GtkWidget   *label;
+               GtkWidget   *submenu;
+
+               item = GTK_MENU_ITEM (window->edit_context);
+               label = gtk_bin_get_child (GTK_BIN (item));
+               gtk_label_set_text (GTK_LABEL (label), _("Group"));
+
+               gtk_widget_show (window->edit_context);
+               gtk_widget_show (window->edit_context_separator);
+
+               submenu = empathy_contact_list_view_get_group_menu (window->list_view);
+               gtk_menu_item_set_submenu (item, submenu);
+
+               g_free (group);
+
+               return FALSE;
+       }
+
+       contact = empathy_contact_list_view_get_selected (window->list_view);
+       if (contact) {
+               GtkMenuItem *item;
+               GtkWidget   *label;
+               GtkWidget   *submenu;
+
+               item = GTK_MENU_ITEM (window->edit_context);
+               label = gtk_bin_get_child (GTK_BIN (item));
+               gtk_label_set_text (GTK_LABEL (label), _("Contact"));
+
+               gtk_widget_show (window->edit_context);
+               gtk_widget_show (window->edit_context_separator);
+
+               submenu = empathy_contact_list_view_get_contact_menu (window->list_view,
+                                                                    contact);
+               gtk_menu_item_set_submenu (item, submenu);
+
+               g_object_unref (contact);
+
+               return FALSE;
+       }
+
+       gtk_widget_hide (window->edit_context);
+       gtk_widget_hide (window->edit_context_separator);
+
+       return FALSE;
+}
+
+static void
+main_window_edit_accounts_cb (GtkWidget         *widget,
+                             EmpathyMainWindow *window)
+{
+       empathy_accounts_dialog_show (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_edit_personal_information_cb (GtkWidget         *widget,
+                                         EmpathyMainWindow *window)
+{
+       GSList *accounts;
+
+       accounts = mission_control_get_online_connections (window->mc, NULL);
+       if (accounts) {
+               EmpathyContactFactory *factory;
+               EmpathyContact        *contact;
+               McAccount             *account;
+
+               account = accounts->data;
+               factory = empathy_contact_factory_new ();
+               contact = empathy_contact_factory_get_user (factory, account);
+               empathy_contact_run_until_ready (contact,
+                                                EMPATHY_CONTACT_READY_HANDLE |
+                                                EMPATHY_CONTACT_READY_ID,
+                                                NULL);
+
+               empathy_contact_information_dialog_show (contact,
+                                                        GTK_WINDOW (window->window),
+                                                        TRUE, TRUE);
+
+               g_slist_foreach (accounts, (GFunc) g_object_unref, NULL);
+               g_slist_free (accounts);
+               g_object_unref (factory);
+               g_object_unref (contact);
+       }
+}
+
+static void
+main_window_edit_preferences_cb (GtkWidget         *widget,
+                                EmpathyMainWindow *window)
+{
+       empathy_preferences_show (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_help_about_cb (GtkWidget         *widget,
+                          EmpathyMainWindow *window)
+{
+       empathy_about_dialog_new (GTK_WINDOW (window->window));
+}
+
+static void
+main_window_help_contents_cb (GtkWidget         *widget,
+                             EmpathyMainWindow *window)
+{
+       //empathy_help_show ();
+}
+
+static gboolean
+main_window_throbber_button_press_event_cb (GtkWidget         *throbber_ebox,
+                                           GdkEventButton    *event,
+                                           EmpathyMainWindow *window)
+{
+       if (event->type != GDK_BUTTON_PRESS ||
+           event->button != 1) {
+               return FALSE;
+       }
+
+       empathy_accounts_dialog_show (GTK_WINDOW (window->window));
+
+       return FALSE;
+}
+
+static void
+main_window_error_edit_clicked_cb (GtkButton         *button,
+                                  EmpathyMainWindow *window)
+{
+       McAccount *account;
+       GtkWidget *error_widget;
+
+       empathy_accounts_dialog_show (GTK_WINDOW (window->window));
+
+       account = g_object_get_data (G_OBJECT (button), "account");
+       error_widget = g_hash_table_lookup (window->errors, account);
+       gtk_widget_destroy (error_widget);
+       g_hash_table_remove (window->errors, account);
+}
+
+static void
+main_window_error_clear_clicked_cb (GtkButton         *button,
+                                   EmpathyMainWindow *window)
+{
+       McAccount *account;
+       GtkWidget *error_widget;
+
+       account = g_object_get_data (G_OBJECT (button), "account");
+       error_widget = g_hash_table_lookup (window->errors, account);
+       gtk_widget_destroy (error_widget);
+       g_hash_table_remove (window->errors, account);
+}
+
+static void
+main_window_error_display (EmpathyMainWindow *window,
+                          McAccount         *account,
+                          const gchar       *message)
+{
+       GtkWidget *child;
+       GtkWidget *table;
+       GtkWidget *image;
+       GtkWidget *button_edit;
+       GtkWidget *alignment;
+       GtkWidget *hbox;
+       GtkWidget *label;
+       GtkWidget *fixed;
+       GtkWidget *vbox;
+       GtkWidget *button_close;
+       gchar     *str;
+
+       child = g_hash_table_lookup (window->errors, account);
+       if (child) {
+               label = g_object_get_data (G_OBJECT (child), "label");
+
+               /* Just set the latest error and return */
+               str = g_markup_printf_escaped ("<b>%s</b>\n%s",
+                                              mc_account_get_display_name (account),
+                                              message);
+               gtk_label_set_markup (GTK_LABEL (label), str);
+               g_free (str);
+
+               return;
+       }
+
+       child = gtk_vbox_new (FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (window->errors_vbox), child, FALSE, TRUE, 0);
+       gtk_container_set_border_width (GTK_CONTAINER (child), 6);
+       gtk_widget_show (child);
+
+       table = gtk_table_new (2, 4, FALSE);
+       gtk_widget_show (table);
+       gtk_box_pack_start (GTK_BOX (child), table, TRUE, TRUE, 0);
+       gtk_table_set_row_spacings (GTK_TABLE (table), 12);
+       gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+
+       image = gtk_image_new_from_stock (GTK_STOCK_DISCONNECT, GTK_ICON_SIZE_MENU);
+       gtk_widget_show (image);
+       gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 2,
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (GTK_FILL), 0, 0);
+       gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0);
+
+       button_edit = gtk_button_new ();
+       gtk_widget_show (button_edit);
+       gtk_table_attach (GTK_TABLE (table), button_edit, 1, 2, 1, 2,
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (0), 0, 0);
+
+       alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
+       gtk_widget_show (alignment);
+       gtk_container_add (GTK_CONTAINER (button_edit), alignment);
+
+       hbox = gtk_hbox_new (FALSE, 2);
+       gtk_widget_show (hbox);
+       gtk_container_add (GTK_CONTAINER (alignment), hbox);
+
+       image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
+       gtk_widget_show (image);
+       gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+
+       label = gtk_label_new_with_mnemonic (_("_Edit account"));
+       gtk_widget_show (label);
+       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+       fixed = gtk_fixed_new ();
+       gtk_widget_show (fixed);
+       gtk_table_attach (GTK_TABLE (table), fixed, 2, 3, 1, 2,
+                         (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                         (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+       vbox = gtk_vbox_new (FALSE, 6);
+       gtk_widget_show (vbox);
+       gtk_table_attach (GTK_TABLE (table), vbox, 3, 4, 0, 2,
+                         (GtkAttachOptions) (GTK_FILL),
+                         (GtkAttachOptions) (GTK_FILL), 0, 0);
+
+       button_close = gtk_button_new ();
+       gtk_widget_show (button_close);
+       gtk_box_pack_start (GTK_BOX (vbox), button_close, FALSE, FALSE, 0);
+       gtk_button_set_relief (GTK_BUTTON (button_close), GTK_RELIEF_NONE);
+
+
+       image = gtk_image_new_from_stock ("gtk-close", GTK_ICON_SIZE_MENU);
+       gtk_widget_show (image);
+       gtk_container_add (GTK_CONTAINER (button_close), image);
+
+       label = gtk_label_new ("");
+       gtk_widget_show (label);
+       gtk_table_attach (GTK_TABLE (table), label, 1, 3, 0, 1,
+                         (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL),
+                         (GtkAttachOptions) (GTK_EXPAND | GTK_SHRINK | GTK_FILL), 0, 0);
+       gtk_widget_set_size_request (label, 175, -1);
+       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
+
+       str = g_markup_printf_escaped ("<b>%s</b>\n%s",
+                                      mc_account_get_display_name (account),
+                                      message);
+       gtk_label_set_markup (GTK_LABEL (label), str);
+       g_free (str);
+
+       g_object_set_data (G_OBJECT (child), "label", label);
+       g_object_set_data_full (G_OBJECT (button_edit),
+                               "account", g_object_ref (account),
+                               g_object_unref);
+       g_object_set_data_full (G_OBJECT (button_close),
+                               "account", g_object_ref (account),
+                               g_object_unref);
+
+       g_signal_connect (button_edit, "clicked",
+                         G_CALLBACK (main_window_error_edit_clicked_cb),
+                         window);
+
+       g_signal_connect (button_close, "clicked",
+                         G_CALLBACK (main_window_error_clear_clicked_cb),
+                         window);
+
+       gtk_widget_show (window->errors_vbox);
+
+       g_hash_table_insert (window->errors, g_object_ref (account), child);
+}
+
+static void
+main_window_status_changed_cb (MissionControl           *mc,
+                              TpConnectionStatus        status,
+                              McPresence                presence,
+                              TpConnectionStatusReason  reason,
+                              const gchar              *unique_name,
+                              EmpathyMainWindow        *window)
+{
+       McAccount *account;
+
+       main_window_update_status (window);
+
+       account = mc_account_lookup (unique_name);
+
+       if (status == TP_CONNECTION_STATUS_DISCONNECTED &&
+           reason > TP_CONNECTION_STATUS_REASON_REQUESTED) {
+               const gchar *message;
+
+               switch (reason) {
+               case TP_CONNECTION_STATUS_REASON_NETWORK_ERROR:
+                       message = _("Network error");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED:
+                       message = _("Authentication failed");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR:
+                       message = _("Encryption error");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_NAME_IN_USE:
+                       message = _("Name in use");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_NOT_PROVIDED:
+                       message = _("Certificate not provided");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_UNTRUSTED:
+                       message = _("Certificate untrusted");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_EXPIRED:
+                       message = _("Certificate expired");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_NOT_ACTIVATED:
+                       message = _("Certificate not activated");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_HOSTNAME_MISMATCH:
+                       message = _("Certificate hostname mismatch");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_FINGERPRINT_MISMATCH:
+                       message = _("Certificate fingerprint mismatch");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_SELF_SIGNED:
+                       message = _("Certificate self signed");
+                       break;
+               case TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR:
+                       message = _("Certificate error");
+                       break;
+               default:
+                       message = _("Unknown error");
+                       break;
+               }
+
+               main_window_error_display (window, account, message);
+       }
+
+       if (status == TP_CONNECTION_STATUS_CONNECTED) {
+               GtkWidget *error_widget;
+
+               /* Account connected without error, remove error message if any */
+               error_widget = g_hash_table_lookup (window->errors, account);
+               if (error_widget) {
+                       gtk_widget_destroy (error_widget);
+                       g_hash_table_remove (window->errors, account);
+               }
+       }
+
+       g_object_unref (account);
+}
+
+static void
+main_window_update_status (EmpathyMainWindow *window)
+{
+       GList *accounts, *l;
+       guint  connected = 0;
+       guint  connecting = 0;
+       guint  disconnected = 0;
+
+       /* Count number of connected/connecting/disconnected accounts */
+       accounts = mc_accounts_list (); 
+       for (l = accounts; l; l = l->next) {
+               McAccount *account;
+               guint      status;
+
+               account = l->data;
+
+               status = mission_control_get_connection_status (window->mc,
+                                                               account,
+                                                               NULL);
+
+               if (status == 0) {
+                       connected++;
+               } else if (status == 1) {
+                       connecting++;
+               } else if (status == 2) {
+                       disconnected++;
+               }
+
+               g_object_unref (account);
+       }
+       g_list_free (accounts);
+
+       /* Update the spinner state */
+       if (connecting > 0) {
+               ephy_spinner_start (EPHY_SPINNER (window->throbber));
+       } else {
+               ephy_spinner_stop (EPHY_SPINNER (window->throbber));
+       }
+
+       /* Update widgets sensibility */
+       for (l = window->widgets_connected; l; l = l->next) {
+               gtk_widget_set_sensitive (l->data, (connected > 0));
+       }
+
+       for (l = window->widgets_disconnected; l; l = l->next) {
+               gtk_widget_set_sensitive (l->data, (disconnected > 0));
+       }
+}
+
+/*
+ * Accels
+ */
+static void
+main_window_accels_load (void)
+{
+       gchar *filename;
+
+       filename = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, ACCELS_FILENAME, NULL);
+       if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
+               empathy_debug (DEBUG_DOMAIN, "Loading from:'%s'", filename);
+               gtk_accel_map_load (filename);
+       }
+
+       g_free (filename);
+}
+
+static void
+main_window_accels_save (void)
+{
+       gchar *dir;
+       gchar *file_with_path;
+
+       dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL);
+       g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
+       file_with_path = g_build_filename (dir, ACCELS_FILENAME, NULL);
+       g_free (dir);
+
+       empathy_debug (DEBUG_DOMAIN, "Saving to:'%s'", file_with_path);
+       gtk_accel_map_save (file_with_path);
+
+       g_free (file_with_path);
+}
+
+static void
+main_window_connection_items_setup (EmpathyMainWindow *window,
+                                   GladeXML          *glade)
+{
+       GList         *list;
+       GtkWidget     *w;
+       gint           i;
+       const gchar *widgets_connected[] = {
+               "room",
+               "chat_new_message",
+               "chat_add_contact",
+               "edit_personal_information"
+       };
+       const gchar *widgets_disconnected[] = {
+       };
+
+       for (i = 0, list = NULL; i < G_N_ELEMENTS (widgets_connected); i++) {
+               w = glade_xml_get_widget (glade, widgets_connected[i]);
+               list = g_list_prepend (list, w);
+       }
+
+       window->widgets_connected = list;
+
+       for (i = 0, list = NULL; i < G_N_ELEMENTS (widgets_disconnected); i++) {
+               w = glade_xml_get_widget (glade, widgets_disconnected[i]);
+               list = g_list_prepend (list, w);
+       }
+
+       window->widgets_disconnected = list;
+}
+
+static gboolean
+main_window_configure_event_timeout_cb (EmpathyMainWindow *window)
+{
+       gint x, y, w, h;
+
+       gtk_window_get_size (GTK_WINDOW (window->window), &w, &h);
+       gtk_window_get_position (GTK_WINDOW (window->window), &x, &y);
+
+       empathy_geometry_save (GEOMETRY_NAME, x, y, w, h);
+
+       window->size_timeout_id = 0;
+
+       return FALSE;
+}
+
+static gboolean
+main_window_configure_event_cb (GtkWidget         *widget,
+                               GdkEventConfigure *event,
+                               EmpathyMainWindow *window)
+{
+       if (window->size_timeout_id) {
+               g_source_remove (window->size_timeout_id);
+       }
+
+       window->size_timeout_id = g_timeout_add_seconds (1,
+                                                        (GSourceFunc) main_window_configure_event_timeout_cb,
+                                                        window);
+
+       return FALSE;
+}
+
+static void
+main_window_notify_show_offline_cb (EmpathyConf  *conf,
+                                   const gchar *key,
+                                   gpointer     check_menu_item)
+{
+       gboolean show_offline;
+
+       if (empathy_conf_get_bool (conf, key, &show_offline)) {
+               gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (check_menu_item),
+                                               show_offline);
+       }
+}
+
+static void
+main_window_notify_show_avatars_cb (EmpathyConf        *conf,
+                                   const gchar       *key,
+                                   EmpathyMainWindow *window)
+{
+       gboolean show_avatars;
+
+       if (empathy_conf_get_bool (conf, key, &show_avatars)) {
+               empathy_contact_list_store_set_show_avatars (window->list_store,
+                                                           show_avatars);
+       }
+}
+
+static void
+main_window_notify_compact_contact_list_cb (EmpathyConf        *conf,
+                                           const gchar       *key,
+                                           EmpathyMainWindow *window)
+{
+       gboolean compact_contact_list;
+
+       if (empathy_conf_get_bool (conf, key, &compact_contact_list)) {
+               empathy_contact_list_store_set_is_compact (window->list_store,
+                                                         compact_contact_list);
+       }
+}
+
+static void
+main_window_notify_sort_criterium_cb (EmpathyConf       *conf,
+                                     const gchar       *key,
+                                     EmpathyMainWindow *window)
+{
+       gchar *str = NULL;
+
+       if (empathy_conf_get_string (conf, key, &str) && str) {
+               GType       type;
+               GEnumClass *enum_class;
+               GEnumValue *enum_value;
+
+               type = empathy_contact_list_store_sort_get_type ();
+               enum_class = G_ENUM_CLASS (g_type_class_peek (type));
+               enum_value = g_enum_get_value_by_nick (enum_class, str);
+               g_free (str);
+
+               if (enum_value) {
+                       empathy_contact_list_store_set_sort_criterium (window->list_store, 
+                                                                      enum_value->value);
+               }
+       }
+}
+
diff --git a/src/empathy-main-window.glade b/src/empathy-main-window.glade
new file mode 100644 (file)
index 0000000..5ac2187
--- /dev/null
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+  <widget class="GtkWindow" id="main_window">
+    <property name="title" translatable="yes">Contact List</property>
+    <property name="default_width">225</property>
+    <property name="default_height">325</property>
+    <child>
+      <widget class="GtkVBox" id="main_vbox">
+        <property name="visible">True</property>
+        <child>
+          <widget class="GtkMenuBar" id="menubar2">
+            <property name="visible">True</property>
+            <child>
+              <widget class="GtkMenuItem" id="chat">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Chat</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="chat_menu">
+                    <child>
+                      <widget class="GtkImageMenuItem" id="chat_new_message">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_New Conversation...</property>
+                        <property name="use_underline">True</property>
+                        <accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image885">
+                            <property name="visible">True</property>
+                            <property name="icon_size">1</property>
+                            <property name="icon_name">im-message-new</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="chat_history">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_View Previous Conversations</property>
+                        <property name="use_underline">True</property>
+                        <accelerator key="F3" modifiers="" signal="activate"/>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image886">
+                            <property name="visible">True</property>
+                            <property name="icon_size">1</property>
+                            <property name="icon_name">document-open-recent</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="separator5">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="chat_add_contact">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Add Contact...</property>
+                        <property name="use_underline">True</property>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image887">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-add</property>
+                            <property name="icon_size">1</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="separator3">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkCheckMenuItem" id="chat_show_offline">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Show _Offline Contacts</property>
+                        <property name="use_underline">True</property>
+                        <accelerator key="H" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="separator6">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="chat_quit">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">gtk-quit</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                        <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkMenuItem" id="edit">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Edit</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="edit_menu">
+                    <child>
+                      <widget class="GtkMenuItem" id="edit_context">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Context</property>
+                        <property name="use_underline">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="edit_context_separator">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkMenuItem" id="edit_accounts">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Accounts</property>
+                        <property name="use_underline">True</property>
+                        <accelerator key="F4" modifiers="" signal="activate"/>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="edit_personal_information">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Personal Information</property>
+                        <property name="use_underline">True</property>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image894">
+                            <property name="visible">True</property>
+                            <property name="icon_size">1</property>
+                            <property name="icon_name">user-info</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="separator2">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="edit_preferences">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Preferences</property>
+                        <property name="use_underline">True</property>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image891">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-preferences</property>
+                            <property name="icon_size">1</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkMenuItem" id="room">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Room</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="room_menu">
+                    <child>
+                      <widget class="GtkMenuItem" id="room_join_new">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Join _New...</property>
+                        <property name="use_underline">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkMenuItem" id="room_join_favorites">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Join _Favorites</property>
+                        <property name="use_underline">True</property>
+                        <accelerator key="F5" modifiers="" signal="activate"/>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="room_sep">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkSeparatorMenuItem" id="room_sep2">
+                        <property name="visible">True</property>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="room_manage_favorites">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Manage Favorites</property>
+                        <property name="use_underline">True</property>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image890">
+                            <property name="visible">True</property>
+                            <property name="icon_size">1</property>
+                            <property name="icon_name">system-users</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkMenuItem" id="help">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">_Help</property>
+                <property name="use_underline">True</property>
+                <child>
+                  <widget class="GtkMenu" id="help_menu">
+                    <child>
+                      <widget class="GtkImageMenuItem" id="help_contents">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">_Contents</property>
+                        <property name="use_underline">True</property>
+                        <accelerator key="F1" modifiers="" signal="activate"/>
+                        <child internal-child="image">
+                          <widget class="GtkImage" id="image892">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-help</property>
+                            <property name="icon_size">1</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkImageMenuItem" id="help_about">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">gtk-about</property>
+                        <property name="use_underline">True</property>
+                        <property name="use_stock">True</property>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkToolbar" id="presence_toolbar">
+            <property name="visible">True</property>
+            <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkVBox" id="errors_vbox">
+            <child>
+              <placeholder/>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="GtkScrolledWindow" id="roster_scrolledwindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="has_focus">True</property>
+            <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+            <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+            <property name="shadow_type">GTK_SHADOW_IN</property>
+            <child>
+              <placeholder/>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">3</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/src/empathy-main-window.h b/src/empathy-main-window.h
new file mode 100644 (file)
index 0000000..669a978
--- /dev/null
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002-2007 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_MAIN_WINDOW_H__
+#define __EMPATHY_MAIN_WINDOW_H__
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *empathy_main_window_show (void);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_MAIN_WINDOW_H__ */
diff --git a/src/empathy-new-chatroom-dialog.c b/src/empathy-new-chatroom-dialog.c
new file mode 100644 (file)
index 0000000..b8be23a
--- /dev/null
@@ -0,0 +1,567 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Martyn Russell <martyn@imendio.com>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <libmissioncontrol/mission-control.h>
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mc-profile.h>
+
+#include <libempathy/empathy-tp-roomlist.h>
+#include <libempathy/empathy-chatroom.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-debug.h>
+
+#include <libempathy-gtk/empathy-account-chooser.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+
+#include "empathy-new-chatroom-dialog.h"
+#include "ephy-spinner.h"
+
+#define DEBUG_DOMAIN "NewChatroomDialog"
+
+typedef struct {
+       EmpathyTpRoomlist *room_list;
+
+       GtkWidget         *window;
+       GtkWidget         *vbox_widgets;
+       GtkWidget         *table_info;
+       GtkWidget         *label_account;
+       GtkWidget         *account_chooser;
+       GtkWidget         *label_server;
+       GtkWidget         *entry_server;
+       GtkWidget         *togglebutton_refresh;
+       GtkWidget         *label_room;
+       GtkWidget         *entry_room;
+       GtkWidget         *vbox_browse;
+       GtkWidget         *image_status;
+       GtkWidget         *label_status;
+       GtkWidget         *hbox_status;
+       GtkWidget         *throbber;
+       GtkWidget         *treeview;
+       GtkTreeModel      *model;
+       GtkWidget         *button_join;
+       GtkWidget         *button_close;
+} EmpathyNewChatroomDialog;
+
+enum {
+       COL_NAME,
+       COL_ROOM,
+       COL_COUNT
+};
+
+static void     new_chatroom_dialog_response_cb                     (GtkWidget               *widget,
+                                                                    gint                     response,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_destroy_cb                      (GtkWidget               *widget,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_model_setup                     (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_model_add_columns               (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_update_widgets                  (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_account_changed_cb              (GtkComboBox              *combobox,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_roomlist_destroy_cb             (EmpathyTpRoomlist        *room_list,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_new_room_cb                     (EmpathyTpRoomlist        *room_list,
+                                                                    EmpathyChatroom          *chatroom,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_listing_cb                      (EmpathyTpRoomlist        *room_list,
+                                                                    gboolean                  listing,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_model_clear                     (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_model_row_activated_cb          (GtkTreeView             *tree_view,
+                                                                    GtkTreePath             *path,
+                                                                    GtkTreeViewColumn       *column,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_model_selection_changed         (GtkTreeSelection        *selection,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_join                            (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_entry_changed_cb                (GtkWidget               *entry,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_browse_start                    (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_browse_stop                     (EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_entry_server_activate_cb        (GtkWidget               *widget,
+                                                                    EmpathyNewChatroomDialog *dialog);
+static void     new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget               *widget,
+                                                                    EmpathyNewChatroomDialog *dialog);
+
+static EmpathyNewChatroomDialog *dialog_p = NULL;
+
+void
+empathy_new_chatroom_dialog_show (GtkWindow *parent)
+{
+       EmpathyNewChatroomDialog *dialog;
+       GladeXML                 *glade;
+       GtkSizeGroup             *size_group;
+
+       if (dialog_p) {
+               gtk_window_present (GTK_WINDOW (dialog_p->window));
+               return;
+       }
+
+       dialog_p = dialog = g_new0 (EmpathyNewChatroomDialog, 1);
+
+       glade = empathy_glade_get_file ("empathy-new-chatroom-dialog.glade",
+                                      "new_chatroom_dialog",
+                                      NULL,
+                                      "new_chatroom_dialog", &dialog->window,
+                                      "table_info", &dialog->table_info,
+                                      "label_account", &dialog->label_account,
+                                      "label_server", &dialog->label_server,
+                                      "label_room", &dialog->label_room,
+                                      "entry_server", &dialog->entry_server,
+                                      "entry_room", &dialog->entry_room,
+                                      "togglebutton_refresh", &dialog->togglebutton_refresh,
+                                      "vbox_browse", &dialog->vbox_browse,
+                                      "image_status", &dialog->image_status,
+                                      "label_status", &dialog->label_status,
+                                      "hbox_status", &dialog->hbox_status,
+                                      "treeview", &dialog->treeview,
+                                      "button_join", &dialog->button_join,
+                                      NULL);
+
+       empathy_glade_connect (glade,
+                             dialog,
+                             "new_chatroom_dialog", "response", new_chatroom_dialog_response_cb,
+                             "new_chatroom_dialog", "destroy", new_chatroom_dialog_destroy_cb,
+                             "entry_server", "changed", new_chatroom_dialog_entry_changed_cb,
+                             "entry_server", "activate", new_chatroom_dialog_entry_server_activate_cb,
+                             "entry_room", "changed", new_chatroom_dialog_entry_changed_cb,
+                             "togglebutton_refresh", "toggled", new_chatroom_dialog_togglebutton_refresh_toggled_cb,
+                             NULL);
+
+       g_object_unref (glade);
+
+       g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog_p);
+
+       /* Label alignment */
+       size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+       gtk_size_group_add_widget (size_group, dialog->label_account);
+       gtk_size_group_add_widget (size_group, dialog->label_server);
+       gtk_size_group_add_widget (size_group, dialog->label_room);
+
+       g_object_unref (size_group);
+
+       /* Set up chatrooms treeview */
+       new_chatroom_dialog_model_setup (dialog);
+
+       /* Add throbber */
+       dialog->throbber = ephy_spinner_new ();
+       ephy_spinner_set_size (EPHY_SPINNER (dialog->throbber), GTK_ICON_SIZE_LARGE_TOOLBAR);
+       gtk_widget_show (dialog->throbber);
+
+       gtk_box_pack_start (GTK_BOX (dialog->hbox_status), dialog->throbber, 
+                           FALSE, FALSE, 0);
+
+       /* Account chooser for custom */
+       dialog->account_chooser = empathy_account_chooser_new ();
+       empathy_account_chooser_set_filter (EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser),
+                                           empathy_account_chooser_filter_is_connected,
+                                           NULL);
+       gtk_table_attach_defaults (GTK_TABLE (dialog->table_info),
+                                  dialog->account_chooser,
+                                  1, 3, 0, 1);
+       gtk_widget_show (dialog->account_chooser);
+
+       g_signal_connect (GTK_COMBO_BOX (dialog->account_chooser), "changed",
+                         G_CALLBACK (new_chatroom_dialog_account_changed_cb),
+                         dialog);
+       new_chatroom_dialog_account_changed_cb (GTK_COMBO_BOX (dialog->account_chooser),
+                                               dialog);
+
+       if (parent) {
+               gtk_window_set_transient_for (GTK_WINDOW (dialog->window),
+                                             GTK_WINDOW (parent));
+       }
+
+       gtk_widget_show (dialog->window);
+}
+
+static void
+new_chatroom_dialog_response_cb (GtkWidget               *widget,
+                                gint                     response,
+                                EmpathyNewChatroomDialog *dialog)
+{
+       if (response == GTK_RESPONSE_OK) {
+               new_chatroom_dialog_join (dialog);
+       }
+
+       gtk_widget_destroy (widget);
+}
+
+static void
+new_chatroom_dialog_destroy_cb (GtkWidget               *widget,
+                               EmpathyNewChatroomDialog *dialog)
+{
+       if (dialog->room_list) {
+               g_object_unref (dialog->room_list);
+       }
+       g_object_unref (dialog->model);  
+
+       g_free (dialog);
+}
+
+static void
+new_chatroom_dialog_model_setup (EmpathyNewChatroomDialog *dialog)
+{
+       GtkTreeView      *view;
+       GtkListStore     *store;
+       GtkTreeSelection *selection;
+
+       /* View */
+       view = GTK_TREE_VIEW (dialog->treeview);
+
+       g_signal_connect (view, "row-activated",
+                         G_CALLBACK (new_chatroom_dialog_model_row_activated_cb),
+                         dialog);
+
+       /* Store/Model */
+       store = gtk_list_store_new (COL_COUNT,
+                                   G_TYPE_STRING,       /* Image */
+                                   G_TYPE_STRING,       /* Text */
+                                   G_TYPE_STRING);      /* Room */
+
+       dialog->model = GTK_TREE_MODEL (store);
+       gtk_tree_view_set_model (view, dialog->model);
+
+       /* Selection */
+       selection = gtk_tree_view_get_selection (view);
+       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+                                             COL_NAME, GTK_SORT_ASCENDING);
+
+       g_signal_connect (selection, "changed",
+                         G_CALLBACK (new_chatroom_dialog_model_selection_changed),
+                         dialog);
+
+       /* Columns */
+       new_chatroom_dialog_model_add_columns (dialog);
+}
+
+static void
+new_chatroom_dialog_model_add_columns (EmpathyNewChatroomDialog *dialog)
+{
+       GtkTreeView       *view;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer   *cell;
+
+       view = GTK_TREE_VIEW (dialog->treeview);
+       gtk_tree_view_set_headers_visible (view, FALSE);
+
+       cell = gtk_cell_renderer_text_new ();
+       g_object_set (cell,
+                     "xpad", (guint) 4,
+                     "ypad", (guint) 1,
+                     "ellipsize", PANGO_ELLIPSIZE_END,
+                     NULL);
+
+       column = gtk_tree_view_column_new_with_attributes (_("Chat Rooms"),
+                                                          cell,
+                                                          "text", COL_NAME,
+                                                          NULL);
+
+       gtk_tree_view_column_set_expand (column, TRUE);
+       gtk_tree_view_append_column (view, column);
+}
+
+static void
+new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog)
+{
+       EmpathyAccountChooser *account_chooser;
+       McAccount             *account;
+       McProfile             *profile;
+       const gchar           *protocol;
+       const gchar           *room;
+       
+       account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
+       account = empathy_account_chooser_get_account (account_chooser);
+       profile = mc_account_get_profile (account);
+       protocol = mc_profile_get_protocol_name (profile);
+
+       gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), "");
+
+       /* hardcode here known protocols */
+       if (strcmp (protocol, "jabber") == 0) {
+               gtk_widget_set_sensitive (dialog->entry_server, TRUE);
+               gtk_widget_show (dialog->vbox_browse);
+
+       }
+       else if (strcmp (protocol, "local-xmpp") == 0) {
+               gtk_widget_set_sensitive (dialog->entry_server, FALSE);
+               gtk_widget_show (dialog->vbox_browse);          
+       }
+       else if (strcmp (protocol, "irc") == 0) {
+               gtk_widget_set_sensitive (dialog->entry_server, FALSE);
+               gtk_widget_show (dialog->vbox_browse);          
+       } else {
+               gtk_widget_set_sensitive (dialog->entry_server, TRUE);
+               gtk_widget_show (dialog->vbox_browse);
+       }
+
+       room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
+       gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room));
+
+       /* Final set up of the dialog */
+       gtk_widget_grab_focus (dialog->entry_room);
+
+       g_object_unref (account);
+       g_object_unref (profile);
+}
+
+static void
+new_chatroom_dialog_account_changed_cb (GtkComboBox             *combobox,
+                                       EmpathyNewChatroomDialog *dialog)
+{
+       EmpathyAccountChooser *account_chooser;
+       McAccount             *account;
+       gboolean               listing = FALSE;
+
+       if (dialog->room_list) {
+               g_object_unref (dialog->room_list);
+       }
+
+       ephy_spinner_stop (EPHY_SPINNER (dialog->throbber));
+       new_chatroom_dialog_model_clear (dialog);
+
+       account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
+       account = empathy_account_chooser_get_account (account_chooser);
+       dialog->room_list = empathy_tp_roomlist_new (account);
+
+       if (dialog->room_list)  {
+               g_signal_connect (dialog->room_list, "destroy",
+                                 G_CALLBACK (new_chatroom_dialog_roomlist_destroy_cb),
+                                 dialog);
+               g_signal_connect (dialog->room_list, "new-room",
+                                 G_CALLBACK (new_chatroom_dialog_new_room_cb),
+                                 dialog);
+               g_signal_connect (dialog->room_list, "listing",
+                                 G_CALLBACK (new_chatroom_dialog_listing_cb),
+                                 dialog);
+
+               listing = empathy_tp_roomlist_is_listing (dialog->room_list);
+               if (listing) {
+                       ephy_spinner_start (EPHY_SPINNER (dialog->throbber));
+               }
+       }
+
+       new_chatroom_dialog_update_widgets (dialog);
+}
+
+static void
+new_chatroom_dialog_roomlist_destroy_cb (EmpathyTpRoomlist        *room_list,
+                                        EmpathyNewChatroomDialog *dialog)
+{
+       g_object_unref (dialog->room_list);
+       dialog->room_list = NULL;
+}
+
+static void
+new_chatroom_dialog_new_room_cb (EmpathyTpRoomlist        *room_list,
+                                EmpathyChatroom          *chatroom,
+                                EmpathyNewChatroomDialog *dialog)
+{
+       GtkTreeView      *view;
+       GtkTreeSelection *selection;
+       GtkListStore     *store;
+       GtkTreeIter       iter;
+
+       empathy_debug (DEBUG_DOMAIN, "New chatroom listed: %s (%s)",
+                      empathy_chatroom_get_name (chatroom),
+                      empathy_chatroom_get_room (chatroom));
+
+       /* Add to model */
+       view = GTK_TREE_VIEW (dialog->treeview);
+       selection = gtk_tree_view_get_selection (view);
+       store = GTK_LIST_STORE (dialog->model);
+
+       gtk_list_store_append (store, &iter);
+       gtk_list_store_set (store, &iter,
+                           COL_NAME, empathy_chatroom_get_name (chatroom),
+                           COL_ROOM, empathy_chatroom_get_room (chatroom),
+                           -1);
+}
+
+static void
+new_chatroom_dialog_listing_cb (EmpathyTpRoomlist        *room_list,
+                               gboolean                  listing,
+                               EmpathyNewChatroomDialog *dialog)
+{
+       /* Update the throbber */
+       if (listing) {
+               ephy_spinner_start (EPHY_SPINNER (dialog->throbber));           
+       } else {
+               ephy_spinner_stop (EPHY_SPINNER (dialog->throbber));
+       }
+
+       /* Update the refresh toggle button */
+       g_signal_handlers_block_by_func (dialog->togglebutton_refresh,
+                                        new_chatroom_dialog_togglebutton_refresh_toggled_cb,
+                                        dialog);
+       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->togglebutton_refresh),
+                                     listing);
+       g_signal_handlers_unblock_by_func (dialog->togglebutton_refresh,
+                                          new_chatroom_dialog_togglebutton_refresh_toggled_cb,
+                                          dialog);
+}
+
+static void
+new_chatroom_dialog_model_clear (EmpathyNewChatroomDialog *dialog)
+{
+       GtkListStore *store;
+
+       store = GTK_LIST_STORE (dialog->model);
+       gtk_list_store_clear (store);
+}
+
+static void
+new_chatroom_dialog_model_row_activated_cb (GtkTreeView             *tree_view,
+                                           GtkTreePath             *path,
+                                           GtkTreeViewColumn       *column,
+                                           EmpathyNewChatroomDialog *dialog)
+{
+       gtk_widget_activate (dialog->button_join);
+}
+
+static void
+new_chatroom_dialog_model_selection_changed (GtkTreeSelection         *selection,
+                                            EmpathyNewChatroomDialog *dialog)
+{      
+       GtkTreeModel *model;
+       GtkTreeIter   iter;
+       gchar        *room = NULL;
+       gchar        *server = NULL;
+
+       if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+               return;
+       }
+
+       gtk_tree_model_get (model, &iter, COL_ROOM, &room, -1);
+       server = strstr (room, "@");
+       if (server) {
+               *server = '\0';
+               server++;
+       }
+
+       gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), server ? server : "");
+       gtk_entry_set_text (GTK_ENTRY (dialog->entry_room), room ? room : "");
+
+       g_free (room);
+}
+
+static void
+new_chatroom_dialog_join (EmpathyNewChatroomDialog *dialog)
+{
+       McAccount            *account;
+       EmpathyAccountChooser *account_chooser;
+       MissionControl       *mc;
+       const gchar          *room;
+       const gchar          *server = NULL;
+       gchar                *room_name = NULL;
+
+       room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
+       server = gtk_entry_get_text (GTK_ENTRY (dialog->entry_server));
+
+       account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser);
+       account = empathy_account_chooser_get_account (account_chooser);
+
+       if (!G_STR_EMPTY (server)) {
+               room_name = g_strconcat (room, "@", server, NULL);
+       } else {
+               room_name = g_strdup (room);
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Requesting channel for '%s'", room_name);
+
+       mc = empathy_mission_control_new ();
+       mission_control_request_channel_with_string_handle (mc,
+                                                           account,
+                                                           TP_IFACE_CHANNEL_TYPE_TEXT,
+                                                           room_name,
+                                                           TP_HANDLE_TYPE_ROOM,
+                                                           NULL, NULL);        
+       g_free (room_name);
+       g_object_unref (mc);
+}
+
+static void
+new_chatroom_dialog_entry_changed_cb (GtkWidget                *entry,
+                                     EmpathyNewChatroomDialog *dialog)
+{
+       if (entry == dialog->entry_room) {
+               const gchar *room;
+
+               room = gtk_entry_get_text (GTK_ENTRY (dialog->entry_room));
+               gtk_widget_set_sensitive (dialog->button_join, !G_STR_EMPTY (room));
+               /* FIXME: Select the room in the list */
+       }
+}
+
+static void
+new_chatroom_dialog_browse_start (EmpathyNewChatroomDialog *dialog)
+{
+       new_chatroom_dialog_model_clear (dialog);
+       if (dialog->room_list) {
+               empathy_tp_roomlist_start (dialog->room_list);
+       }
+}
+
+static void
+new_chatroom_dialog_browse_stop (EmpathyNewChatroomDialog *dialog)
+{
+       if (dialog->room_list) {
+               empathy_tp_roomlist_stop (dialog->room_list);
+       }
+}
+
+static void
+new_chatroom_dialog_entry_server_activate_cb (GtkWidget                *widget,
+                                             EmpathyNewChatroomDialog  *dialog)
+{
+       new_chatroom_dialog_togglebutton_refresh_toggled_cb (dialog->togglebutton_refresh, 
+                                                            dialog);
+}
+
+static void
+new_chatroom_dialog_togglebutton_refresh_toggled_cb (GtkWidget               *widget,
+                                                    EmpathyNewChatroomDialog *dialog)
+{
+       gboolean toggled;
+
+       toggled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+       
+       if (toggled) {
+               new_chatroom_dialog_browse_start (dialog);
+       } else {
+               new_chatroom_dialog_browse_stop (dialog);
+       }
+}
+
diff --git a/src/empathy-new-chatroom-dialog.glade b/src/empathy-new-chatroom-dialog.glade
new file mode 100644 (file)
index 0000000..1ba74ec
--- /dev/null
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+  <widget class="GtkDialog" id="new_chatroom_dialog">
+    <property name="visible">True</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Join New</property>
+    <property name="resizable">False</property>
+    <property name="default_width">350</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox4">
+        <property name="visible">True</property>
+        <property name="spacing">6</property>
+        <child>
+          <widget class="GtkVBox" id="vbox_widgets">
+            <property name="visible">True</property>
+            <property name="border_width">5</property>
+            <property name="spacing">18</property>
+            <child>
+              <widget class="GtkTable" id="table_info">
+                <property name="visible">True</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">3</property>
+                <property name="column_spacing">6</property>
+                <property name="row_spacing">6</property>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <widget class="GtkEntry" id="entry_room">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tooltip" translatable="yes">Enter the room name to join here or click on one or more rooms in the list.</property>
+                    <property name="invisible_char">*</property>
+                    <property name="activates_default">True</property>
+                    <property name="width_chars">32</property>
+                  </widget>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkToggleButton" id="togglebutton_refresh">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="label" translatable="yes">Re_fresh</property>
+                    <property name="use_underline">True</property>
+                    <property name="response_id">0</property>
+                  </widget>
+                  <packing>
+                    <property name="left_attach">2</property>
+                    <property name="right_attach">3</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkEntry" id="entry_server">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="tooltip" translatable="yes">Enter the server which hosts the room, or leave it empty if the room is on the current account's server</property>
+                    <property name="invisible_char">*</property>
+                    <property name="width_chars">25</property>
+                  </widget>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label_room">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">_Room:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry_room</property>
+                  </widget>
+                  <packing>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label_server">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">_Server:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">entry_server</property>
+                  </widget>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label_account">
+                    <property name="visible">True</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Account:</property>
+                  </widget>
+                  <packing>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options"></property>
+                  </packing>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="vbox_browse">
+                <property name="visible">True</property>
+                <property name="spacing">6</property>
+                <child>
+                  <widget class="GtkHBox" id="hbox_status">
+                    <property name="visible">True</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <widget class="GtkHBox" id="hbox35">
+                        <property name="visible">True</property>
+                        <property name="spacing">3</property>
+                        <child>
+                          <widget class="GtkImage" id="image_status">
+                            <property name="visible">True</property>
+                            <property name="icon_size">2</property>
+                            <property name="icon_name">gtk-find</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label_status">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Browse:</property>
+                            <property name="wrap">True</property>
+                          </widget>
+                          <packing>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkScrolledWindow" id="scrolledwindow2">
+                    <property name="height_request">150</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                    <property name="shadow_type">GTK_SHADOW_IN</property>
+                    <child>
+                      <widget class="GtkTreeView" id="treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="tooltip" translatable="yes">This list represents all chat rooms hosted on the server you have entered.</property>
+                        <property name="headers_visible">False</property>
+                      </widget>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area4">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button_cancel">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-7</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button_join">
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="response_id">-5</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment4">
+                    <property name="visible">True</property>
+                    <property name="xscale">0</property>
+                    <property name="yscale">0</property>
+                    <child>
+                      <widget class="GtkHBox" id="hbox29">
+                        <property name="visible">True</property>
+                        <property name="spacing">2</property>
+                        <child>
+                          <widget class="GtkImage" id="image4">
+                            <property name="visible">True</property>
+                            <property name="stock">gtk-execute</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label79">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Join</property>
+                            <property name="use_underline">True</property>
+                          </widget>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/src/empathy-new-chatroom-dialog.h b/src/empathy-new-chatroom-dialog.h
new file mode 100644 (file)
index 0000000..2a12608
--- /dev/null
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Authors: Martyn Russell <martyn@imendio.com>
+ *          Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_NEW_CHATROOMS_WINDOW_H__
+#define __EMPATHY_NEW_CHATROOMS_WINDOW_H__
+
+G_BEGIN_DECLS
+
+void empathy_new_chatroom_dialog_show (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_NEW_CHATROOMS_WINDOW_H__ */
diff --git a/src/empathy-preferences.c b/src/empathy-preferences.c
new file mode 100644 (file)
index 0000000..1304c58
--- /dev/null
@@ -0,0 +1,1018 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003-2007 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ *          Richard Hult <richard@imendio.com>
+ *          Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <glib/gi18n.h>
+
+#include <libempathy-gtk/empathy-conf.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+#include <libempathy-gtk/empathy-theme-manager.h>
+#include <libempathy-gtk/empathy-spell.h>
+#include <libempathy-gtk/empathy-contact-list-store.h>
+#include <libempathy-gtk/empathy-gtk-enum-types.h>
+
+#include "empathy-preferences.h"
+
+typedef struct {
+       GtkWidget *dialog;
+
+       GtkWidget *notebook;
+
+       GtkWidget *checkbutton_show_avatars;
+       GtkWidget *checkbutton_compact_contact_list;
+       GtkWidget *checkbutton_show_smileys;
+       GtkWidget *combobox_chat_theme;
+       GtkWidget *checkbutton_theme_chat_room;
+       GtkWidget *checkbutton_separate_chat_windows;
+       GtkWidget *checkbutton_autoconnect;
+       GtkWidget *radiobutton_contact_list_sort_by_name;
+       GtkWidget *radiobutton_contact_list_sort_by_state;
+
+       GtkWidget *checkbutton_sounds_for_messages;
+       GtkWidget *checkbutton_sounds_when_busy;
+       GtkWidget *checkbutton_sounds_when_away;
+       GtkWidget *checkbutton_popups_when_available;
+
+       GtkWidget *treeview_spell_checker;
+
+       GList     *notify_ids;
+} EmpathyPreferences;
+
+static void     preferences_setup_widgets                (EmpathyPreferences      *preferences);
+static void     preferences_languages_setup              (EmpathyPreferences      *preferences);
+static void     preferences_languages_add                (EmpathyPreferences      *preferences);
+static void     preferences_languages_save               (EmpathyPreferences      *preferences);
+static gboolean preferences_languages_save_foreach       (GtkTreeModel           *model,
+                                                         GtkTreePath            *path,
+                                                         GtkTreeIter            *iter,
+                                                         gchar                 **languages);
+static void     preferences_languages_load               (EmpathyPreferences      *preferences);
+static gboolean preferences_languages_load_foreach       (GtkTreeModel           *model,
+                                                         GtkTreePath            *path,
+                                                         GtkTreeIter            *iter,
+                                                         gchar                 **languages);
+static void     preferences_languages_cell_toggled_cb    (GtkCellRendererToggle  *cell,
+                                                         gchar                  *path_string,
+                                                         EmpathyPreferences      *preferences);
+static void     preferences_themes_setup                 (EmpathyPreferences      *preferences);
+static void     preferences_widget_sync_bool             (const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_widget_sync_int              (const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_widget_sync_string           (const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_widget_sync_string_combo     (const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_notify_int_cb                (EmpathyConf             *conf,
+                                                         const gchar            *key,
+                                                         gpointer                user_data);
+static void     preferences_notify_string_cb             (EmpathyConf             *conf,
+                                                         const gchar            *key,
+                                                         gpointer                user_data);
+static void     preferences_notify_string_combo_cb       (EmpathyConf             *conf,
+                                                         const gchar            *key,
+                                                         gpointer                user_data);
+static void     preferences_notify_bool_cb               (EmpathyConf             *conf,
+                                                         const gchar            *key,
+                                                         gpointer                user_data);
+static void     preferences_notify_sensitivity_cb        (EmpathyConf             *conf,
+                                                         const gchar            *key,
+                                                         gpointer                user_data);
+static void     preferences_hookup_spin_button           (EmpathyPreferences      *preferences,
+                                                         const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_hookup_entry                 (EmpathyPreferences      *preferences,
+                                                         const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_hookup_toggle_button         (EmpathyPreferences      *preferences,
+                                                         const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_hookup_radio_button          (EmpathyPreferences      *preferences,
+                                                         const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_hookup_string_combo          (EmpathyPreferences      *preferences,
+                                                         const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_hookup_sensitivity           (EmpathyPreferences      *preferences,
+                                                         const gchar            *key,
+                                                         GtkWidget              *widget);
+static void     preferences_spin_button_value_changed_cb (GtkWidget              *button,
+                                                         gpointer                user_data);
+static void     preferences_entry_value_changed_cb       (GtkWidget              *entry,
+                                                         gpointer                user_data);
+static void     preferences_toggle_button_toggled_cb     (GtkWidget              *button,
+                                                         gpointer                user_data);
+static void     preferences_radio_button_toggled_cb      (GtkWidget              *button,
+                                                         gpointer                user_data);
+static void     preferences_string_combo_changed_cb      (GtkWidget *button,
+                                                         gpointer                user_data);
+static void     preferences_destroy_cb                   (GtkWidget              *widget,
+                                                         EmpathyPreferences      *preferences);
+static void     preferences_response_cb                  (GtkWidget              *widget,
+                                                         gint                    response,
+                                                         EmpathyPreferences      *preferences);
+
+enum {
+       COL_LANG_ENABLED,
+       COL_LANG_CODE,
+       COL_LANG_NAME,
+       COL_LANG_COUNT
+};
+
+enum {
+       COL_COMBO_VISIBLE_NAME,
+       COL_COMBO_NAME,
+       COL_COMBO_COUNT
+};
+
+static void
+preferences_add_id (EmpathyPreferences *preferences, guint id)
+{
+       preferences->notify_ids = g_list_prepend (preferences->notify_ids,
+                                                 GUINT_TO_POINTER (id));
+}
+
+static void
+preferences_compact_contact_list_changed_cb (EmpathyConf *conf,
+                                            const gchar *key,
+                                            gpointer     user_data)
+{
+       EmpathyPreferences *preferences = user_data;
+       gboolean            value;
+
+       if (empathy_conf_get_bool (empathy_conf_get (), key, &value)) {
+               gtk_widget_set_sensitive (preferences->checkbutton_show_avatars,
+                                         !value);
+       }
+}
+
+static void
+preferences_setup_widgets (EmpathyPreferences *preferences)
+{
+       guint id;
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_SOUNDS_FOR_MESSAGES,
+                                         preferences->checkbutton_sounds_for_messages);
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_SOUNDS_WHEN_AWAY,
+                                         preferences->checkbutton_sounds_when_away);
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_SOUNDS_WHEN_BUSY,
+                                         preferences->checkbutton_sounds_when_busy);
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_POPUPS_WHEN_AVAILABLE,
+                                         preferences->checkbutton_popups_when_available);
+
+       preferences_hookup_sensitivity (preferences,
+                                       EMPATHY_PREFS_SOUNDS_FOR_MESSAGES,
+                                       preferences->checkbutton_sounds_when_away);
+       preferences_hookup_sensitivity (preferences,
+                                       EMPATHY_PREFS_SOUNDS_FOR_MESSAGES,
+                                       preferences->checkbutton_sounds_when_busy);
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_UI_SEPARATE_CHAT_WINDOWS,
+                                         preferences->checkbutton_separate_chat_windows);
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_UI_SHOW_AVATARS,
+                                         preferences->checkbutton_show_avatars);
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
+                                         preferences->checkbutton_compact_contact_list);
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_CHAT_SHOW_SMILEYS,
+                                         preferences->checkbutton_show_smileys);
+
+       preferences_hookup_string_combo (preferences,
+                                        EMPATHY_PREFS_CHAT_THEME,
+                                        preferences->combobox_chat_theme);
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_CHAT_THEME_CHAT_ROOM,
+                                         preferences->checkbutton_theme_chat_room);
+
+       preferences_hookup_radio_button (preferences,
+                                        EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
+                                        preferences->radiobutton_contact_list_sort_by_name);
+
+       preferences_hookup_toggle_button (preferences,
+                                         EMPATHY_PREFS_AUTOCONNECT,
+                                         preferences->checkbutton_autoconnect);
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                     EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
+                                     preferences_compact_contact_list_changed_cb,
+                                     preferences);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+       preferences_compact_contact_list_changed_cb (empathy_conf_get (),
+                                                    EMPATHY_PREFS_UI_COMPACT_CONTACT_LIST,
+                                                    preferences);
+}
+
+static void
+preferences_languages_setup (EmpathyPreferences *preferences)
+{
+       GtkTreeView       *view;
+       GtkListStore      *store;
+       GtkTreeSelection  *selection;
+       GtkTreeModel      *model;
+       GtkTreeViewColumn *column;
+       GtkCellRenderer   *renderer;
+       guint              col_offset;
+
+       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
+
+       store = gtk_list_store_new (COL_LANG_COUNT,
+                                   G_TYPE_BOOLEAN,  /* enabled */
+                                   G_TYPE_STRING,   /* code */
+                                   G_TYPE_STRING);  /* name */
+
+       gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
+
+       selection = gtk_tree_view_get_selection (view);
+       gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+       model = GTK_TREE_MODEL (store);
+
+       renderer = gtk_cell_renderer_toggle_new ();
+       g_signal_connect (renderer, "toggled",
+                         G_CALLBACK (preferences_languages_cell_toggled_cb),
+                         preferences);
+
+       column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
+                                                          "active", COL_LANG_ENABLED,
+                                                          NULL);
+
+       gtk_tree_view_append_column (view, column);
+
+       renderer = gtk_cell_renderer_text_new ();
+       col_offset = gtk_tree_view_insert_column_with_attributes (view,
+                                                                 -1, _("Language"),
+                                                                 renderer,
+                                                                 "text", COL_LANG_NAME,
+                                                                 NULL);
+
+       g_object_set_data (G_OBJECT (renderer),
+                          "column", GINT_TO_POINTER (COL_LANG_NAME));
+
+       column = gtk_tree_view_get_column (view, col_offset - 1);
+       gtk_tree_view_column_set_sort_column_id (column, COL_LANG_NAME);
+       gtk_tree_view_column_set_resizable (column, FALSE);
+       gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
+
+       g_object_unref (store);
+}
+
+static void
+preferences_languages_add (EmpathyPreferences *preferences)
+{
+       GtkTreeView  *view;
+       GtkListStore *store;
+       GList        *codes, *l;
+
+       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
+       store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
+
+       codes = empathy_spell_get_language_codes ();
+
+       empathy_conf_set_bool (empathy_conf_get(),
+                              EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
+                              codes != NULL);
+       if (!codes) {
+               gtk_widget_set_sensitive (preferences->treeview_spell_checker, FALSE);
+       }               
+
+       for (l = codes; l; l = l->next) {
+               GtkTreeIter  iter;
+               const gchar *code;
+               const gchar *name;
+
+               code = l->data;
+               name = empathy_spell_get_language_name (code);
+               if (!name) {
+                       continue;
+               }
+
+               gtk_list_store_append (store, &iter);
+               gtk_list_store_set (store, &iter,
+                                   COL_LANG_CODE, code,
+                                   COL_LANG_NAME, name,
+                                   -1);
+       }
+
+       empathy_spell_free_language_codes (codes);
+}
+
+static void
+preferences_languages_save (EmpathyPreferences *preferences)
+{
+       GtkTreeView       *view;
+       GtkTreeModel      *model;
+
+       gchar             *languages = NULL;
+
+       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
+       model = gtk_tree_view_get_model (view);
+
+       gtk_tree_model_foreach (model,
+                               (GtkTreeModelForeachFunc) preferences_languages_save_foreach,
+                               &languages);
+
+       /* if user selects no languages, we don't want spell check */
+       empathy_conf_set_bool (empathy_conf_get (),
+                              EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
+                              languages != NULL);
+
+       empathy_conf_set_string (empathy_conf_get (),
+                                EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
+                                languages ? languages : "");
+
+       g_free (languages);
+}
+
+static gboolean
+preferences_languages_save_foreach (GtkTreeModel  *model,
+                                   GtkTreePath   *path,
+                                   GtkTreeIter   *iter,
+                                   gchar        **languages)
+{
+       gboolean  enabled;
+       gchar    *code;
+
+       if (!languages) {
+               return TRUE;
+       }
+
+       gtk_tree_model_get (model, iter, COL_LANG_ENABLED, &enabled, -1);
+       if (!enabled) {
+               return FALSE;
+       }
+
+       gtk_tree_model_get (model, iter, COL_LANG_CODE, &code, -1);
+       if (!code) {
+               return FALSE;
+       }
+
+       if (!(*languages)) {
+               *languages = g_strdup (code);
+       } else {
+               gchar *str = *languages;
+               *languages = g_strdup_printf ("%s,%s", str, code);
+               g_free (str);
+       }
+
+       g_free (code);
+
+       return FALSE;
+}
+
+static void
+preferences_languages_load (EmpathyPreferences *preferences)
+{
+       GtkTreeView   *view;
+       GtkTreeModel  *model;
+       gchar         *value;
+       gchar        **vlanguages;
+
+       if (!empathy_conf_get_string (empathy_conf_get (),
+                                     EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
+                                     &value) || !value) {
+               return;
+       }
+
+       vlanguages = g_strsplit (value, ",", -1);
+       g_free (value);
+
+       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
+       model = gtk_tree_view_get_model (view);
+
+       gtk_tree_model_foreach (model,
+                               (GtkTreeModelForeachFunc) preferences_languages_load_foreach,
+                               vlanguages);
+
+       g_strfreev (vlanguages);
+}
+
+static gboolean
+preferences_languages_load_foreach (GtkTreeModel  *model,
+                                   GtkTreePath   *path,
+                                   GtkTreeIter   *iter,
+                                   gchar        **languages)
+{
+       gchar    *code;
+       gchar    *lang;
+       gint      i;
+       gboolean  found = FALSE;
+
+       if (!languages) {
+               return TRUE;
+       }
+
+       gtk_tree_model_get (model, iter, COL_LANG_CODE, &code, -1);
+       if (!code) {
+               return FALSE;
+       }
+
+       for (i = 0, lang = languages[i]; lang; lang = languages[++i]) {
+               if (strcmp (lang, code) == 0) {
+                       found = TRUE;
+               }
+       }
+
+       gtk_list_store_set (GTK_LIST_STORE (model), iter, COL_LANG_ENABLED, found, -1);
+       return FALSE;
+}
+
+static void
+preferences_languages_cell_toggled_cb (GtkCellRendererToggle *cell,
+                                      gchar                 *path_string,
+                                      EmpathyPreferences     *preferences)
+{
+       GtkTreeView  *view;
+       GtkTreeModel *model;
+       GtkListStore *store;
+       GtkTreePath  *path;
+       GtkTreeIter   iter;
+       gboolean      enabled;
+
+       view = GTK_TREE_VIEW (preferences->treeview_spell_checker);
+       model = gtk_tree_view_get_model (view);
+       store = GTK_LIST_STORE (model);
+
+       path = gtk_tree_path_new_from_string (path_string);
+
+       gtk_tree_model_get_iter (model, &iter, path);
+       gtk_tree_model_get (model, &iter, COL_LANG_ENABLED, &enabled, -1);
+
+       enabled ^= 1;
+
+       gtk_list_store_set (store, &iter, COL_LANG_ENABLED, enabled, -1);
+       gtk_tree_path_free (path);
+
+       preferences_languages_save (preferences);
+}
+
+static void
+preferences_themes_setup (EmpathyPreferences *preferences)
+{
+       GtkComboBox   *combo;
+       GtkListStore  *model;
+       GtkTreeIter    iter;
+       const gchar  **themes;
+       gint           i;
+
+       combo = GTK_COMBO_BOX (preferences->combobox_chat_theme);
+
+       model = gtk_list_store_new (COL_COMBO_COUNT,
+                                   G_TYPE_STRING,
+                                   G_TYPE_STRING);
+
+       themes = empathy_theme_manager_get_themes ();
+       for (i = 0; themes[i]; i += 2) {
+               gtk_list_store_append (model, &iter);
+               gtk_list_store_set (model, &iter,
+                                   COL_COMBO_VISIBLE_NAME, _(themes[i + 1]),
+                                   COL_COMBO_NAME, themes[i],
+                                   -1);
+       }
+
+       gtk_combo_box_set_model (combo, GTK_TREE_MODEL (model));
+       g_object_unref (model);
+}
+
+static void
+preferences_widget_sync_bool (const gchar *key, GtkWidget *widget)
+{
+       gboolean value;
+
+       if (empathy_conf_get_bool (empathy_conf_get (), key, &value)) {
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
+       }
+}
+
+static void
+preferences_widget_sync_int (const gchar *key, GtkWidget *widget)
+{
+       gint value;
+
+       if (empathy_conf_get_int (empathy_conf_get (), key, &value)) {
+               if (GTK_IS_SPIN_BUTTON (widget)) {
+                       gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
+               }
+       }
+}
+
+static void
+preferences_widget_sync_string (const gchar *key, GtkWidget *widget)
+{
+       gchar *value;
+
+       if (empathy_conf_get_string (empathy_conf_get (), key, &value) && value) {
+               if (GTK_IS_ENTRY (widget)) {
+                       gtk_entry_set_text (GTK_ENTRY (widget), value);
+               } else if (GTK_IS_RADIO_BUTTON (widget)) {
+                       if (strcmp (key, EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM) == 0) {
+                               GType        type;
+                               GEnumClass  *enum_class;
+                               GEnumValue  *enum_value;
+                               GSList      *list;
+                               GtkWidget   *toggle_widget;
+                               
+                               /* Get index from new string */
+                               type = empathy_contact_list_store_sort_get_type ();
+                               enum_class = G_ENUM_CLASS (g_type_class_peek (type));
+                               enum_value = g_enum_get_value_by_nick (enum_class, value);
+                               
+                               if (enum_value) { 
+                                       list = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+                                       toggle_widget = g_slist_nth_data (list, enum_value->value);
+                                       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_widget), TRUE);
+                               }
+                       } else {
+                               g_warning ("Unhandled key:'%s' just had string change", key);
+                       }
+               }
+
+               g_free (value);
+       }
+}
+
+static void
+preferences_widget_sync_string_combo (const gchar *key, GtkWidget *widget)
+{
+       gchar        *value;
+       GtkTreeModel *model;
+       GtkTreeIter   iter;
+       gboolean      found;
+
+       if (!empathy_conf_get_string (empathy_conf_get (), key, &value)) {
+               return;
+       }
+
+       model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
+
+       found = FALSE;
+       if (value && gtk_tree_model_get_iter_first (model, &iter)) {
+               gchar *name;
+
+               do {
+                       gtk_tree_model_get (model, &iter,
+                                           COL_COMBO_NAME, &name,
+                                           -1);
+
+                       if (strcmp (name, value) == 0) {
+                               found = TRUE;
+                               gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
+                               break;
+                       } else {
+                               found = FALSE;
+                       }
+
+                       g_free (name);
+               } while (gtk_tree_model_iter_next (model, &iter));
+       }
+
+       /* Fallback to the first one. */
+       if (!found) {
+               if (gtk_tree_model_get_iter_first (model, &iter)) {
+                       gtk_combo_box_set_active_iter (GTK_COMBO_BOX (widget), &iter);
+               }
+       }
+
+       g_free (value);
+}
+
+static void
+preferences_notify_int_cb (EmpathyConf  *conf,
+                          const gchar *key,
+                          gpointer     user_data)
+{
+       preferences_widget_sync_int (key, user_data);   
+}
+
+static void
+preferences_notify_string_cb (EmpathyConf  *conf,
+                             const gchar *key,
+                             gpointer     user_data)
+{
+       preferences_widget_sync_string (key, user_data);
+}
+
+static void
+preferences_notify_string_combo_cb (EmpathyConf  *conf,
+                                   const gchar *key,
+                                   gpointer     user_data)
+{
+       preferences_widget_sync_string_combo (key, user_data);
+}
+
+static void
+preferences_notify_bool_cb (EmpathyConf  *conf,
+                           const gchar *key,
+                           gpointer     user_data)
+{
+       preferences_widget_sync_bool (key, user_data);
+}
+
+static void
+preferences_notify_sensitivity_cb (EmpathyConf  *conf,
+                                  const gchar *key,
+                                  gpointer     user_data)
+{
+       gboolean value;
+
+       if (empathy_conf_get_bool (conf, key, &value)) {
+               gtk_widget_set_sensitive (GTK_WIDGET (user_data), value);
+       }
+}
+
+static void
+preferences_hookup_spin_button (EmpathyPreferences *preferences,
+                               const gchar       *key,
+                               GtkWidget         *widget)
+{
+       guint id;
+
+       /* Silence warning. */
+       if (0) {
+               preferences_hookup_spin_button (preferences, key, widget);
+       }
+
+       preferences_widget_sync_int (key, widget);
+
+       g_object_set_data_full (G_OBJECT (widget), "key",
+                               g_strdup (key), g_free);
+
+       g_signal_connect (widget,
+                         "value_changed",
+                         G_CALLBACK (preferences_spin_button_value_changed_cb),
+                         NULL);
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                     key,
+                                     preferences_notify_int_cb,
+                                     widget);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+}
+
+static void
+preferences_hookup_entry (EmpathyPreferences *preferences,
+                         const gchar       *key,
+                         GtkWidget         *widget)
+{
+       guint id;
+
+       if (0) {  /* Silent warning before we use this function. */
+               preferences_hookup_entry (preferences, key, widget);
+       }
+
+       preferences_widget_sync_string (key, widget);
+
+       g_object_set_data_full (G_OBJECT (widget), "key",
+                               g_strdup (key), g_free);
+
+       g_signal_connect (widget,
+                         "changed",
+                         G_CALLBACK (preferences_entry_value_changed_cb),
+                         NULL);
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                     key,
+                                     preferences_notify_string_cb,
+                                     widget);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+}
+
+static void
+preferences_hookup_toggle_button (EmpathyPreferences *preferences,
+                                 const gchar       *key,
+                                 GtkWidget         *widget)
+{
+       guint id;
+
+       preferences_widget_sync_bool (key, widget);
+
+       g_object_set_data_full (G_OBJECT (widget), "key",
+                               g_strdup (key), g_free);
+
+       g_signal_connect (widget,
+                         "toggled",
+                         G_CALLBACK (preferences_toggle_button_toggled_cb),
+                         NULL);
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                    key,
+                                    preferences_notify_bool_cb,
+                                    widget);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+}
+
+static void
+preferences_hookup_radio_button (EmpathyPreferences *preferences,
+                                const gchar       *key,
+                                GtkWidget         *widget)
+{
+       GSList *group, *l;
+       guint   id;
+
+       preferences_widget_sync_string (key, widget);
+
+       group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget));
+       for (l = group; l; l = l->next) {
+               g_signal_connect (l->data,
+                                 "toggled",
+                                 G_CALLBACK (preferences_radio_button_toggled_cb),
+                                 NULL);
+
+               g_object_set_data_full (G_OBJECT (l->data), "key",
+                                       g_strdup (key), g_free);
+       }
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                    key,
+                                    preferences_notify_string_cb,
+                                    widget);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+}
+
+static void
+preferences_hookup_string_combo (EmpathyPreferences *preferences,
+                                const gchar       *key,
+                                GtkWidget         *widget)
+{
+       guint id;
+
+       preferences_widget_sync_string_combo (key, widget);
+
+       g_object_set_data_full (G_OBJECT (widget), "key",
+                               g_strdup (key), g_free);
+
+       g_signal_connect (widget,
+                         "changed",
+                         G_CALLBACK (preferences_string_combo_changed_cb),
+                         NULL);
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                     key,
+                                     preferences_notify_string_combo_cb,
+                                     widget);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+}
+
+static void
+preferences_hookup_sensitivity (EmpathyPreferences *preferences,
+                               const gchar       *key,
+                               GtkWidget         *widget)
+{
+       gboolean value;
+       guint    id;
+
+       if (empathy_conf_get_bool (empathy_conf_get (), key, &value)) {
+               gtk_widget_set_sensitive (widget, value);
+       }
+
+       id = empathy_conf_notify_add (empathy_conf_get (),
+                                     key,
+                                     preferences_notify_sensitivity_cb,
+                                     widget);
+       if (id) {
+               preferences_add_id (preferences, id);
+       }
+}
+
+static void
+preferences_spin_button_value_changed_cb (GtkWidget *button,
+                                         gpointer   user_data)
+{
+       const gchar *key;
+
+       key = g_object_get_data (G_OBJECT (button), "key");
+
+       empathy_conf_set_int (empathy_conf_get (),
+                             key,
+                             gtk_spin_button_get_value (GTK_SPIN_BUTTON (button)));
+}
+
+static void
+preferences_entry_value_changed_cb (GtkWidget *entry,
+                                   gpointer   user_data)
+{
+       const gchar *key;
+
+       key = g_object_get_data (G_OBJECT (entry), "key");
+
+       empathy_conf_set_string (empathy_conf_get (),
+                                key,
+                                gtk_entry_get_text (GTK_ENTRY (entry)));
+}
+
+static void
+preferences_toggle_button_toggled_cb (GtkWidget *button,
+                                     gpointer   user_data)
+{
+       const gchar *key;
+
+       key = g_object_get_data (G_OBJECT (button), "key");
+
+       empathy_conf_set_bool (empathy_conf_get (),
+                              key,
+                              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
+}
+
+static void
+preferences_radio_button_toggled_cb (GtkWidget *button,
+                                    gpointer   user_data)
+{
+       const gchar *key;
+       const gchar *value = NULL;
+
+       if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) {
+               return;
+       }
+
+       key = g_object_get_data (G_OBJECT (button), "key");
+
+       if (key && strcmp (key, EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM) == 0) {
+               GSList      *group;
+               GType        type;
+               GEnumClass  *enum_class;
+               GEnumValue  *enum_value;
+               
+               group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
+               
+               /* Get string from index */
+               type = empathy_contact_list_store_sort_get_type ();
+               enum_class = G_ENUM_CLASS (g_type_class_peek (type));
+               enum_value = g_enum_get_value (enum_class, g_slist_index (group, button));
+               
+               if (!enum_value) {
+                       g_warning ("No GEnumValue for EmpathyContactListSort with GtkRadioButton index:%d", 
+                                  g_slist_index (group, button));
+                       return;
+               }
+
+               value = enum_value->value_nick;
+       }
+
+       empathy_conf_set_string (empathy_conf_get (), key, value);
+}
+
+static void
+preferences_string_combo_changed_cb (GtkWidget *combo,
+                                    gpointer   user_data)
+{
+       const gchar  *key;
+       GtkTreeModel *model;
+       GtkTreeIter   iter;
+       gchar        *name;
+
+       key = g_object_get_data (G_OBJECT (combo), "key");
+
+       if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) {
+               model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
+
+               gtk_tree_model_get (model, &iter,
+                                   COL_COMBO_NAME, &name,
+                                   -1);
+               empathy_conf_set_string (empathy_conf_get (), key, name);
+               g_free (name);
+       }
+}
+
+static void
+preferences_response_cb (GtkWidget         *widget,
+                        gint               response,
+                        EmpathyPreferences *preferences)
+{
+       gtk_widget_destroy (widget);
+}
+
+static void
+preferences_destroy_cb (GtkWidget         *widget,
+                       EmpathyPreferences *preferences)
+{
+       GList *l;
+
+       for (l = preferences->notify_ids; l; l = l->next) {
+               guint id;
+
+               id = GPOINTER_TO_UINT (l->data);
+               empathy_conf_notify_remove (empathy_conf_get (), id);
+       }
+
+       g_list_free (preferences->notify_ids);
+       g_free (preferences);
+}
+
+GtkWidget *
+empathy_preferences_show (GtkWindow *parent)
+{
+       static EmpathyPreferences *preferences;
+       GladeXML                 *glade;
+
+       if (preferences) {
+               gtk_window_present (GTK_WINDOW (preferences->dialog));
+               return preferences->dialog;
+       }
+
+       preferences = g_new0 (EmpathyPreferences, 1);
+
+       glade = empathy_glade_get_file (
+               "empathy-preferences.glade",
+               "preferences_dialog",
+               NULL,
+               "preferences_dialog", &preferences->dialog,
+               "notebook", &preferences->notebook,
+               "checkbutton_show_avatars", &preferences->checkbutton_show_avatars,
+               "checkbutton_compact_contact_list", &preferences->checkbutton_compact_contact_list,
+               "checkbutton_show_smileys", &preferences->checkbutton_show_smileys,
+               "combobox_chat_theme", &preferences->combobox_chat_theme,
+               "checkbutton_theme_chat_room", &preferences->checkbutton_theme_chat_room,
+               "checkbutton_separate_chat_windows", &preferences->checkbutton_separate_chat_windows,
+               "checkbutton_autoconnect", &preferences->checkbutton_autoconnect,
+               "radiobutton_contact_list_sort_by_name", &preferences->radiobutton_contact_list_sort_by_name,
+               "radiobutton_contact_list_sort_by_state", &preferences->radiobutton_contact_list_sort_by_state,
+               "checkbutton_sounds_for_messages", &preferences->checkbutton_sounds_for_messages,
+               "checkbutton_sounds_when_busy", &preferences->checkbutton_sounds_when_busy,
+               "checkbutton_sounds_when_away", &preferences->checkbutton_sounds_when_away,
+               "checkbutton_popups_when_available", &preferences->checkbutton_popups_when_available,
+               "treeview_spell_checker", &preferences->treeview_spell_checker,
+               NULL);
+
+       empathy_glade_connect (glade,
+                             preferences,
+                             "preferences_dialog", "destroy", preferences_destroy_cb,
+                             "preferences_dialog", "response", preferences_response_cb,
+                             NULL);
+
+       g_object_unref (glade);
+
+       g_object_add_weak_pointer (G_OBJECT (preferences->dialog), (gpointer) &preferences);
+
+       preferences_themes_setup (preferences);
+
+       preferences_setup_widgets (preferences);
+
+       preferences_languages_setup (preferences);
+       preferences_languages_add (preferences);
+       preferences_languages_load (preferences);
+
+       if (empathy_spell_supported ()) {
+               GtkWidget *page;
+
+               page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (preferences->notebook), 2);
+               gtk_widget_show (page);
+       }
+
+       if (parent) {
+               gtk_window_set_transient_for (GTK_WINDOW (preferences->dialog),
+                                             GTK_WINDOW (parent));
+       }
+
+       gtk_widget_show (preferences->dialog);
+
+       return preferences->dialog;
+}
+
diff --git a/src/empathy-preferences.glade b/src/empathy-preferences.glade
new file mode 100644 (file)
index 0000000..bf03da6
--- /dev/null
@@ -0,0 +1,644 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+  <widget class="GtkDialog" id="preferences_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Preferences</property>
+    <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+    <property name="icon_name">gtk-preferences</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox5">
+        <property name="visible">True</property>
+        <property name="spacing">2</property>
+        <child>
+          <widget class="GtkNotebook" id="notebook">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="border_width">5</property>
+            <child>
+              <widget class="GtkVBox" id="vbox197">
+                <property name="visible">True</property>
+                <property name="border_width">12</property>
+                <property name="spacing">18</property>
+                <child>
+                  <widget class="GtkFrame" id="frame3">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment11">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox199">
+                            <property name="visible">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_compact_contact_list">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Show co_mpact contact list</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_show_avatars">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="tooltip" translatable="yes">Avatars are user chosen images shown in the contact list</property>
+                                <property name="label" translatable="yes">Show _avatars</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_show_smileys">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Show _smileys as images</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label611">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Appearance&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkFrame" id="frame4">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment12">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox218">
+                            <property name="visible">True</property>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_separate_chat_windows">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">_Open new chats in separate windows</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_autoconnect">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Automatically _connect on startup </property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="active">True</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label612">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Behaviour&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkFrame" id="frame13">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment31">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox217">
+                            <property name="visible">True</property>
+                            <child>
+                              <widget class="GtkRadioButton" id="radiobutton_contact_list_sort_by_name">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Sort by _name</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkRadioButton" id="radiobutton_contact_list_sort_by_state">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Sort by s_tate</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                                <property name="group">radiobutton_contact_list_sort_by_name</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label644">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Contact List&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label602">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">General</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="outer_vbox">
+                <property name="visible">True</property>
+                <property name="border_width">12</property>
+                <property name="spacing">18</property>
+                <child>
+                  <widget class="GtkFrame" id="frame5">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment13">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox106">
+                            <property name="visible">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_sounds_for_messages">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">_Play sound when messages arrive</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_sounds_when_busy">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Enable sounds when _busy</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkCheckButton" id="checkbutton_sounds_when_away">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="label" translatable="yes">Enable sounds when _away</property>
+                                <property name="use_underline">True</property>
+                                <property name="response_id">0</property>
+                                <property name="draw_indicator">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label613">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Audio&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkFrame" id="frame6">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment14">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkCheckButton" id="checkbutton_popups_when_available">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="label" translatable="yes">Display notifications when contacts come _online</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label614">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Visual&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label607">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Notifications</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="position">1</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="vbox168">
+                <property name="border_width">12</property>
+                <property name="spacing">18</property>
+                <child>
+                  <widget class="GtkFrame" id="frame7">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment15">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox201">
+                            <property name="visible">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <widget class="GtkHBox" id="hbox153">
+                                <property name="visible">True</property>
+                                <child>
+                                  <widget class="GtkHBox" id="hbox154">
+                                    <property name="visible">True</property>
+                                    <property name="spacing">6</property>
+                                    <child>
+                                      <widget class="GtkScrolledWindow" id="scrolledwindow18">
+                                        <property name="visible">True</property>
+                                        <property name="can_focus">False</property>
+                                        <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                                        <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+                                        <property name="shadow_type">GTK_SHADOW_IN</property>
+                                        <child>
+                                          <widget class="GtkTreeView" id="treeview_spell_checker">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">True</property>
+                                            <property name="headers_visible">False</property>
+                                          </widget>
+                                        </child>
+                                      </widget>
+                                    </child>
+                                  </widget>
+                                </child>
+                              </widget>
+                            </child>
+                            <child>
+                              <widget class="GtkHBox" id="hbox155">
+                                <property name="visible">True</property>
+                                <property name="spacing">6</property>
+                                <child>
+                                  <widget class="GtkImage" id="image422">
+                                    <property name="visible">True</property>
+                                    <property name="yalign">0</property>
+                                    <property name="stock">gtk-dialog-info</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkLabel" id="label616">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">&lt;small&gt;The list of languages reflects only the languages for which you have a dictionary installed.&lt;/small&gt;</property>
+                                    <property name="use_markup">True</property>
+                                    <property name="wrap">True</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label615">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Enable spell checking for languages:&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label567">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Spell Checking</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="position">2</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkVBox" id="vbox206">
+                <property name="visible">True</property>
+                <property name="border_width">12</property>
+                <property name="spacing">18</property>
+                <child>
+                  <widget class="GtkFrame" id="frame11">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment19">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkVBox" id="vbox207">
+                            <property name="visible">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <widget class="GtkHBox" id="hbox139">
+                                <property name="visible">True</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <widget class="GtkLabel" id="label586">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">Chat Th_eme:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">combobox_chat_theme</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkComboBox" id="combobox_chat_theme">
+                                    <property name="visible">True</property>
+                                    <property name="items" translatable="yes"></property>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </widget>
+                            </child>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label626">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Appearance&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="GtkFrame" id="frame12">
+                    <property name="visible">True</property>
+                    <property name="label_xalign">0</property>
+                    <property name="shadow_type">GTK_SHADOW_NONE</property>
+                    <child>
+                      <widget class="GtkAlignment" id="alignment20">
+                        <property name="visible">True</property>
+                        <property name="top_padding">6</property>
+                        <property name="left_padding">12</property>
+                        <child>
+                          <widget class="GtkCheckButton" id="checkbutton_theme_chat_room">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="label" translatable="yes">_Use for chat rooms</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                        </child>
+                      </widget>
+                    </child>
+                    <child>
+                      <widget class="GtkLabel" id="label627">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;b&gt;Options&lt;/b&gt;</property>
+                        <property name="use_markup">True</property>
+                      </widget>
+                      <packing>
+                        <property name="type">label_item</property>
+                      </packing>
+                    </child>
+                  </widget>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="GtkLabel" id="label624">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Themes</property>
+              </widget>
+              <packing>
+                <property name="type">tab</property>
+                <property name="position">3</property>
+                <property name="tab_fill">False</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area5">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button_close">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-close</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-6</property>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/src/empathy-preferences.h b/src/empathy-preferences.h
new file mode 100644 (file)
index 0000000..07ae6b5
--- /dev/null
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003-2007 Imendio AB
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ *          Richard Hult <richard@imendio.com>
+ *          Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __EMPATHY_PREFERENCES_H__
+#define __EMPATHY_PREFERENCES_H__
+
+#include <gtk/gtkwindow.h>
+
+G_BEGIN_DECLS
+
+GtkWidget * empathy_preferences_show (GtkWindow *parent);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_PREFERENCES_H__ */
+
+
diff --git a/src/empathy-status-icon.c b/src/empathy-status-icon.c
new file mode 100644 (file)
index 0000000..07224b0
--- /dev/null
@@ -0,0 +1,863 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007-2008 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <glib/gi18n.h>
+
+#include <libmissioncontrol/mission-control.h>
+
+#include <libempathy/empathy-contact-list.h>
+#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact.h>
+#include <libempathy/empathy-tp-chat.h>
+#include <libempathy/empathy-debug.h>
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-idle.h>
+#include <libempathy/empathy-filter.h>
+
+#include <libempathy-gtk/empathy-contact-dialogs.h>
+#include <libempathy-gtk/empathy-presence-chooser.h>
+#include <libempathy-gtk/empathy-conf.h>
+#include <libempathy-gtk/empathy-ui-utils.h>
+#include <libempathy-gtk/empathy-accounts-dialog.h>
+#include <libempathy-gtk/empathy-images.h>
+#include <libempathy-gtk/empathy-new-message-dialog.h>
+
+#include "empathy-status-icon.h"
+#include "empathy-preferences.h"
+
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+                      EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconPriv))
+
+#define DEBUG_DOMAIN "StatusIcon"
+
+/* Number of ms to wait when blinking */
+#define BLINK_TIMEOUT 500
+
+typedef struct _StatusIconEvent StatusIconEvent;
+
+struct _EmpathyStatusIconPriv {
+       GtkStatusIcon         *icon;
+       EmpathyContactManager *manager;
+       EmpathyFilter         *text_filter;
+       EmpathyFilter         *call_filter;
+       EmpathyIdle           *idle;
+       MissionControl        *mc;
+       GList                 *events;
+       gboolean               showing_event_icon;
+       StatusIconEvent       *flash_state_event;
+       guint                  blink_timeout;
+
+       GtkWindow             *window;
+       GtkWidget             *popup_menu;
+       GtkWidget             *show_window_item;
+       GtkWidget             *message_item;
+       GtkWidget             *status_item;
+};
+
+typedef void (*EventActivatedFunc) (StatusIconEvent *event);
+
+struct _StatusIconEvent {
+       gchar              *icon_name;
+       gchar              *message;
+       EventActivatedFunc  func;
+       gpointer            user_data;
+};
+
+
+static void       empathy_status_icon_class_init  (EmpathyStatusIconClass *klass);
+static void       empathy_status_icon_init        (EmpathyStatusIcon      *icon);
+static void       status_icon_finalize            (GObject                *object);
+static void       status_icon_text_filter_new_channel (EmpathyFilter          *filter,
+                                                  TpConn                 *tp_conn,
+                                                  TpChan                 *tp_chan,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_call_filter_new_channel (EmpathyFilter          *filter,
+                                                  TpConn                 *tp_conn,
+                                                  TpChan                 *tp_chan,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_message_received_cb (EmpathyTpChat          *tp_chat,
+                                                  EmpathyMessage         *message,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_idle_notify_cb      (EmpathyStatusIcon      *icon);
+static void       status_icon_update_tooltip      (EmpathyStatusIcon      *icon);
+static void       status_icon_set_from_state      (EmpathyStatusIcon      *icon);
+static void       status_icon_set_visibility      (EmpathyStatusIcon      *icon,
+                                                  gboolean                visible,
+                                                  gboolean                store);
+static void       status_icon_toggle_visibility   (EmpathyStatusIcon      *icon);
+static void       status_icon_activate_cb         (GtkStatusIcon          *status_icon,
+                                                  EmpathyStatusIcon      *icon);
+static gboolean   status_icon_delete_event_cb     (GtkWidget              *widget,
+                                                  GdkEvent               *event,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_popup_menu_cb       (GtkStatusIcon          *status_icon,
+                                                  guint                   button,
+                                                  guint                   activate_time,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_create_menu         (EmpathyStatusIcon      *icon);
+static void       status_icon_new_message_cb      (GtkWidget              *widget,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_quit_cb             (GtkWidget              *window,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_show_hide_window_cb (GtkWidget              *widget,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_pendings_changed_cb (EmpathyContactManager  *manager,
+                                                  EmpathyContact         *contact,
+                                                  EmpathyContact         *actor,
+                                                  guint                   reason,
+                                                  gchar                  *message,
+                                                  gboolean                is_pending,
+                                                  EmpathyStatusIcon      *icon);
+static void       status_icon_event_subscribe_cb  (StatusIconEvent        *event);
+static void       status_icon_event_flash_state_cb (StatusIconEvent       *event);
+static void       status_icon_event_msg_cb        (StatusIconEvent        *event);
+static StatusIconEvent * status_icon_event_new    (EmpathyStatusIcon      *icon,
+                                                  const gchar            *icon_name,
+                                                  const gchar            *message);
+static void       status_icon_event_remove        (EmpathyStatusIcon      *icon,
+                                                  StatusIconEvent        *event);
+static gboolean   status_icon_event_timeout_cb    (EmpathyStatusIcon      *icon);
+static void       status_icon_event_free          (StatusIconEvent        *event);
+
+G_DEFINE_TYPE (EmpathyStatusIcon, empathy_status_icon, G_TYPE_OBJECT);
+
+static void
+status_icon_notify_use_nm_cb (EmpathyConf  *conf,
+                             const gchar *key,
+                             gpointer     user_data)
+{
+       EmpathyStatusIconPriv *priv = GET_PRIV (user_data);
+       gboolean               use_nm;
+
+       if (empathy_conf_get_bool (conf, key, &use_nm)) {
+               empathy_idle_set_use_nm (priv->idle, use_nm);
+       }
+}
+
+static void
+status_icon_notify_visibility_cb (EmpathyConf *conf,
+                                 const gchar *key,
+                                 gpointer     user_data)
+{
+       EmpathyStatusIcon *icon = user_data;
+       gboolean           hidden = FALSE;
+
+       if (empathy_conf_get_bool (conf, key, &hidden)) {
+               status_icon_set_visibility (icon, !hidden, FALSE);
+       }
+}
+
+static void
+empathy_status_icon_class_init (EmpathyStatusIconClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = status_icon_finalize;
+
+       g_type_class_add_private (object_class, sizeof (EmpathyStatusIconPriv));
+}
+
+static void
+empathy_status_icon_init (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       GList                 *pendings, *l;
+       gboolean               use_nm;
+
+       priv = GET_PRIV (icon);
+
+       priv->icon = gtk_status_icon_new ();
+       priv->manager = empathy_contact_manager_new ();
+       priv->mc = empathy_mission_control_new ();
+       priv->text_filter = empathy_filter_new ("org.gnome.Empathy.ChatFilter",
+                                               "/org/gnome/Empathy/ChatFilter",
+                                               TP_IFACE_CHANNEL_TYPE_TEXT,
+                                               MC_FILTER_PRIORITY_DIALOG,
+                                               MC_FILTER_FLAG_INCOMING);
+       priv->call_filter = empathy_filter_new ("org.gnome.Empathy.CallFilter",
+                                               "/org/gnome/Empathy/CallFilter",
+                                               TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
+                                               MC_FILTER_PRIORITY_DIALOG,
+                                               MC_FILTER_FLAG_INCOMING);
+
+       /* Setup EmpathyIdle */
+       priv->idle = empathy_idle_new ();
+       empathy_conf_get_bool (empathy_conf_get (),
+                              EMPATHY_PREFS_USE_NM,
+                              &use_nm);
+       empathy_conf_notify_add (empathy_conf_get (),
+                                EMPATHY_PREFS_USE_NM,
+                                status_icon_notify_use_nm_cb,
+                                icon);
+       empathy_idle_set_auto_away (priv->idle, TRUE);
+       empathy_idle_set_use_nm (priv->idle, use_nm);
+
+       /* make icon listen and respond to MAIN_WINDOW_HIDDEN changes */
+       empathy_conf_notify_add (empathy_conf_get (),
+                                EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
+                                status_icon_notify_visibility_cb,
+                                icon);
+
+       status_icon_create_menu (icon);
+       status_icon_idle_notify_cb (icon);
+
+       g_signal_connect (priv->text_filter, "new-channel",
+                         G_CALLBACK (status_icon_text_filter_new_channel),
+                         icon);
+       g_signal_connect (priv->call_filter, "new-channel",
+                         G_CALLBACK (status_icon_call_filter_new_channel),
+                         icon);
+       g_signal_connect_swapped (priv->idle, "notify",
+                                 G_CALLBACK (status_icon_idle_notify_cb),
+                                 icon);
+       g_signal_connect (priv->icon, "activate",
+                         G_CALLBACK (status_icon_activate_cb),
+                         icon);
+       g_signal_connect (priv->icon, "popup-menu",
+                         G_CALLBACK (status_icon_popup_menu_cb),
+                         icon);
+       g_signal_connect (priv->manager, "pendings-changed",
+                         G_CALLBACK (status_icon_pendings_changed_cb),
+                         icon);
+
+       pendings = empathy_contact_list_get_pendings (EMPATHY_CONTACT_LIST (priv->manager));
+       for (l = pendings; l; l = l->next) {
+               EmpathyPendingInfo *info;
+
+               info = l->data;
+               status_icon_pendings_changed_cb (priv->manager,
+                                                info->member,
+                                                info->actor,
+                                                0,
+                                                info->message,
+                                                TRUE,
+                                                icon);
+               empathy_pending_info_free (info);
+       }
+       g_list_free (pendings);
+}
+
+static void
+status_icon_finalize (GObject *object)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (object);
+
+       g_list_foreach (priv->events, (GFunc) status_icon_event_free, NULL);
+       g_list_free (priv->events);
+
+       if (priv->blink_timeout) {
+               g_source_remove (priv->blink_timeout);
+       }
+
+       g_object_unref (priv->icon);
+       g_object_unref (priv->window);
+       g_object_unref (priv->idle);
+       g_object_unref (priv->manager);
+       g_object_unref (priv->mc);
+       g_object_unref (priv->text_filter);
+       g_object_unref (priv->call_filter);
+}
+
+EmpathyStatusIcon *
+empathy_status_icon_new (GtkWindow *window)
+{
+       EmpathyStatusIconPriv *priv;
+       EmpathyStatusIcon     *icon;
+       gboolean               should_hide;
+
+       g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+
+       icon = g_object_new (EMPATHY_TYPE_STATUS_ICON, NULL);
+       priv = GET_PRIV (icon);
+
+       priv->window = g_object_ref (window);
+
+       g_signal_connect (priv->window, "delete-event",
+                         G_CALLBACK (status_icon_delete_event_cb),
+                         icon);
+
+       empathy_conf_get_bool (empathy_conf_get (),
+                             EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN,
+                             &should_hide);
+
+       if (gtk_window_is_active (priv->window) == should_hide) {
+               status_icon_set_visibility (icon, !should_hide, FALSE);
+       }
+
+       return icon;
+}
+
+static void
+status_icon_text_filter_new_channel (EmpathyFilter     *filter,
+                                    TpConn            *tp_conn,
+                                    TpChan            *tp_chan,
+                                    EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       McAccount             *account;
+       EmpathyTpChat         *tp_chat;
+
+       priv = GET_PRIV (icon);
+
+       account = mission_control_get_account_for_connection (priv->mc, tp_conn, NULL);
+
+       empathy_debug (DEBUG_DOMAIN, "New text channel to be filtered for contact %s",
+                      empathy_inspect_channel (account, tp_chan));
+
+       tp_chat = empathy_tp_chat_new (account, tp_chan);
+       g_object_set_data (G_OBJECT (tp_chat), "filter", filter);
+       g_object_unref (account);
+
+       g_signal_connect (tp_chat, "message-received",
+                         G_CALLBACK (status_icon_message_received_cb),
+                         icon);
+}
+
+static void
+status_icon_message_received_cb (EmpathyTpChat     *tp_chat,
+                                EmpathyMessage    *message,
+                                EmpathyStatusIcon *icon)
+{
+       EmpathyContact  *sender;
+       gchar           *msg;
+       StatusIconEvent *event;
+
+       empathy_debug (DEBUG_DOMAIN, "Message received, add event");
+
+       g_signal_handlers_disconnect_by_func (tp_chat,
+                                             status_icon_message_received_cb,
+                                             icon);
+
+       sender = empathy_message_get_sender (message);
+       msg = g_strdup_printf (_("New message from %s:\n%s"),
+                              empathy_contact_get_name (sender),
+                              empathy_message_get_body (message));
+
+       event = status_icon_event_new (icon, EMPATHY_IMAGE_NEW_MESSAGE, msg);
+       event->func = status_icon_event_msg_cb;
+       event->user_data = tp_chat;
+       g_free (msg);
+}
+
+static void
+status_icon_call_member_added_cb (EmpathyTpGroup    *group,
+                                 EmpathyContact    *member,
+                                 EmpathyContact    *actor,
+                                 guint              reason,
+                                 const gchar       *message,
+                                 EmpathyStatusIcon *icon)
+{
+       EmpathyFilter *filter;
+
+       if (empathy_contact_is_user (member)) {
+               /* We are member, it's an outgoing call, we can dispatch
+                * the channel without asking the user */
+               empathy_debug (DEBUG_DOMAIN, "Process OUTGOING call channel");
+               filter = g_object_get_data (G_OBJECT (group), "filter");
+               empathy_filter_process (filter,
+                                       empathy_tp_group_get_channel (group),
+                                       TRUE);
+               g_object_unref (group);
+       }
+}
+
+static void
+status_icon_event_call_cb (StatusIconEvent *event)
+{
+       EmpathyFilter  *filter;
+       EmpathyTpGroup *group;
+
+       empathy_debug (DEBUG_DOMAIN, "Dispatching call channel");
+
+       group = event->user_data;
+       filter = g_object_get_data (G_OBJECT (group), "filter");
+       empathy_filter_process (filter,
+                               empathy_tp_group_get_channel (group),
+                               TRUE);
+       g_object_unref (group);
+}
+
+static void
+status_icon_call_local_pending_cb (EmpathyTpGroup    *group,
+                                  EmpathyContact    *member,
+                                  EmpathyContact    *actor,
+                                  guint              reason,
+                                  const gchar       *message,
+                                  EmpathyStatusIcon *icon)
+{
+       StatusIconEvent *event;
+
+       if (empathy_contact_is_user (member)) {
+               gchar *msg;
+
+               /* We are local pending, it's an incoming call, we need to ask
+                * the user if he wants to accept the call. */
+               empathy_contact_run_until_ready (member,
+                                                EMPATHY_CONTACT_READY_NAME,
+                                                NULL);
+
+               empathy_debug (DEBUG_DOMAIN, "INCOMING call, add event");
+
+               msg = g_strdup_printf (_("Incoming call from %s:\n%s"),
+                                      empathy_contact_get_name (member),
+                                      message);
+
+               event = status_icon_event_new (icon, EMPATHY_IMAGE_VOIP, msg);
+               event->func = status_icon_event_call_cb;
+               event->user_data = group;
+               g_free (msg);
+       }
+}
+
+static void
+status_icon_call_filter_new_channel (EmpathyFilter     *filter,
+                                    TpConn            *tp_conn,
+                                    TpChan            *tp_chan,
+                                    EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       McAccount             *account;
+       EmpathyTpGroup        *group;
+
+       priv = GET_PRIV (icon);
+
+       account = mission_control_get_account_for_connection (priv->mc, tp_conn, NULL);
+
+       empathy_debug (DEBUG_DOMAIN, "New media channel to be filtered");
+
+       /* FIXME: We have to check if the user is member or local-pending to
+        * know if it's an incoming or outgoing call because of the way we
+        * request media channels MC can't know if it's incoming or outgoing */
+       group = empathy_tp_group_new (account, tp_chan);
+       g_object_set_data (G_OBJECT (group), "filter", filter);
+       g_object_unref (account);
+
+       g_signal_connect (group, "member-added",
+                         G_CALLBACK (status_icon_call_member_added_cb),
+                         icon);
+       g_signal_connect (group, "local-pending",
+                         G_CALLBACK (status_icon_call_local_pending_cb),
+                         icon);
+}
+
+static void
+status_icon_idle_notify_cb (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       McPresence             flash_state;
+
+       priv = GET_PRIV (icon);
+
+       flash_state = empathy_idle_get_flash_state (priv->idle);
+       if (flash_state != MC_PRESENCE_UNSET) {
+               const gchar *icon_name;
+
+               icon_name = empathy_icon_name_for_presence (flash_state);
+               if (!priv->flash_state_event) {
+                       /* We are now flashing */
+                       priv->flash_state_event = status_icon_event_new (icon, icon_name, NULL);
+                       priv->flash_state_event->user_data = icon;
+                       priv->flash_state_event->func = status_icon_event_flash_state_cb;
+               } else {
+                       /* We are still flashing but with another state */
+                       g_free (priv->flash_state_event->icon_name);
+                       priv->flash_state_event->icon_name = g_strdup (icon_name);
+               }
+       }
+       else if (priv->flash_state_event) {
+               /* We are no more flashing */
+               status_icon_event_remove (icon, priv->flash_state_event);
+               priv->flash_state_event = NULL;
+       }
+
+       if (!priv->showing_event_icon) {
+               status_icon_set_from_state (icon);
+       }
+
+       status_icon_update_tooltip (icon);
+}
+
+static void
+status_icon_update_tooltip (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       const gchar           *tooltip = NULL;
+
+       priv = GET_PRIV (icon);
+
+       if (priv->events) {
+               StatusIconEvent *event;
+
+               event = priv->events->data;
+               tooltip = event->message;
+       }
+
+       if (!tooltip) {
+               tooltip = empathy_idle_get_status (priv->idle);
+       }
+
+       gtk_status_icon_set_tooltip (priv->icon, tooltip);      
+}
+
+static void
+status_icon_set_from_state (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       McPresence             state;
+       const gchar           *icon_name;
+
+       priv = GET_PRIV (icon);
+
+       state = empathy_idle_get_state (priv->idle);
+       icon_name = empathy_icon_name_for_presence (state);
+       gtk_status_icon_set_from_icon_name (priv->icon, icon_name);
+}
+
+static void
+status_icon_set_visibility (EmpathyStatusIcon *icon,
+                           gboolean           visible,
+                           gboolean           store)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (icon);
+
+       if (store) {
+               empathy_conf_set_bool (empathy_conf_get (),
+                                      EMPATHY_PREFS_UI_MAIN_WINDOW_HIDDEN, !visible);
+       }
+
+       if (!visible) {
+               empathy_window_iconify (priv->window, priv->icon);
+       } else {
+               GList *accounts;
+
+               empathy_window_present (GTK_WINDOW (priv->window), TRUE);
+       
+               /* Show the accounts dialog if there is no enabled accounts */
+               accounts = mc_accounts_list_by_enabled (TRUE);
+               if (accounts) {
+                       mc_accounts_list_free (accounts);
+               } else {
+                       empathy_debug (DEBUG_DOMAIN,
+                                     "No enabled account, Showing account dialog");
+                       empathy_accounts_dialog_show (GTK_WINDOW (priv->window));
+               }
+       }
+}
+
+static void
+status_icon_toggle_visibility (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv = GET_PRIV (icon);
+       gboolean               visible;
+
+       visible = gtk_window_is_active (priv->window);
+       status_icon_set_visibility (icon, !visible, TRUE);
+}
+
+static void
+status_icon_activate_cb (GtkStatusIcon     *status_icon,
+                        EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (icon);
+
+       empathy_debug (DEBUG_DOMAIN, "Activated: %s",
+                      priv->events ? "event" : "toggle");
+
+       if (priv->events) {
+               status_icon_event_remove (icon, priv->events->data);
+       } else {
+               status_icon_toggle_visibility (icon);
+       }
+}
+
+static gboolean
+status_icon_delete_event_cb (GtkWidget         *widget,
+                            GdkEvent          *event,
+                            EmpathyStatusIcon *icon)
+{
+       status_icon_set_visibility (icon, FALSE, TRUE);
+
+       return TRUE;
+}
+
+static void
+status_icon_popup_menu_cb (GtkStatusIcon     *status_icon,
+                          guint              button,
+                          guint              activate_time,
+                          EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       GtkWidget             *submenu;
+       gboolean               show;
+
+       priv = GET_PRIV (icon);
+
+       show = empathy_window_get_is_visible (GTK_WINDOW (priv->window));
+
+       g_signal_handlers_block_by_func (priv->show_window_item,
+                                        status_icon_show_hide_window_cb,
+                                        icon);
+       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (priv->show_window_item),
+                                       show);
+       g_signal_handlers_unblock_by_func (priv->show_window_item,
+                                          status_icon_show_hide_window_cb,
+                                          icon);
+
+       submenu = empathy_presence_chooser_create_menu ();
+       gtk_menu_item_set_submenu (GTK_MENU_ITEM (priv->status_item),
+                                  submenu);
+
+       gtk_menu_popup (GTK_MENU (priv->popup_menu),
+                       NULL, NULL,
+                       gtk_status_icon_position_menu,
+                       priv->icon,
+                       button,
+                       activate_time);
+}
+
+static void
+status_icon_create_menu (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       GladeXML              *glade;
+
+       priv = GET_PRIV (icon);
+
+       glade = empathy_glade_get_file ("empathy-status-icon.glade",
+                                      "tray_menu",
+                                      NULL,
+                                      "tray_menu", &priv->popup_menu,
+                                      "tray_show_list", &priv->show_window_item,
+                                      "tray_new_message", &priv->message_item,
+                                      "tray_status", &priv->status_item,
+                                      NULL);
+
+       empathy_glade_connect (glade,
+                             icon,
+                             "tray_show_list", "toggled", status_icon_show_hide_window_cb,
+                             "tray_new_message", "activate", status_icon_new_message_cb,
+                             "tray_quit", "activate", status_icon_quit_cb,
+                             NULL);
+
+       g_object_unref (glade);
+}
+
+static void
+status_icon_new_message_cb (GtkWidget         *widget,
+                           EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (icon);
+
+       empathy_new_message_dialog_show (NULL);
+}
+
+static void
+status_icon_quit_cb (GtkWidget         *window,
+                    EmpathyStatusIcon *icon)
+{
+       gtk_main_quit ();
+}
+
+static void
+status_icon_show_hide_window_cb (GtkWidget         *widget,
+                                EmpathyStatusIcon *icon)
+{
+       gboolean visible;
+
+       visible = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
+       status_icon_set_visibility (icon, visible, TRUE);
+}
+
+static void
+status_icon_pendings_changed_cb (EmpathyContactManager *manager,
+                                EmpathyContact        *contact,
+                                EmpathyContact        *actor,
+                                guint                  reason,
+                                gchar                 *message,
+                                gboolean               is_pending,
+                                EmpathyStatusIcon     *icon)
+{
+       EmpathyStatusIconPriv *priv;
+       StatusIconEvent       *event;
+       GString               *str;
+
+       priv = GET_PRIV (icon);
+
+       if (!is_pending) {
+               /* FIXME: We should remove the event */
+               return;
+       }
+
+       empathy_contact_run_until_ready (contact,
+                                        EMPATHY_CONTACT_READY_NAME,
+                                        NULL);
+
+       str = g_string_new (NULL);
+       g_string_printf (str, _("Subscription requested by %s"),
+                        empathy_contact_get_name (contact));   
+       if (!G_STR_EMPTY (message)) {
+               g_string_append_printf (str, _("\nMessage: %s"), message);
+       }
+
+       event = status_icon_event_new (icon, GTK_STOCK_DIALOG_QUESTION, str->str);
+       event->user_data = g_object_ref (contact);
+       event->func = status_icon_event_subscribe_cb;
+
+       g_string_free (str, TRUE);
+}
+
+static void
+status_icon_event_subscribe_cb (StatusIconEvent *event)
+{
+       EmpathyContact *contact;
+
+       contact = EMPATHY_CONTACT (event->user_data);
+
+       empathy_subscription_dialog_show (contact, NULL);
+
+       g_object_unref (contact);
+}
+
+static void
+status_icon_event_flash_state_cb (StatusIconEvent *event)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (event->user_data);
+
+       empathy_idle_set_flash_state (priv->idle, MC_PRESENCE_UNSET);
+}
+
+static void
+status_icon_event_msg_cb (StatusIconEvent *event)
+{
+       EmpathyFilter *filter;
+       EmpathyTpChat *tp_chat;
+
+       empathy_debug (DEBUG_DOMAIN, "Dispatching text channel");
+
+       tp_chat = event->user_data;
+       filter = g_object_get_data (G_OBJECT (tp_chat), "filter");
+       empathy_filter_process (filter,
+                               empathy_tp_chat_get_channel (tp_chat),
+                               TRUE);
+
+       g_object_unref (tp_chat);
+}
+
+static StatusIconEvent *
+status_icon_event_new (EmpathyStatusIcon *icon,
+                      const gchar       *icon_name,
+                      const gchar       *message)
+{
+       EmpathyStatusIconPriv *priv;
+       StatusIconEvent       *event;
+
+       priv = GET_PRIV (icon);
+
+       event = g_slice_new0 (StatusIconEvent);
+       event->icon_name = g_strdup (icon_name);        
+       event->message = g_strdup (message);
+
+       priv->events = g_list_append (priv->events, event);
+       if (!priv->blink_timeout) {
+               priv->showing_event_icon = FALSE;
+               priv->blink_timeout = g_timeout_add (BLINK_TIMEOUT,
+                                                    (GSourceFunc) status_icon_event_timeout_cb,
+                                                    icon);
+               status_icon_event_timeout_cb (icon);
+               status_icon_update_tooltip (icon);
+       }
+
+       return event;
+}
+
+static void
+status_icon_event_remove (EmpathyStatusIcon *icon,
+                         StatusIconEvent   *event)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (icon);
+
+       if (event->func) {
+               event->func (event);
+       }
+       priv->events = g_list_remove (priv->events, event);
+       status_icon_event_free (event);
+       priv->showing_event_icon = FALSE;
+       status_icon_update_tooltip (icon);
+       status_icon_set_from_state (icon);
+
+       if (priv->events) {
+               return;
+       }
+
+       if (priv->blink_timeout) {
+               g_source_remove (priv->blink_timeout);
+               priv->blink_timeout = 0;
+       }
+}
+
+static gboolean
+status_icon_event_timeout_cb (EmpathyStatusIcon *icon)
+{
+       EmpathyStatusIconPriv *priv;
+
+       priv = GET_PRIV (icon);
+
+       priv->showing_event_icon = !priv->showing_event_icon;
+
+       if (!priv->showing_event_icon) {
+               status_icon_set_from_state (icon);
+       } else {
+               StatusIconEvent *event;
+
+               event = priv->events->data;
+               gtk_status_icon_set_from_icon_name (priv->icon, event->icon_name);
+       }
+
+       return TRUE;
+}
+
+static void
+status_icon_event_free (StatusIconEvent *event)
+{
+       g_free (event->icon_name);
+       g_free (event->message);
+       g_slice_free (StatusIconEvent, event);
+}
+
diff --git a/src/empathy-status-icon.glade b/src/empathy-status-icon.glade
new file mode 100644 (file)
index 0000000..ab0f09f
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+  <widget class="GtkMenu" id="tray_menu">
+    <child>
+      <widget class="GtkCheckMenuItem" id="tray_show_list">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">_Show Contact List</property>
+        <property name="use_underline">True</property>
+      </widget>
+    </child>
+    <child>
+      <widget class="GtkSeparatorMenuItem" id="avskiljare5">
+        <property name="visible">True</property>
+      </widget>
+    </child>
+    <child>
+      <widget class="GtkImageMenuItem" id="tray_new_message">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">_New Conversation...</property>
+        <property name="use_underline">True</property>
+        <child internal-child="image">
+          <widget class="GtkImage" id="image599">
+            <property name="visible">True</property>
+            <property name="icon_size">1</property>
+            <property name="icon_name">im-message-new</property>
+          </widget>
+        </child>
+      </widget>
+    </child>
+    <child>
+      <widget class="GtkMenuItem" id="tray_status">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">Status</property>
+        <property name="use_underline">True</property>
+      </widget>
+    </child>
+    <child>
+      <widget class="GtkSeparatorMenuItem" id="avskiljare6">
+        <property name="visible">True</property>
+      </widget>
+    </child>
+    <child>
+      <widget class="GtkImageMenuItem" id="tray_quit">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">_Quit</property>
+        <property name="use_underline">True</property>
+        <child internal-child="image">
+          <widget class="GtkImage" id="image600">
+            <property name="visible">True</property>
+            <property name="stock">gtk-quit</property>
+            <property name="icon_size">1</property>
+          </widget>
+        </child>
+      </widget>
+    </child>
+  </widget>
+</glade-interface>
diff --git a/src/empathy-status-icon.h b/src/empathy-status-icon.h
new file mode 100644 (file)
index 0000000..a7ca3c3
--- /dev/null
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#ifndef __EMPATHY_STATUS_ICON_H__
+#define __EMPATHY_STATUS_ICON_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_STATUS_ICON         (empathy_status_icon_get_type ())
+#define EMPATHY_STATUS_ICON(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIcon))
+#define EMPATHY_STATUS_ICON_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconClass))
+#define EMPATHY_IS_STATUS_ICON(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_STATUS_ICON))
+#define EMPATHY_IS_STATUS_ICON_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_STATUS_ICON))
+#define EMPATHY_STATUS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_STATUS_ICON, EmpathyStatusIconClass))
+
+typedef struct _EmpathyStatusIcon      EmpathyStatusIcon;
+typedef struct _EmpathyStatusIconClass EmpathyStatusIconClass;
+typedef struct _EmpathyStatusIconPriv  EmpathyStatusIconPriv;
+
+struct _EmpathyStatusIcon {
+       GObject      parent;
+};
+
+struct _EmpathyStatusIconClass {
+       GObjectClass parent_class;
+};
+
+GType              empathy_status_icon_get_type (void) G_GNUC_CONST;
+EmpathyStatusIcon *empathy_status_icon_new      (GtkWindow *window);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_STATUS_ICON_H__ */
index d261cd54b31f55f96966bf5443b04f3c776b8438..38060912ce41b027f363cdbe9b6a9c51429ec3ee 100644 (file)
@@ -51,8 +51,8 @@
 #include <libempathy-gtk/empathy-chat.h>
 #include <libempathy-gtk/empathy-private-chat.h>
 #include <libempathy-gtk/empathy-group-chat.h>
-#include <libempathy-gtk/empathy-chat-window.h>
 
+#include "empathy-chat-window.h"
 #include "bacon-message-connection.h"
 
 #define DEBUG_DOMAIN "EmpathyMain"
@@ -89,7 +89,7 @@ new_text_channel_cb (EmpathyChandler *chandler,
                        empathy_chat_set_tp_chat (chat, tp_chat);
                        g_object_unref (tp_chat);
                }
-               empathy_chat_present (chat);
+               empathy_chat_window_present_chat (chat);
 
                g_object_unref (account);
                return;
@@ -112,7 +112,7 @@ new_text_channel_cb (EmpathyChandler *chandler,
                return;
        }
 
-       empathy_chat_present (chat);
+       empathy_chat_window_present_chat (chat);
 
        g_object_unref (chat);
        g_object_unref (account);
diff --git a/src/ephy-spinner.c b/src/ephy-spinner.c
new file mode 100644 (file)
index 0000000..b67b90f
--- /dev/null
@@ -0,0 +1,977 @@
+/* 
+ * Copyright © 2000 Eazel, Inc.
+ * Copyright © 2002-2004 Marco Pesenti Gritti
+ * Copyright © 2004, 2006 Christian Persch
+ *
+ * Nautilus is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Andy Hertzfeld <andy@eazel.com>
+ *
+ * Ephy port by Marco Pesenti Gritti <marco@it.gnome.org>
+ * 
+ * $Id: ephy-spinner.c 2114 2006-12-25 12:15:00Z mr $
+ */
+
+#include <config.h>
+
+#include "ephy-spinner.h"
+
+/* #include "ephy-debug.h" */
+#define LOG(msg, args...)
+#define START_PROFILER(name)
+#define STOP_PROFILER(name)
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtkicontheme.h>
+#include <gtk/gtkiconfactory.h>
+#include <gtk/gtksettings.h>
+
+/* Spinner cache implementation */
+
+#define EPHY_TYPE_SPINNER_CACHE                        (ephy_spinner_cache_get_type())
+#define EPHY_SPINNER_CACHE(object)             (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCache))
+#define EPHY_SPINNER_CACHE_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCacheClass))
+#define EPHY_IS_SPINNER_CACHE(object)          (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_SPINNER_CACHE))
+#define EPHY_IS_SPINNER_CACHE_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_SPINNER_CACHE))
+#define EPHY_SPINNER_CACHE_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCacheClass))
+
+typedef struct _EphySpinnerCache       EphySpinnerCache;
+typedef struct _EphySpinnerCacheClass  EphySpinnerCacheClass;
+typedef struct _EphySpinnerCachePrivate        EphySpinnerCachePrivate;
+
+struct _EphySpinnerCacheClass
+{
+       GObjectClass parent_class;
+};
+
+struct _EphySpinnerCache
+{
+       GObject parent_object;
+
+       /*< private >*/
+       EphySpinnerCachePrivate *priv;
+};
+
+#define EPHY_SPINNER_CACHE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCachePrivate))
+
+struct _EphySpinnerCachePrivate
+{
+       /* Hash table of GdkScreen -> EphySpinnerCacheData */
+       GHashTable *hash;
+};
+
+typedef struct
+{
+       guint ref_count;
+       GtkIconSize size;
+       int width;
+       int height;
+       GdkPixbuf **animation_pixbufs;
+       guint n_animation_pixbufs;
+} EphySpinnerImages;
+
+#define LAST_ICON_SIZE                 GTK_ICON_SIZE_DIALOG + 1
+#define SPINNER_ICON_NAME              "process-working"
+#define SPINNER_FALLBACK_ICON_NAME     "gnome-spinner"
+#define EPHY_SPINNER_IMAGES_INVALID    ((EphySpinnerImages *) 0x1)
+
+typedef struct
+{
+       GdkScreen *screen;
+       GtkIconTheme *icon_theme;
+       EphySpinnerImages *images[LAST_ICON_SIZE];
+} EphySpinnerCacheData;
+
+static void ephy_spinner_cache_class_init (EphySpinnerCacheClass *klass);
+static void ephy_spinner_cache_init      (EphySpinnerCache *cache);
+
+static GObjectClass *ephy_spinner_cache_parent_class;
+
+static GType
+ephy_spinner_cache_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY (type == 0))
+       {
+               const GTypeInfo our_info =
+               {
+                       sizeof (EphySpinnerCacheClass),
+                       NULL,
+                       NULL,
+                       (GClassInitFunc) ephy_spinner_cache_class_init,
+                       NULL,
+                       NULL,
+                       sizeof (EphySpinnerCache),
+                       0,
+                       (GInstanceInitFunc) ephy_spinner_cache_init
+               };
+
+               type = g_type_register_static (G_TYPE_OBJECT,
+                                              "EphySpinnerCache",
+                                              &our_info, 0);
+       }
+
+       return type;
+}
+
+static EphySpinnerImages *
+ephy_spinner_images_ref (EphySpinnerImages *images)
+{
+       g_return_val_if_fail (images != NULL, NULL);
+
+       images->ref_count++;
+
+       return images;
+}
+
+static void
+ephy_spinner_images_unref (EphySpinnerImages *images)
+{
+       g_return_if_fail (images != NULL);
+
+       images->ref_count--;
+       if (images->ref_count == 0)
+       {
+               guint i;
+
+               LOG ("Freeing spinner images %p for size %d", images, images->size);
+
+               for (i = 0; i < images->n_animation_pixbufs; ++i)
+               {
+                       g_object_unref (images->animation_pixbufs[i]);
+               }
+               g_free (images->animation_pixbufs);
+
+               g_free (images);
+       }
+}
+
+static void
+ephy_spinner_cache_data_unload (EphySpinnerCacheData *data)
+{
+       GtkIconSize size;
+       EphySpinnerImages *images;
+
+       g_return_if_fail (data != NULL);
+
+       LOG ("EphySpinnerDataCache unload for screen %p", data->screen);
+
+       for (size = GTK_ICON_SIZE_INVALID; size < LAST_ICON_SIZE; ++size)
+       {
+               images = data->images[size];
+               data->images[size] = NULL;
+
+               if (images != NULL && images != EPHY_SPINNER_IMAGES_INVALID)
+               {
+                       ephy_spinner_images_unref (images);
+               }
+       }
+}
+
+static GdkPixbuf *
+extract_frame (GdkPixbuf *grid_pixbuf,
+              int x,
+              int y,
+              int size)
+{
+       GdkPixbuf *pixbuf;
+
+       if (x + size > gdk_pixbuf_get_width (grid_pixbuf) ||
+           y + size > gdk_pixbuf_get_height (grid_pixbuf))
+       {
+               return NULL;
+       }
+
+       pixbuf = gdk_pixbuf_new_subpixbuf (grid_pixbuf,
+                                          x, y,
+                                          size, size);
+       g_return_val_if_fail (pixbuf != NULL, NULL);
+
+       return pixbuf;
+}
+
+static GdkPixbuf *
+scale_to_size (GdkPixbuf *pixbuf,
+              int dw,
+              int dh)
+{
+       GdkPixbuf *result;
+       int pw, ph;
+
+       g_return_val_if_fail (pixbuf != NULL, NULL);
+
+       pw = gdk_pixbuf_get_width (pixbuf);
+       ph = gdk_pixbuf_get_height (pixbuf);
+
+       if (pw != dw || ph != dh)
+       {
+               result = gdk_pixbuf_scale_simple (pixbuf, dw, dh,
+                                                 GDK_INTERP_BILINEAR);
+               g_object_unref (pixbuf);
+               return result;
+       }
+
+       return pixbuf;
+}
+
+static EphySpinnerImages *
+ephy_spinner_images_load (GdkScreen *screen,
+                         GtkIconTheme *icon_theme,
+                         GtkIconSize icon_size)
+{
+       EphySpinnerImages *images;
+       GdkPixbuf *icon_pixbuf, *pixbuf;
+       GtkIconInfo *icon_info = NULL;
+       int grid_width, grid_height, x, y, requested_size, size, isw, ish, n;
+       const char *icon;
+       GSList *list = NULL, *l;
+
+       LOG ("EphySpinnerCacheData loading for screen %p at size %d", screen, icon_size);
+
+       START_PROFILER ("loading spinner animation")
+
+       if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_for_screen (screen),
+                                               icon_size, &isw, &ish)) goto loser;
+
+       requested_size = MAX (ish, isw);
+
+       /* Load the animation. The 'rest icon' is the 0th frame */
+       icon_info = gtk_icon_theme_lookup_icon (icon_theme,
+                                               SPINNER_ICON_NAME,
+                                               requested_size, 0);
+       if (icon_info == NULL)
+       {
+               g_warning ("Throbber animation not found");
+       
+               /* If the icon naming spec compliant name wasn't found, try the old name */
+               icon_info = gtk_icon_theme_lookup_icon (icon_theme,
+                                                       SPINNER_FALLBACK_ICON_NAME,
+                                                       requested_size, 0);
+               if (icon_info == NULL)
+               {
+                       g_warning ("Throbber fallback animation not found either");
+                       goto loser;
+               }
+       }
+       g_assert (icon_info != NULL);
+
+       size = gtk_icon_info_get_base_size (icon_info);
+       icon = gtk_icon_info_get_filename (icon_info);
+       if (icon == NULL) goto loser;
+
+       icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL);
+       gtk_icon_info_free (icon_info);
+       icon_info = NULL;
+
+       if (icon_pixbuf == NULL)
+       {
+               g_warning ("Could not load the spinner file");
+               goto loser;
+       }
+
+       grid_width = gdk_pixbuf_get_width (icon_pixbuf);
+       grid_height = gdk_pixbuf_get_height (icon_pixbuf);
+
+       n = 0;
+       for (y = 0; y < grid_height; y += size)
+       {
+               for (x = 0; x < grid_width ; x += size)
+               {
+                       pixbuf = extract_frame (icon_pixbuf, x, y, size);
+
+                       if (pixbuf)
+                       {
+                               list = g_slist_prepend (list, pixbuf);
+                               ++n;
+                       }
+                       else
+                       {
+                               g_warning ("Cannot extract frame (%d, %d) from the grid\n", x, y);
+                       }
+               }
+       }
+
+       g_object_unref (icon_pixbuf);
+
+       if (list == NULL) goto loser;
+       g_assert (n > 0);
+
+       if (size > requested_size)
+       {
+               for (l = list; l != NULL; l = l->next)
+               {
+                       l->data = scale_to_size (l->data, isw, ish);
+               }
+       }
+
+       /* Now we've successfully got all the data */
+       images = g_new (EphySpinnerImages, 1);
+       images->ref_count = 1;
+
+       images->size = icon_size;
+       images->width = images->height = requested_size;
+
+       images->n_animation_pixbufs = n;
+       images->animation_pixbufs = g_new (GdkPixbuf *, n);
+
+       for (l = list; l != NULL; l = l->next)
+       {
+               g_assert (l->data != NULL);
+               images->animation_pixbufs[--n] = l->data;
+       }
+       g_assert (n == 0);
+
+       g_slist_free (list);
+
+       STOP_PROFILER ("loading spinner animation")
+
+       return images;
+
+loser:
+       if (icon_info)
+       {
+               gtk_icon_info_free (icon_info);
+       }
+       g_slist_foreach (list, (GFunc) g_object_unref, NULL);
+
+       STOP_PROFILER ("loading spinner animation")
+
+       return NULL;
+}
+
+static EphySpinnerCacheData *
+ephy_spinner_cache_data_new (GdkScreen *screen)
+{
+       EphySpinnerCacheData *data;
+
+       data = g_new0 (EphySpinnerCacheData, 1);
+
+       data->screen = screen;
+       data->icon_theme = gtk_icon_theme_get_for_screen (screen);
+       g_signal_connect_swapped (data->icon_theme, "changed",
+                                 G_CALLBACK (ephy_spinner_cache_data_unload),
+                                 data);
+
+       return data;
+}
+
+static void
+ephy_spinner_cache_data_free (EphySpinnerCacheData *data)
+{
+       g_return_if_fail (data != NULL);
+       g_return_if_fail (data->icon_theme != NULL);
+
+       g_signal_handlers_disconnect_by_func
+               (data->icon_theme,
+                G_CALLBACK (ephy_spinner_cache_data_unload), data);
+
+       ephy_spinner_cache_data_unload (data);
+
+       g_free (data);
+}
+
+static EphySpinnerImages *
+ephy_spinner_cache_get_images (EphySpinnerCache *cache,
+                              GdkScreen *screen,
+                              GtkIconSize icon_size)
+{
+       EphySpinnerCachePrivate *priv = cache->priv;
+       EphySpinnerCacheData *data;
+       EphySpinnerImages *images;
+
+       LOG ("Getting animation images for screen %p at size %d", screen, icon_size);
+
+       g_return_val_if_fail (icon_size >= 0 && icon_size < LAST_ICON_SIZE, NULL);
+
+       /* Backward compat: "invalid" meant "native" size which doesn't exist anymore */
+       if (icon_size == GTK_ICON_SIZE_INVALID)
+       {
+               icon_size = GTK_ICON_SIZE_DIALOG;
+       }
+
+       data = g_hash_table_lookup (priv->hash, screen);
+       if (data == NULL)
+       {
+               data = ephy_spinner_cache_data_new (screen);
+               /* FIXME: think about what happens when the screen's display is closed later on */
+               g_hash_table_insert (priv->hash, screen, data);
+       }
+
+       images = data->images[icon_size];
+       if (images == EPHY_SPINNER_IMAGES_INVALID)
+       {
+               /* Load failed, but don't try endlessly again! */
+               return NULL;
+       }
+
+       if (images != NULL)
+       {
+               /* Return cached data */
+               return ephy_spinner_images_ref (images);
+       }
+
+       images = ephy_spinner_images_load (screen, data->icon_theme, icon_size);
+
+       if (images == NULL)
+       {
+               /* Mark as failed-to-load */
+               data->images[icon_size] = EPHY_SPINNER_IMAGES_INVALID;
+
+               return NULL;
+       }
+
+       data->images[icon_size] = images;
+
+       return ephy_spinner_images_ref (images);
+}
+
+static void
+ephy_spinner_cache_init (EphySpinnerCache *cache)
+{
+       EphySpinnerCachePrivate *priv;
+
+       priv = cache->priv = EPHY_SPINNER_CACHE_GET_PRIVATE (cache);
+
+       LOG ("EphySpinnerCache initialising");
+
+       priv->hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                           NULL,
+                                           (GDestroyNotify) ephy_spinner_cache_data_free);
+}
+
+static void
+ephy_spinner_cache_finalize (GObject *object)
+{
+       EphySpinnerCache *cache = EPHY_SPINNER_CACHE (object); 
+       EphySpinnerCachePrivate *priv = cache->priv;
+
+       g_hash_table_destroy (priv->hash);
+
+       LOG ("EphySpinnerCache finalised");
+
+       G_OBJECT_CLASS (ephy_spinner_cache_parent_class)->finalize (object);
+}
+
+static void
+ephy_spinner_cache_class_init (EphySpinnerCacheClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       ephy_spinner_cache_parent_class = g_type_class_peek_parent (klass);
+
+       object_class->finalize = ephy_spinner_cache_finalize;
+
+       g_type_class_add_private (object_class, sizeof (EphySpinnerCachePrivate));
+}
+
+static EphySpinnerCache *spinner_cache = NULL;
+
+static EphySpinnerCache *
+ephy_spinner_cache_ref (void)
+{
+       if (spinner_cache == NULL)
+       {
+               EphySpinnerCache **cache_ptr;
+
+               spinner_cache = g_object_new (EPHY_TYPE_SPINNER_CACHE, NULL);
+               cache_ptr = &spinner_cache;
+               g_object_add_weak_pointer (G_OBJECT (spinner_cache),
+                                          (gpointer *) cache_ptr);
+
+               return spinner_cache;
+       }
+               
+       return g_object_ref (spinner_cache);
+}
+
+/* Spinner implementation */
+
+#define SPINNER_TIMEOUT 125 /* ms */
+
+#define EPHY_SPINNER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SPINNER, EphySpinnerDetails))
+
+struct _EphySpinnerDetails
+{
+       GtkIconTheme *icon_theme;
+       EphySpinnerCache *cache;
+       GtkIconSize size;
+       EphySpinnerImages *images;
+       guint current_image;
+       guint timeout;
+       guint timer_task;
+       guint spinning : 1;
+       guint need_load : 1;
+};
+
+static void ephy_spinner_class_init (EphySpinnerClass *class);
+static void ephy_spinner_init      (EphySpinner *spinner);
+
+static GObjectClass *parent_class;
+
+GType
+ephy_spinner_get_type (void)
+{
+       static GType type = 0;
+
+       if (G_UNLIKELY (type == 0))
+       {
+               const GTypeInfo our_info =
+               {
+                       sizeof (EphySpinnerClass),
+                       NULL, /* base_init */
+                       NULL, /* base_finalize */
+                       (GClassInitFunc) ephy_spinner_class_init,
+                       NULL,
+                       NULL, /* class_data */
+                       sizeof (EphySpinner),
+                       0, /* n_preallocs */
+                       (GInstanceInitFunc) ephy_spinner_init
+               };
+
+               type = g_type_register_static (GTK_TYPE_WIDGET,
+                                              "EphySpinner",
+                                              &our_info, 0);
+       }
+
+       return type;
+}
+
+static gboolean
+ephy_spinner_load_images (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       if (details->need_load)
+       {
+               START_PROFILER ("ephy_spinner_load_images")
+
+               details->images =
+                       ephy_spinner_cache_get_images
+                               (details->cache,
+                                gtk_widget_get_screen (GTK_WIDGET (spinner)),
+                                details->size);
+
+               STOP_PROFILER ("ephy_spinner_load_images")
+
+               details->current_image = 0; /* 'rest' icon */
+               details->need_load = FALSE;
+       }
+
+       return details->images != NULL;
+}
+
+static void
+ephy_spinner_unload_images (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       if (details->images != NULL)
+       {
+               ephy_spinner_images_unref (details->images);
+               details->images = NULL;
+       }
+
+       details->current_image = 0;
+       details->need_load = TRUE;
+}
+
+static void
+icon_theme_changed_cb (GtkIconTheme *icon_theme,
+                      EphySpinner *spinner)
+{
+       ephy_spinner_unload_images (spinner);
+       gtk_widget_queue_resize (GTK_WIDGET (spinner));
+}
+
+static void
+ephy_spinner_init (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details;
+
+       details = spinner->details = EPHY_SPINNER_GET_PRIVATE (spinner);
+
+       GTK_WIDGET_SET_FLAGS (GTK_WIDGET (spinner), GTK_NO_WINDOW);
+
+       details->cache = ephy_spinner_cache_ref ();
+       details->size = GTK_ICON_SIZE_DIALOG;
+       details->spinning = FALSE;
+       details->timeout = SPINNER_TIMEOUT;
+       details->need_load = TRUE;
+}
+
+static int
+ephy_spinner_expose (GtkWidget *widget,
+                    GdkEventExpose *event)
+{
+       EphySpinner *spinner = EPHY_SPINNER (widget);
+       EphySpinnerDetails *details = spinner->details;
+       EphySpinnerImages *images;
+       GdkPixbuf *pixbuf;
+       GdkGC *gc;
+       int x_offset, y_offset, width, height;
+       GdkRectangle pix_area, dest;
+
+       if (!GTK_WIDGET_DRAWABLE (spinner))
+       {
+               return FALSE;
+       }
+
+       if (details->need_load &&
+           !ephy_spinner_load_images (spinner))
+       {
+               return FALSE;
+       }
+
+       images = details->images;
+       if (images == NULL)
+       {
+               return FALSE;
+       }
+
+       /* Otherwise |images| will be NULL anyway */
+       g_assert (images->n_animation_pixbufs > 0);
+               
+       g_assert (details->current_image >= 0 &&
+                 details->current_image < images->n_animation_pixbufs);
+
+       pixbuf = images->animation_pixbufs[details->current_image];
+
+       g_assert (pixbuf != NULL);
+
+       width = gdk_pixbuf_get_width (pixbuf);
+       height = gdk_pixbuf_get_height (pixbuf);
+
+       /* Compute the offsets for the image centered on our allocation */
+       x_offset = (widget->allocation.width - width) / 2;
+       y_offset = (widget->allocation.height - height) / 2;
+
+       pix_area.x = x_offset + widget->allocation.x;
+       pix_area.y = y_offset + widget->allocation.y;
+       pix_area.width = width;
+       pix_area.height = height;
+
+       if (!gdk_rectangle_intersect (&event->area, &pix_area, &dest))
+       {
+               return FALSE;
+       }
+
+       gc = gdk_gc_new (widget->window);
+       gdk_draw_pixbuf (widget->window, gc, pixbuf,
+                        dest.x - x_offset - widget->allocation.x,
+                        dest.y - y_offset - widget->allocation.y,
+                        dest.x, dest.y,
+                        dest.width, dest.height,
+                        GDK_RGB_DITHER_MAX, 0, 0);
+       g_object_unref (gc);
+
+       return FALSE;
+}
+
+static gboolean
+bump_spinner_frame_cb (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       /* This can happen when we've unloaded the images on a theme
+        * change, but haven't been in the queued size request yet.
+        * Just skip this update.
+        */
+       if (details->images == NULL) return TRUE;
+
+       details->current_image++;
+       if (details->current_image >= details->images->n_animation_pixbufs)
+       {
+               /* the 0th frame is the 'rest' icon */
+               details->current_image = MIN (1, details->images->n_animation_pixbufs);
+       }
+
+       gtk_widget_queue_draw (GTK_WIDGET (spinner));
+
+       /* run again */
+       return TRUE;
+}
+
+/**
+ * ephy_spinner_start:
+ * @spinner: a #EphySpinner
+ *
+ * Start the spinner animation.
+ **/
+void
+ephy_spinner_start (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       details->spinning = TRUE;
+
+       if (GTK_WIDGET_MAPPED (GTK_WIDGET (spinner)) &&
+           details->timer_task == 0 &&
+           ephy_spinner_load_images (spinner))
+       {
+               /* the 0th frame is the 'rest' icon */
+               details->current_image = MIN (1, details->images->n_animation_pixbufs);
+
+               details->timer_task =
+                       g_timeout_add_full (G_PRIORITY_LOW,
+                                           details->timeout,
+                                           (GSourceFunc) bump_spinner_frame_cb,
+                                           spinner,
+                                           NULL);
+       }
+}
+
+static void
+ephy_spinner_remove_update_callback (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       if (details->timer_task != 0)
+       {
+               g_source_remove (details->timer_task);
+               details->timer_task = 0;
+       }
+}
+
+/**
+ * ephy_spinner_stop:
+ * @spinner: a #EphySpinner
+ *
+ * Stop the spinner animation.
+ **/
+void
+ephy_spinner_stop (EphySpinner *spinner)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       details->spinning = FALSE;
+       details->current_image = 0;
+
+       if (details->timer_task != 0)
+       {
+               ephy_spinner_remove_update_callback (spinner);
+
+               if (GTK_WIDGET_MAPPED (GTK_WIDGET (spinner)))
+               {
+                       gtk_widget_queue_draw (GTK_WIDGET (spinner));
+               }
+       }
+}
+
+/*
+ * ephy_spinner_set_size:
+ * @spinner: a #EphySpinner
+ * @size: the size of type %GtkIconSize
+ *
+ * Set the size of the spinner.
+ **/
+void
+ephy_spinner_set_size (EphySpinner *spinner,
+                      GtkIconSize size)
+{
+       if (size == GTK_ICON_SIZE_INVALID)
+       {
+               size = GTK_ICON_SIZE_DIALOG;
+       }
+
+       if (size != spinner->details->size)
+       {
+               ephy_spinner_unload_images (spinner);
+
+               spinner->details->size = size;
+
+               gtk_widget_queue_resize (GTK_WIDGET (spinner));
+       }
+}
+
+#if 0
+/*
+ * ephy_spinner_set_timeout:
+ * @spinner: a #EphySpinner
+ * @timeout: time delay between updates to the spinner.
+ *
+ * Sets the timeout delay for spinner updates.
+ **/
+void
+ephy_spinner_set_timeout (EphySpinner *spinner,
+                         guint timeout)
+{
+       EphySpinnerDetails *details = spinner->details;
+
+       if (timeout != details->timeout)
+       {
+               ephy_spinner_stop (spinner);
+
+               details->timeout = timeout;
+
+               if (details->spinning)
+               {
+                       ephy_spinner_start (spinner);
+               }
+       }
+}
+#endif
+
+static void
+ephy_spinner_size_request (GtkWidget *widget,
+                          GtkRequisition *requisition)
+{
+       EphySpinner *spinner = EPHY_SPINNER (widget);
+       EphySpinnerDetails *details = spinner->details;
+
+       if ((details->need_load &&
+            !ephy_spinner_load_images (spinner)) ||
+            details->images == NULL)
+       {
+               requisition->width = requisition->height = 0;
+               gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
+                                                  details->size,
+                                                  &requisition->width,
+                                                  &requisition->height);
+               return;
+       }
+
+       requisition->width = details->images->width;
+       requisition->height = details->images->height;
+
+       /* FIXME fix this hack */
+       /* allocate some extra margin so we don't butt up against toolbar edges */
+       if (details->size != GTK_ICON_SIZE_MENU)
+       {
+               requisition->width += 2;
+               requisition->height += 2;
+       }
+}
+
+static void
+ephy_spinner_map (GtkWidget *widget)
+{
+       EphySpinner *spinner = EPHY_SPINNER (widget);
+       EphySpinnerDetails *details = spinner->details;
+
+       GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+       if (details->spinning)
+       {
+               ephy_spinner_start (spinner);
+       }
+}
+
+static void
+ephy_spinner_unmap (GtkWidget *widget)
+{
+       EphySpinner *spinner = EPHY_SPINNER (widget);
+
+       ephy_spinner_remove_update_callback (spinner);
+
+       GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+}
+
+static void
+ephy_spinner_dispose (GObject *object)
+{
+       EphySpinner *spinner = EPHY_SPINNER (object);
+
+       g_signal_handlers_disconnect_by_func
+                       (spinner->details->icon_theme,
+                G_CALLBACK (icon_theme_changed_cb), spinner);
+
+       G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+ephy_spinner_finalize (GObject *object)
+{
+       EphySpinner *spinner = EPHY_SPINNER (object);
+
+       ephy_spinner_remove_update_callback (spinner);
+       ephy_spinner_unload_images (spinner);
+
+       g_object_unref (spinner->details->cache);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+ephy_spinner_screen_changed (GtkWidget *widget,
+                            GdkScreen *old_screen)
+{
+       EphySpinner *spinner = EPHY_SPINNER (widget);
+       EphySpinnerDetails *details = spinner->details;
+       GdkScreen *screen;
+
+       if (GTK_WIDGET_CLASS (parent_class)->screen_changed)
+       {
+               GTK_WIDGET_CLASS (parent_class)->screen_changed (widget, old_screen);
+       }
+
+       screen = gtk_widget_get_screen (widget);
+
+       /* FIXME: this seems to be happening when then spinner is destroyed!? */
+       if (old_screen == screen) return;
+
+       /* We'll get mapped again on the new screen, but not unmapped from
+        * the old screen, so remove timeout here.
+        */
+       ephy_spinner_remove_update_callback (spinner);
+
+       ephy_spinner_unload_images (spinner);
+
+       if (old_screen != NULL)
+       {
+               g_signal_handlers_disconnect_by_func
+                       (gtk_icon_theme_get_for_screen (old_screen),
+                        G_CALLBACK (icon_theme_changed_cb), spinner);
+       }
+
+       details->icon_theme = gtk_icon_theme_get_for_screen (screen);
+       g_signal_connect (details->icon_theme, "changed",
+                         G_CALLBACK (icon_theme_changed_cb), spinner);
+}
+
+static void
+ephy_spinner_class_init (EphySpinnerClass *class)
+{
+       GObjectClass *object_class =  G_OBJECT_CLASS (class);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+       parent_class = g_type_class_peek_parent (class);
+
+       object_class->dispose = ephy_spinner_dispose;
+       object_class->finalize = ephy_spinner_finalize;
+
+       widget_class->expose_event = ephy_spinner_expose;
+       widget_class->size_request = ephy_spinner_size_request;
+       widget_class->map = ephy_spinner_map;
+       widget_class->unmap = ephy_spinner_unmap;
+       widget_class->screen_changed = ephy_spinner_screen_changed;
+
+       g_type_class_add_private (object_class, sizeof (EphySpinnerDetails));
+}
+
+/*
+ * ephy_spinner_new:
+ *
+ * Create a new #EphySpinner. The spinner is a widget
+ * that gives the user feedback about network status with
+ * an animated image.
+ *
+ * Return Value: the spinner #GtkWidget
+ **/
+GtkWidget *
+ephy_spinner_new (void)
+{
+       return GTK_WIDGET (g_object_new (EPHY_TYPE_SPINNER, NULL));
+}
diff --git a/src/ephy-spinner.h b/src/ephy-spinner.h
new file mode 100644 (file)
index 0000000..4435fe3
--- /dev/null
@@ -0,0 +1,70 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Copyright © 2000 Eazel, Inc.
+ * Copyright © 2004, 2006 Christian Persch
+ *
+ * Nautilus is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Andy Hertzfeld <andy@eazel.com>
+ *
+ * $Id: ephy-spinner.h 2114 2006-12-25 12:15:00Z mr $
+ */
+
+#ifndef EPHY_SPINNER_H
+#define EPHY_SPINNER_H
+
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkenums.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SPINNER              (ephy_spinner_get_type ())
+#define EPHY_SPINNER(o)                        (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_SPINNER, EphySpinner))
+#define EPHY_SPINNER_CLASS(k)          (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_SPINNER, EphySpinnerClass))
+#define EPHY_IS_SPINNER(o)             (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_SPINNER))
+#define EPHY_IS_SPINNER_CLASS(k)       (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_SPINNER))
+#define EPHY_SPINNER_GET_CLASS(o)      (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_SPINNER, EphySpinnerClass))
+
+typedef struct _EphySpinner            EphySpinner;
+typedef struct _EphySpinnerClass       EphySpinnerClass;
+typedef struct _EphySpinnerDetails     EphySpinnerDetails;
+
+struct _EphySpinner
+{
+       GtkWidget parent;
+
+       /*< private >*/
+       EphySpinnerDetails *details;
+};
+
+struct _EphySpinnerClass
+{
+       GtkWidgetClass parent_class;
+};
+
+GType          ephy_spinner_get_type   (void);
+
+GtkWidget      *ephy_spinner_new       (void);
+
+void           ephy_spinner_start      (EphySpinner *throbber);
+
+void           ephy_spinner_stop       (EphySpinner *throbber);
+
+void           ephy_spinner_set_size   (EphySpinner *spinner,
+                                        GtkIconSize size);
+
+G_END_DECLS
+
+#endif /* EPHY_SPINNER_H */