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 =\
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 = \
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 \
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
+++ /dev/null
-/* -*- 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);
-}
-
-
+++ /dev/null
-/* -*- 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__ */
#include "empathy-avatar-chooser.h"
#include "empathy-conf.h"
-#include "empathy-preferences.h"
#include "empathy-ui-utils.h"
#define DEBUG_DOMAIN "AvatarChooser"
+++ /dev/null
-/*
- * 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 (¤t);
-
- 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;
-}
-
+++ /dev/null
-<?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>
+++ /dev/null
-/*
- * 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__ */
#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"
+++ /dev/null
-/* -*- 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;
-}
-
+++ /dev/null
-/* -*- 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__ */
#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"
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;
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 = >K_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 = >K_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;
}
}
typedef struct {
- GtkWidget *window;
+ GtkWindow *window;
gint width;
gint height;
} ChangeSizeData;
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;
}
{
EmpathyChatPriv *priv;
gint width;
- GtkWidget *dialog;
+ GtkWindow *dialog;
ChangeSizeData *data;
gint window_height;
gint new_height;
view_allocation = >K_WIDGET (chat->view)->allocation;
- dialog = empathy_chat_window_get_dialog (priv->window);
- gtk_window_get_size (GTK_WINDOW (dialog), NULL, ¤t_height);
+ dialog = empathy_get_toplevel_window (priv->widget);
+ gtk_window_get_size (dialog, NULL, ¤t_height);
new_height = view_allocation->height + priv->padding_height + allocation->height - diff;
}
/* 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;
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
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)
{
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
typedef struct _EmpathyChatClass EmpathyChatClass;
typedef struct _EmpathyChatPriv EmpathyChatPriv;
-#include "empathy-chat-window.h"
-
struct _EmpathyChat {
GObject parent;
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);
+++ /dev/null
-/* -*- 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);
-}
-
+++ /dev/null
-<?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>
+++ /dev/null
-/* -*- 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__ */
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);
#include "empathy-images.h"
#include "empathy-ui-utils.h"
#include "empathy-conf.h"
-#include "empathy-preferences.h"
#define DEBUG_DOMAIN "GroupChat"
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);
}
}
+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,
}
}
-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)
{
+++ /dev/null
-/* -*- 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);
- }
- }
-}
-
+++ /dev/null
-<?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>
+++ /dev/null
-/* -*- 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__ */
+++ /dev/null
-/* -*- 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);
- }
-}
-
+++ /dev/null
-<?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>
+++ /dev/null
-/* -*- 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__ */
+++ /dev/null
-/* -*- 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;
-}
-
+++ /dev/null
-<?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"><b>Appearance</b></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"><b>Behaviour</b></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"><b>Contact List</b></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"><b>Audio</b></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"><b>Visual</b></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"><small>The list of languages reflects only the languages for which you have a dictionary installed.</small></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"><b>Enable spell checking for languages:</b></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"><b>Appearance</b></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"><b>Options</b></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>
+++ /dev/null
-/* -*- 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__ */
-
-
#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"
#include "empathy-spell.h"
#include "empathy-conf.h"
-#include "empathy-preferences.h"
#define DEBUG_DOMAIN "Spell"
+++ /dev/null
-/* -*- 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);
-}
-
+++ /dev/null
-<?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>
+++ /dev/null
-/* -*- 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__ */
#include <libempathy/empathy-debug.h>
#include "empathy-ui-utils.h"
-#include "empathy-main-window.h"
#include "empathy-theme-boxes.h"
#define DEBUG_DOMAIN "FancyTheme"
#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"
#include "empathy-chat.h"
#include "empathy-conf.h"
-#include "empathy-preferences.h"
#include "empathy-theme.h"
#include "empathy-smiley-manager.h"
+++ /dev/null
-/*
- * 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));
-}
+++ /dev/null
-/* -*- 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 */
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
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
--- /dev/null
+/* -*- 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);
+}
+
+
--- /dev/null
+/* -*- 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__ */
--- /dev/null
+/*
+ * 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 (¤t);
+
+ 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;
+}
+
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/* -*- 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);
+}
+
--- /dev/null
+/* -*- 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__ */
--- /dev/null
+/* -*- 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);
+}
+
--- /dev/null
+<?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>
--- /dev/null
+/* -*- 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__ */
--- /dev/null
+/* -*- 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);
+ }
+ }
+}
+
--- /dev/null
+<?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>
--- /dev/null
+/* -*- 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__ */
--- /dev/null
+/* -*- 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);
+ }
+}
+
--- /dev/null
+<?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>
--- /dev/null
+/* -*- 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__ */
--- /dev/null
+/* -*- 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;
+}
+
--- /dev/null
+<?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"><b>Appearance</b></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"><b>Behaviour</b></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"><b>Contact List</b></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"><b>Audio</b></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"><b>Visual</b></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"><small>The list of languages reflects only the languages for which you have a dictionary installed.</small></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"><b>Enable spell checking for languages:</b></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"><b>Appearance</b></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"><b>Options</b></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>
--- /dev/null
+/* -*- 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__ */
+
+
--- /dev/null
+/* -*- 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);
+}
+
--- /dev/null
+<?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>
--- /dev/null
+/* -*- 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__ */
#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"
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;
return;
}
- empathy_chat_present (chat);
+ empathy_chat_window_present_chat (chat);
g_object_unref (chat);
g_object_unref (account);
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+/* -*- 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 */