45
44
#include <telepathy-glib/connection-manager.h>
46
45
#include <telepathy-glib/interfaces.h>
48
#include <telepathy-yell/telepathy-yell.h>
50
47
#include <telepathy-logger/log-manager.h>
52
#include <libempathy/empathy-idle.h>
49
#include <libempathy/empathy-presence-manager.h>
53
50
#include <libempathy/empathy-utils.h>
54
51
#include <libempathy/empathy-chatroom-manager.h>
55
52
#include <libempathy/empathy-account-settings.h>
56
53
#include <libempathy/empathy-connectivity.h>
57
54
#include <libempathy/empathy-connection-managers.h>
58
#include <libempathy/empathy-dispatcher.h>
55
#include <libempathy/empathy-request-util.h>
59
56
#include <libempathy/empathy-ft-factory.h>
60
57
#include <libempathy/empathy-gsettings.h>
61
58
#include <libempathy/empathy-tp-chat.h>
63
60
#include <libempathy-gtk/empathy-ui-utils.h>
64
61
#include <libempathy-gtk/empathy-location-manager.h>
65
#include <libempathy-gtk/empathy-theme-manager.h>
67
63
#include "empathy-main-window.h"
68
64
#include "empathy-accounts-common.h"
69
65
#include "empathy-accounts-dialog.h"
70
#include "empathy-chat-manager.h"
71
66
#include "empathy-status-icon.h"
72
67
#include "empathy-ft-manager.h"
68
#include "empathy-notifications-approver.h"
74
70
#include "extensions/extensions.h"
76
72
#define DEBUG_FLAG EMPATHY_DEBUG_OTHER
77
73
#include <libempathy/empathy-debug.h>
79
static gboolean start_hidden = FALSE;
80
static gboolean no_connect = FALSE;
75
#define EMPATHY_DBUS_NAME "org.gnome.Empathy"
77
#define EMPATHY_TYPE_APP (empathy_app_get_type ())
78
#define EMPATHY_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_APP, EmpathyApp))
79
#define EMPATHY_APP_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), EMPATHY_TYPE_APP, EmpathyAppClass))
80
#define EMPATHY_IS_EMPATHY_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_APP))
81
#define EMPATHY_IS_EMPATHY_APP_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), EMPATHY_TYPE_APP))
82
#define EMPATHY_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_APP, EmpathyAppClass))
84
typedef struct _EmpathyApp EmpathyApp;
85
typedef struct _EmpathyAppClass EmpathyAppClass;
93
GType empathy_app_get_type (void);
95
struct _EmpathyAppClass
97
GtkApplicationClass parent_class;
102
GtkApplication parent;
106
gboolean start_hidden;
111
EmpathyStatusIcon *icon;
112
TpAccountManager *account_manager;
113
TplLogManager *log_manager;
114
EmpathyChatroomManager *chatroom_manager;
115
EmpathyFTFactory *ft_factory;
116
EmpathyPresenceManager *presence_mgr;
117
EmpathyConnectivity *connectivity;
118
GSettings *gsettings;
119
EmpathyNotificationsApprover *notifications_approver;
121
EmpathyLocationManager *location_manager;
124
TpDebugSender *debug_sender;
129
G_DEFINE_TYPE(EmpathyApp, empathy_app, GTK_TYPE_APPLICATION)
132
empathy_app_dispose (GObject *object)
134
EmpathyApp *self = EMPATHY_APP (object);
135
void (*dispose) (GObject *) =
136
G_OBJECT_CLASS (empathy_app_parent_class)->dispose;
138
if (self->presence_mgr != NULL)
140
empathy_presence_manager_set_state (self->presence_mgr,
141
TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
145
tp_clear_object (&self->debug_sender);
148
tp_clear_object (&self->presence_mgr);
149
tp_clear_object (&self->connectivity);
150
tp_clear_object (&self->icon);
151
tp_clear_object (&self->account_manager);
152
tp_clear_object (&self->log_manager);
153
tp_clear_object (&self->chatroom_manager);
155
tp_clear_object (&self->location_manager);
157
tp_clear_object (&self->ft_factory);
158
tp_clear_object (&self->gsettings);
159
tp_clear_object (&self->notifications_approver);
166
empathy_app_finalize (GObject *object)
168
EmpathyApp *self = EMPATHY_APP (object);
169
void (*finalize) (GObject *) =
170
G_OBJECT_CLASS (empathy_app_parent_class)->finalize;
172
if (self->window != NULL)
173
gtk_widget_destroy (self->window);
175
if (finalize != NULL)
82
179
static void account_manager_ready_cb (GObject *source_object,
83
180
GAsyncResult *result,
84
181
gpointer user_data);
184
empathy_app_set_property (GObject *object,
189
EmpathyApp *self = EMPATHY_APP (object);
193
case PROP_NO_CONNECT:
194
self->no_connect = g_value_get_boolean (value);
196
case PROP_START_HIDDEN:
197
self->start_hidden = g_value_get_boolean (value);
200
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
206
new_incoming_transfer_cb (EmpathyFTFactory *factory,
207
EmpathyFTHandler *handler,
212
empathy_ft_manager_display_error (handler, error);
214
empathy_receive_file_with_file_chooser (handler);
218
new_ft_handler_cb (EmpathyFTFactory *factory,
219
EmpathyFTHandler *handler,
224
empathy_ft_manager_display_error (handler, error);
226
empathy_ft_manager_add_handler (handler);
228
g_object_unref (handler);
232
empathy_app_command_line (GApplication *app,
233
GApplicationCommandLine *cmdline)
235
EmpathyApp *self = (EmpathyApp *) app;
237
if (!self->activated)
239
GError *error = NULL;
241
/* Create the FT factory */
242
self->ft_factory = empathy_ft_factory_dup_singleton ();
243
g_signal_connect (self->ft_factory, "new-ft-handler",
244
G_CALLBACK (new_ft_handler_cb), NULL);
245
g_signal_connect (self->ft_factory, "new-incoming-transfer",
246
G_CALLBACK (new_incoming_transfer_cb), NULL);
248
if (!empathy_ft_factory_register (self->ft_factory, &error))
250
g_warning ("Failed to register FileTransfer handler: %s",
252
g_error_free (error);
255
g_application_hold (G_APPLICATION (app));
256
self->activated = TRUE;
259
self->window = empathy_main_window_dup ();
260
gtk_widget_show (self->window);
261
self->icon = empathy_status_icon_new (GTK_WINDOW (self->window),
264
self->notifications_approver =
265
empathy_notifications_approver_dup_singleton ();
269
/* We're requested to show stuff again, disable the start hidden global in
270
* case the accounts wizard wants to pop up.
272
self->start_hidden = FALSE;
275
if (!self->start_hidden)
276
empathy_window_present (GTK_WINDOW (self->window));
278
/* Display the accounts dialog if needed */
279
tp_account_manager_prepare_async (self->account_manager, NULL,
280
account_manager_ready_cb, self);
286
show_version_cb (const char *option_name,
292
empathy_app_local_command_line (GApplication *app,
296
EmpathyApp *self = (EmpathyApp *) app;
300
gboolean retval = FALSE;
301
GError *error = NULL;
302
gboolean no_connect = FALSE, start_hidden = FALSE;
304
GOptionContext *optcontext;
305
GOptionEntry options[] = {
307
0, G_OPTION_ARG_NONE, &no_connect,
308
N_("Don't connect on startup"),
310
{ "start-hidden", 'h',
311
0, G_OPTION_ARG_NONE, &start_hidden,
312
N_("Don't display the contact list or any other dialogs on startup"),
315
G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb,
320
optcontext = g_option_context_new (N_("- Empathy IM Client"));
321
g_option_context_add_group (optcontext, gtk_get_option_group (TRUE));
322
g_option_context_add_main_entries (optcontext, options, GETTEXT_PACKAGE);
325
for (i = 0; argv[i] != NULL; i++)
328
if (!g_option_context_parse (optcontext, &argc, &argv, &error))
330
g_print ("%s\nRun '%s --help' to see a full list of available command "
332
error->message, argv[0]);
333
g_warning ("Error in empathy init: %s", error->message);
335
*exit_status = EXIT_FAILURE;
339
g_option_context_free (optcontext);
341
self->no_connect = no_connect;
342
self->start_hidden = start_hidden;
347
static void empathy_app_constructed (GObject *object);
350
empathy_app_class_init (EmpathyAppClass *klass)
352
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
353
GApplicationClass *g_app_class = G_APPLICATION_CLASS (klass);
356
gobject_class->set_property = empathy_app_set_property;
357
gobject_class->constructed = empathy_app_constructed;
358
gobject_class->dispose = empathy_app_dispose;
359
gobject_class->finalize = empathy_app_finalize;
361
g_app_class->command_line = empathy_app_command_line;
362
g_app_class->local_command_line = empathy_app_local_command_line;
364
spec = g_param_spec_boolean ("no-connect", "no connect",
365
"Don't connect on startup",
367
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
368
g_object_class_install_property (gobject_class, PROP_NO_CONNECT, spec);
370
spec = g_param_spec_boolean ("start-hidden", "start hidden",
371
"Don't display the contact list or any other dialogs on startup",
373
G_PARAM_STATIC_STRINGS | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
374
g_object_class_install_property (gobject_class, PROP_START_HIDDEN, spec);
378
empathy_app_init (EmpathyApp *self)
87
383
use_conn_notify_cb (GSettings *gsettings,
89
385
gpointer user_data)
166
show_accounts_ui (GdkScreen *screen,
462
show_accounts_ui (EmpathyApp *self,
167
464
gboolean if_needed)
169
466
empathy_accounts_dialog_show_application (screen,
170
NULL, if_needed, start_hidden);
173
static UniqueResponse
174
unique_app_message_cb (UniqueApp *unique_app,
176
UniqueMessageData *data,
180
GtkWindow *window = user_data;
181
TpAccountManager *account_manager;
183
DEBUG ("Other instance launched, presenting the main window. "
184
"Command=%d, timestamp %u", command, timestamp);
186
/* XXX: the standalone app somewhat breaks this case, since
187
* communicating it would be a pain */
189
/* We're requested to show stuff again, disable the start hidden global
190
* in case the accounts wizard wants to pop up.
192
start_hidden = FALSE;
194
gtk_window_set_screen (GTK_WINDOW (window),
195
unique_message_data_get_screen (data));
196
gtk_window_set_startup_id (GTK_WINDOW (window),
197
unique_message_data_get_startup_id (data));
198
gtk_window_present_with_time (GTK_WINDOW (window), timestamp);
199
gtk_window_set_skip_taskbar_hint (window, FALSE);
201
account_manager = tp_account_manager_dup ();
202
tp_account_manager_prepare_async (account_manager, NULL,
203
account_manager_ready_cb, NULL);
204
g_object_unref (account_manager);
206
return UNIQUE_RESPONSE_OK;
209
static gboolean show_version_cb (const char *option_name,
212
GError **error) G_GNUC_NORETURN;
467
NULL, if_needed, self->start_hidden);
215
471
show_version_cb (const char *option_name,
226
new_incoming_transfer_cb (EmpathyFTFactory *factory,
227
EmpathyFTHandler *handler,
232
empathy_ft_manager_display_error (handler, error);
234
empathy_receive_file_with_file_chooser (handler);
238
new_ft_handler_cb (EmpathyFTFactory *factory,
239
EmpathyFTHandler *handler,
244
empathy_ft_manager_display_error (handler, error);
246
empathy_ft_manager_add_handler (handler);
248
g_object_unref (handler);
252
482
account_manager_ready_cb (GObject *source_object,
253
483
GAsyncResult *result,
254
484
gpointer user_data)
256
486
TpAccountManager *manager = TP_ACCOUNT_MANAGER (source_object);
487
EmpathyApp *self = user_data;
257
488
GError *error = NULL;
259
EmpathyConnectivity *connectivity;
260
489
TpConnectionPresenceType presence;
261
GSettings *gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
263
491
if (!tp_account_manager_prepare_finish (manager, result, &error))
265
495
DEBUG ("Failed to prepare account manager: %s", error->message);
497
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
498
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
499
_("Error contacting the Account Manager"));
500
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
501
_("There was an error while trying to connect to the Telepathy "
502
"Account Manager. The error was:\n\n%s"),
505
gtk_dialog_run (GTK_DIALOG (dialog));
506
gtk_widget_destroy (dialog);
266
508
g_error_free (error);
270
512
/* Autoconnect */
271
idle = empathy_idle_dup_singleton ();
272
connectivity = empathy_connectivity_dup_singleton ();
274
513
presence = tp_account_manager_get_most_available_presence (manager, NULL,
277
if (g_settings_get_boolean (gsettings, EMPATHY_PREFS_AUTOCONNECT) &&
516
if (g_settings_get_boolean (self->gsettings, EMPATHY_PREFS_AUTOCONNECT) &&
279
518
tp_connection_presence_type_cmp_availability
280
519
(presence, TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
282
521
/* if current state is Offline, then put it online */
283
empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
522
empathy_presence_manager_set_state (self->presence_mgr,
523
TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
285
525
/* Pop up the accounts dialog if we don't have any account */
286
526
if (!empathy_accounts_has_accounts (manager))
287
show_accounts_ui (gdk_screen_get_default (), TRUE);
289
g_object_unref (idle);
290
g_object_unref (connectivity);
291
g_object_unref (gsettings);
527
show_accounts_ui (self, gdk_screen_get_default (), TRUE);
385
empathy_idle_set_auto_away_cb (GSettings *gsettings,
618
empathy_presence_manager_set_auto_away_cb (GSettings *gsettings,
386
619
const gchar *key,
387
620
gpointer user_data)
389
EmpathyIdle *idle = user_data;
622
EmpathyPresenceManager *presence_mgr = user_data;
391
empathy_idle_set_auto_away (idle,
624
empathy_presence_manager_set_auto_away (presence_mgr,
392
625
g_settings_get_boolean (gsettings, key));
396
main (int argc, char *argv[])
629
empathy_app_constructed (GObject *object)
399
EmpathyLocationManager *location_manager = NULL;
401
EmpathyStatusIcon *icon;
402
EmpathyDispatcher *dispatcher;
403
TpAccountManager *account_manager;
404
TplLogManager *log_manager;
405
EmpathyChatroomManager *chatroom_manager;
406
EmpathyFTFactory *ft_factory;
409
EmpathyConnectivity *connectivity;
410
EmpathyChatManager *chat_manager;
411
GError *error = NULL;
412
UniqueApp *unique_app;
631
EmpathyApp *self = (EmpathyApp *) object;
413
632
gboolean chatroom_manager_ready;
414
gboolean autoaway = TRUE;
416
TpDebugSender *debug_sender;
418
GSettings *gsettings;
419
EmpathyThemeManager *theme_mgr;
421
GOptionContext *optcontext;
422
GOptionEntry options[] = {
424
0, G_OPTION_ARG_NONE, &no_connect,
425
N_("Don't connect on startup"),
427
{ "start-hidden", 'h',
428
0, G_OPTION_ARG_NONE, &start_hidden,
429
N_("Don't display the contact list or any other dialogs on startup"),
432
G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb,
438
g_thread_init (NULL);
440
#ifdef HAVE_LIBCHAMPLAIN
441
gtk_clutter_init (&argc, &argv);
448
optcontext = g_option_context_new (N_("- Empathy IM Client"));
449
g_option_context_add_group (optcontext, gtk_get_option_group (TRUE));
450
g_option_context_add_main_entries (optcontext, options, GETTEXT_PACKAGE);
452
if (!g_option_context_parse (optcontext, &argc, &argv, &error)) {
453
g_print ("%s\nRun '%s --help' to see a full list of available command line options.\n",
454
error->message, argv[0]);
455
g_warning ("Error in empathy init: %s", error->message);
459
g_option_context_free (optcontext);
462
635
g_set_application_name (_(PACKAGE_NAME));
464
637
gtk_window_set_default_icon_name ("empathy");
467
640
#ifdef ENABLE_DEBUG
468
641
/* Set up debug sender */
469
debug_sender = tp_debug_sender_dup ();
642
self->debug_sender = tp_debug_sender_dup ();
470
643
g_log_set_default_handler (tp_debug_sender_log_handler, G_LOG_DOMAIN);
473
unique_app = unique_app_new ("org.gnome."PACKAGE_NAME, NULL);
475
if (unique_app_is_running (unique_app))
477
if (unique_app_send_message (unique_app, UNIQUE_ACTIVATE, NULL) ==
480
g_object_unref (unique_app);
485
646
notify_init (_(PACKAGE_NAME));
487
648
/* Setting up Idle */
488
idle = empathy_idle_dup_singleton ();
490
gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
491
autoaway = g_settings_get_boolean (gsettings, EMPATHY_PREFS_AUTOAWAY);
493
g_signal_connect (gsettings,
649
self->presence_mgr = empathy_presence_manager_dup_singleton ();
651
self->gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
652
autoaway = g_settings_get_boolean (self->gsettings, EMPATHY_PREFS_AUTOAWAY);
654
g_signal_connect (self->gsettings,
494
655
"changed::" EMPATHY_PREFS_AUTOAWAY,
495
G_CALLBACK (empathy_idle_set_auto_away_cb), idle);
656
G_CALLBACK (empathy_presence_manager_set_auto_away_cb),
497
empathy_idle_set_auto_away (idle, autoaway);
659
empathy_presence_manager_set_auto_away (self->presence_mgr, autoaway);
499
661
/* Setting up Connectivity */
500
connectivity = empathy_connectivity_dup_singleton ();
501
use_conn_notify_cb (gsettings, EMPATHY_PREFS_USE_CONN,
503
g_signal_connect (gsettings,
662
self->connectivity = empathy_connectivity_dup_singleton ();
663
use_conn_notify_cb (self->gsettings, EMPATHY_PREFS_USE_CONN,
665
g_signal_connect (self->gsettings,
504
666
"changed::" EMPATHY_PREFS_USE_CONN,
505
G_CALLBACK (use_conn_notify_cb), connectivity);
667
G_CALLBACK (use_conn_notify_cb), self->connectivity);
507
669
/* account management */
508
account_manager = tp_account_manager_dup ();
509
tp_account_manager_prepare_async (account_manager, NULL,
510
account_manager_ready_cb, NULL);
512
/* The EmpathyDispatcher doesn't dispatch anything any more but we have to
513
* keep it around as we still use it to request channels */
514
dispatcher = empathy_dispatcher_dup_singleton ();
670
self->account_manager = tp_account_manager_dup ();
671
tp_account_manager_prepare_async (self->account_manager, NULL,
672
account_manager_ready_cb, self);
516
674
migrate_config_to_xdg_dir ();
519
window = empathy_main_window_dup ();
520
gtk_widget_show (window);
521
icon = empathy_status_icon_new (GTK_WINDOW (window), start_hidden);
524
chat_manager = empathy_chat_manager_dup_singleton ();
526
g_signal_connect (unique_app, "message-received",
527
G_CALLBACK (unique_app_message_cb), window);
530
log_manager = tpl_log_manager_dup_singleton ();
532
chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
534
g_object_get (chatroom_manager, "ready", &chatroom_manager_ready, NULL);
677
self->log_manager = tpl_log_manager_dup_singleton ();
679
self->chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL);
681
g_object_get (self->chatroom_manager, "ready", &chatroom_manager_ready, NULL);
535
682
if (!chatroom_manager_ready)
537
g_signal_connect (G_OBJECT (chatroom_manager), "notify::ready",
538
G_CALLBACK (chatroom_manager_ready_cb), account_manager);
684
g_signal_connect (G_OBJECT (self->chatroom_manager), "notify::ready",
685
G_CALLBACK (chatroom_manager_ready_cb), self->account_manager);
542
chatroom_manager_ready_cb (chatroom_manager, NULL, account_manager);
545
/* Create the FT factory */
546
ft_factory = empathy_ft_factory_dup_singleton ();
547
g_signal_connect (ft_factory, "new-ft-handler",
548
G_CALLBACK (new_ft_handler_cb), NULL);
549
g_signal_connect (ft_factory, "new-incoming-transfer",
550
G_CALLBACK (new_incoming_transfer_cb), NULL);
552
if (!empathy_ft_factory_register (ft_factory, &error))
554
g_warning ("Failed to register FileTransfer handler: %s", error->message);
555
g_error_free (error);
689
chatroom_manager_ready_cb (self->chatroom_manager, NULL,
690
self->account_manager);
558
693
/* Location mananger */
559
694
#ifdef HAVE_GEOCLUE
560
location_manager = empathy_location_manager_dup_singleton ();
563
/* Keep the theme manager alive as it does some caching */
564
theme_mgr = empathy_theme_manager_dup_singleton ();
568
empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE);
571
g_object_unref (debug_sender);
574
g_object_unref (chat_manager);
575
g_object_unref (idle);
576
g_object_unref (connectivity);
577
g_object_unref (icon);
578
g_object_unref (account_manager);
579
g_object_unref (log_manager);
580
g_object_unref (dispatcher);
581
g_object_unref (chatroom_manager);
583
g_object_unref (location_manager);
585
g_object_unref (ft_factory);
586
g_object_unref (unique_app);
587
g_object_unref (gsettings);
588
g_object_unref (theme_mgr);
589
gtk_widget_destroy (window);
695
self->location_manager = empathy_location_manager_dup_singleton ();
698
self->activated = FALSE;
699
self->ft_factory = NULL;
704
main (int argc, char *argv[])
709
g_thread_init (NULL);
712
#ifdef HAVE_LIBCHAMPLAIN
713
gtk_clutter_init (&argc, &argv);
717
gtk_init (&argc, &argv);
720
app = g_object_new (EMPATHY_TYPE_APP,
721
"application-id", EMPATHY_DBUS_NAME,
722
"flags", G_APPLICATION_HANDLES_COMMAND_LINE,
725
retval = g_application_run (G_APPLICATION (app), argc, argv);
591
727
notify_uninit ();
592
728
xmlCleanupParser ();
730
g_object_unref (app);