diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-08-25 18:18:05 +0800 |
---|---|---|
committer | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2009-08-25 18:35:05 +0800 |
commit | 2e6d8132394680ea42a3ebdc1daad33ff5e07b86 (patch) | |
tree | 0bf9179a649dad69089a44270fcf49514a9c80e4 | |
parent | 7cfb268c7d96f929646c5eb093e6f07aa8b1abea (diff) | |
parent | d7f82b00ea09c62be272ed2d0c98e9120a722ca9 (diff) | |
download | gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.gz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.bz2 gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.lz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.xz gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.tar.zst gsoc2013-empathy-2e6d8132394680ea42a3ebdc1daad33ff5e07b86.zip |
Merge branch 'mc5', fixes bug #590165
127 files changed, 11059 insertions, 5115 deletions
diff --git a/configure.ac b/configure.ac index bc0491cae..080fdffd4 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,6 @@ GTK_REQUIRED=2.16.0 GCONF_REQUIRED=1.2.0 LIBPANELAPPLET_REQUIRED=2.10.0 TELEPATHY_GLIB_REQUIRED=0.7.34 -MISSION_CONTROL_REQUIRED=4.61 ENCHANT_REQUIRED=1.2.0 ISO_CODES_REQUIRED=0.35 LIBNOTIFY_REQUIRED=0.4.4 @@ -40,6 +39,7 @@ LIBCHAMPLAIN_GTK_REQUIRED=0.3.6 CLUTTER_GTK_REQUIRED=0.10 GEOCLUE_REQUIRED=0.11 WEBKIT_REQUIRED=1.1.7 +KEYRING_REQUIRED=2.22 NETWORK_MANAGER_REQUIRED=0.7.0 # Use --enable-maintainer-mode to disabled deprecated symbols @@ -95,7 +95,6 @@ PKG_CHECK_MODULES(LIBEMPATHY, gio-unix-2.0 >= $GLIB_REQUIRED libxml-2.0 telepathy-glib >= $TELEPATHY_GLIB_REQUIRED - libmissioncontrol >= $MISSION_CONTROL_REQUIRED telepathy-farsight farsight2-0.10 gstreamer-0.10 @@ -111,7 +110,6 @@ PKG_CHECK_MODULES(LIBEMPATHYGTK, gtk+-2.0 >= $GTK_REQUIRED libcanberra-gtk >= $LIBCANBERRA_GTK_REQUIRED telepathy-glib >= $TELEPATHY_GLIB_REQUIRED - libmissioncontrol >= $MISSION_CONTROL_REQUIRED farsight2-0.10 gstreamer-0.10 gstreamer-interfaces-0.10 @@ -127,9 +125,10 @@ PKG_CHECK_MODULES(EMPATHY, libebook-1.2 dbus-glib-1 telepathy-glib >= $TELEPATHY_GLIB_REQUIRED - libmissioncontrol >= $MISSION_CONTROL_REQUIRED telepathy-farsight gstreamer-0.10 + unique-1.0 + gnome-keyring-1 >= $KEYRING_REQUIRED ]) PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED) @@ -341,7 +340,7 @@ if test "x$enable_megaphone" != "xno"; then glib-2.0 >= $GLIB_REQUIRED gtk+-2.0 >= $GTK_REQUIRED gconf-2.0 >= $GCONF_REQUIRED - libmissioncontrol >= $MISSION_CONTROL_REQUIRED + telepathy-glib >= $TELEPATHY_GLIB_REQUIRED ], have_megaphone="yes", have_megaphone="no") else have_megaphone=no @@ -368,7 +367,7 @@ if test "x$enable_nothere" != "xno"; then glib-2.0 >= $GLIB_REQUIRED gtk+-2.0 >= $GTK_REQUIRED gconf-2.0 >= $GCONF_REQUIRED - libmissioncontrol >= $MISSION_CONTROL_REQUIRED + telepathy-glib >= $TELEPATHY_GLIB_REQUIRED ], have_nothere="yes", have_nothere="no") else have_nothere=no @@ -419,7 +418,6 @@ if test "x$enable_python" != "xno"; then gobject-2.0 gconf-2.0 >= $GCONF_REQUIRED libxml-2.0 - libmissioncontrol >= $MISSION_CONTROL_REQUIRED gtk+-2.0 >= $GTK_REQUIRED gstreamer-0.10 gstreamer-interfaces-0.10 diff --git a/data/Makefile.am b/data/Makefile.am index 7391b409e..43c3bb66c 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,25 +1,5 @@ SUBDIRS = icons -profiledir = $(datadir)/mission-control/profiles -profile_DATA = \ - aim.profile \ - icq.profile \ - jabber.profile \ - salut.profile \ - yahoo.profile \ - gtalk.profile \ - irc.profile \ - msn.profile \ - msn-haze.profile \ - sofiasip.profile \ - ekiga.profile \ - fwd.profile \ - sipphone.profile \ - groupwise.profile \ - gadugadu.profile \ - qq.profile \ - sametime.profile - desktopdir = $(datadir)/applications desktop_in_files = empathy.desktop.in desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) @@ -50,7 +30,6 @@ htmldir = $(datadir)/empathy html_DATA = Template.html EXTRA_DIST = \ - $(profile_DATA) \ $(desktop_in_files) \ $(desktop_DATA) \ $(schemas_in_files) \ diff --git a/data/aim.profile b/data/aim.profile deleted file mode 100644 index ae7dbaecc..000000000 --- a/data/aim.profile +++ /dev/null @@ -1,10 +0,0 @@ -[Profile] -Manager=haze -Protocol=aim -IconName = im-aim -DisplayName=AIM -ConfigurationUI = aim -Capabilities = chat-p2p, supports-alias, supports-avatars, supports-roster -VCardDefault = 1 -VCardField = X-AIM -SupportedPresences = away,hidden,do-not-disturb diff --git a/data/ekiga.profile b/data/ekiga.profile deleted file mode 100644 index 1acc71044..000000000 --- a/data/ekiga.profile +++ /dev/null @@ -1,14 +0,0 @@ -[Profile] -Manager = sofiasip -Protocol = sip -DisplayName = Ekiga.net (SIP) -IconName = im-ekiga -ConfigurationUI = sofiasip -VCardDefault = 1 -VCardField = X-SIP -Capabilities = chat-p2p, voice-p2p, split-account, video-p2p -DefaultAccountDomain = ekiga.net -Default-priority = 1 -Default-stun-server = stun.ekiga.net -Default-discover-stun = false - diff --git a/data/empathy.schemas.in b/data/empathy.schemas.in index bb9068725..6aa7f8a5f 100644 --- a/data/empathy.schemas.in +++ b/data/empathy.schemas.in @@ -479,6 +479,20 @@ </schema> <schema> + <key>/schemas/apps/empathy/accounts/imported_mc4_accounts</key> + <applyto>/apps/empathy/accounts/imported_mc4_accounts</applyto> + <owner>empathy</owner> + <type>bool</type> + <default>false</default> + <locale name="C"> + <short>MC 4 accounts have been imported</short> + <long> + MC 4 accounts have been imported. + </long> + </locale> + </schema> + + <schema> <key>/schemas/apps/empathy/use_conn</key> <applyto>/apps/empathy/use_conn</applyto> <owner>empathy</owner> diff --git a/data/fwd.profile b/data/fwd.profile deleted file mode 100644 index af05b2cc3..000000000 --- a/data/fwd.profile +++ /dev/null @@ -1,15 +0,0 @@ -[Profile] -Manager = sofiasip -Protocol = sip -DisplayName = FreeWorldDialup (SIP) -IconName = im-sip -ConfigurationUI = sofiasip -VCardDefault = 1 -VCardField = X-SIP -Capabilities = chav-p2p, voice-p2p, split-account, video-p2p -DefaultAccountDomain = fwd.pulver.com -Default-priority = 1 -Default-proxy-address = fwd.pulver.com -Default-stun-server = stun.fwdnet.net -Default-discover-stun = false - diff --git a/data/gadugadu.profile b/data/gadugadu.profile deleted file mode 100644 index ca2f5b7a9..000000000 --- a/data/gadugadu.profile +++ /dev/null @@ -1,11 +0,0 @@ -[Profile] -Manager=haze -Protocol=gadugadu -DisplayName=Gadu Gadu -IconName = im-gadugadu -ConfigurationUI = gadugadu -Capabilities = chat-p2p, contact-search, supports-alias, supports-roster -VCardDefault = 1 -VCardField = X-GADUGADU -SupportedPresences = offline,available,away,hidden - diff --git a/data/groupwise.profile b/data/groupwise.profile deleted file mode 100644 index 3e47ec2fb..000000000 --- a/data/groupwise.profile +++ /dev/null @@ -1,11 +0,0 @@ -[Profile] -Manager=haze -Protocol=groupwise -IconName = im-nov -DisplayName=GroupWise -ConfigurationUI = groupwise -Capabilities = chat-p2p, supports-alias, supports-roster -VCardDefault = 1 -VCardField = X-Groupwise -SupportedPresences = away,hidden,do-not-disturb - diff --git a/data/gtalk.profile b/data/gtalk.profile deleted file mode 100644 index 21eadc031..000000000 --- a/data/gtalk.profile +++ /dev/null @@ -1,16 +0,0 @@ -[Profile] -Manager = gabble -Protocol = jabber -DisplayName = Google Talk -IconName = im-google-talk -ConfigurationUI = jabber -VCardDefault = 0 -VCardField = X-JABBER -Capabilities = chat-p2p, voice-p2p, split-account, chat-room, chat-room-list, supports-avatars, supports-alias, supports-roster -DefaultAccountDomain = gmail.com -Default-server = talk.google.com -Default-port = 5223 -Default-old-ssl = 1 -Default-ignore-ssl-errors = 1 -Default-fallback-conference-server = conference.jabber.org -SupportedPresences = away,extended-away,do-not-disturb diff --git a/data/icq.profile b/data/icq.profile deleted file mode 100644 index 0f4622e75..000000000 --- a/data/icq.profile +++ /dev/null @@ -1,11 +0,0 @@ -[Profile] -Manager=haze -Protocol=icq -IconName = im-icq -DisplayName=ICQ -ConfigurationUI = icq -Capabilities = chat-p2p, supports-alias, supports-avatars, supports-roster -VCardDefault = 1 -VCardField = X-ICQ -SupportedPresences = away,hidden,do-not-disturb - diff --git a/data/irc.profile b/data/irc.profile deleted file mode 100644 index 05bf5ed5a..000000000 --- a/data/irc.profile +++ /dev/null @@ -1,9 +0,0 @@ -[Profile] -Manager = idle -Protocol = irc -DisplayName = IRC -IconName = im-irc -ConfigurationUI = irc -VCardField = X-IRC -Capabilities = chat-p2p, chat-room, chat-room-list -SupportedPresences = away diff --git a/data/jabber.profile b/data/jabber.profile deleted file mode 100644 index c3cb57aff..000000000 --- a/data/jabber.profile +++ /dev/null @@ -1,12 +0,0 @@ -[Profile] -Manager = gabble -Protocol = jabber -DisplayName = Jabber -IconName = im-xmpp -ConfigurationUI = jabber -VCardDefault = 1 -VCardField = X-JABBER -Capabilities = chat-p2p, chat-room, chat-room-list, voice-p2p, contact-search, split-account, registration-ui, supports-avatars, supports-alias, supports-roster -DefaultAccountDomain = jabber.org -Default-fallback-conference-server = conference.jabber.org -SupportedPresences = away,extended-away,hidden,do-not-disturb diff --git a/data/msn-haze.profile b/data/msn-haze.profile deleted file mode 100644 index 196825202..000000000 --- a/data/msn-haze.profile +++ /dev/null @@ -1,13 +0,0 @@ -[Profile] -Manager=haze -Protocol=msn -DisplayName=MSN (Haze) -IconName = im-msn -ConfigurationUI = haze -SupportsInvisible = 0 -Capabilities = chat-p2p, split-account, supports-alias, supports-avatars, supports-roster -DefaultAccountDomain = hotmail.com -VCardDefault = 1 -VCardField = X-MSN -SupportedPresences = away,hidden,do-not-disturb - diff --git a/data/msn.profile b/data/msn.profile deleted file mode 100644 index 9bdd051ea..000000000 --- a/data/msn.profile +++ /dev/null @@ -1,13 +0,0 @@ -[Profile] -Manager=butterfly -Protocol=msn -DisplayName=MSN -IconName = im-msn -ConfigurationUI = msn -SupportsInvisible = 1 -Capabilities = chat-p2p, split-account, supports-avatars, supports-alias -DefaultAccountDomain = hotmail.com -VCardDefault = 1 -VCardField = X-MSN -SupportedPresences = offline,available,away,extended-away,hidden,do-not-disturb - diff --git a/data/qq.profile b/data/qq.profile deleted file mode 100644 index 9a52d2441..000000000 --- a/data/qq.profile +++ /dev/null @@ -1,11 +0,0 @@ -[Profile] -Manager=haze -Protocol=qq -DisplayName=QQ -IconName = im-qq -ConfigurationUI = qq -Capabilities = chat-p2p, chat-room, contact-search, supports-alias, supports-roster -VCardDefault = 1 -VCardField = X-QQ -SupportedPresences = offline,available,away,hidden - diff --git a/data/salut.profile b/data/salut.profile deleted file mode 100644 index acd483ccc..000000000 --- a/data/salut.profile +++ /dev/null @@ -1,9 +0,0 @@ -[Profile] -Manager = salut -Protocol = local-xmpp -DisplayName = Salut -IconName = im-local-xmpp -ConfigurationUI = local-xmpp -VCardField = X-LOCAL-XMPP -Capabilities = chat-p2p, contact-search, supports-alias, supports-roster -SupportedPresences = away,extended-away,hidden,do-not-disturb diff --git a/data/sametime.profile b/data/sametime.profile deleted file mode 100644 index aec798925..000000000 --- a/data/sametime.profile +++ /dev/null @@ -1,11 +0,0 @@ -[Profile] -Manager=haze -Protocol=sametime -IconName = im-meanwhile -DisplayName = Sametime -ConfigurationUI = sametime -Capabilities = chat-p2p, supports-alias, supports-roster -VCardDefault = 1 -VCardField = X-Sametime -SupportedPresences = away,hidden,do-not-disturb - diff --git a/data/sipphone.profile b/data/sipphone.profile deleted file mode 100644 index 4904a7481..000000000 --- a/data/sipphone.profile +++ /dev/null @@ -1,16 +0,0 @@ -[Profile] -Manager = sofiasip -Protocol = sip -DisplayName = Sipphone.com (SIP) -IconName = im-sip -ConfigurationUI = sofiasip -VCardDefault = 1 -VCardField = X-SIP -Capabilities = voice-p2p, split-account, video-p2p -DefaultAccountDomain = proxy01.sipphone.com -Default-priority = 1 -Default-stun-server = stun01.sipphone.com -Default-proxy = 198.65.166.131 -Default-discover-stun = false -Default-transport = udp - diff --git a/data/sofiasip.profile b/data/sofiasip.profile deleted file mode 100644 index e49f9a09d..000000000 --- a/data/sofiasip.profile +++ /dev/null @@ -1,10 +0,0 @@ -[Profile] -Manager = sofiasip -Protocol = sip -DisplayName = SIP -IconName = im-sip -ConfigurationUI = sofiasip -VCardDefault = 1 -VCardField = X-SIP -Capabilities = chat-p2p, voice-p2p, split-account - diff --git a/data/yahoo.profile b/data/yahoo.profile deleted file mode 100644 index f4173d1af..000000000 --- a/data/yahoo.profile +++ /dev/null @@ -1,11 +0,0 @@ -[Profile] -Manager=haze -Protocol=yahoo -DisplayName=Yahoo -IconName = im-yahoo -ConfigurationUI = yahoo -Capabilities = chat-p2p, supports-alias, supports-avatars, supports-roster -VCardDefault = 1 -VCardField = X-YAHOO -SupportedPresences = away,hidden,do-not-disturb - diff --git a/docs/libempathy-gtk/libempathy-gtk.types b/docs/libempathy-gtk/libempathy-gtk.types index ead69316b..e82fdc914 100644 --- a/docs/libempathy-gtk/libempathy-gtk.types +++ b/docs/libempathy-gtk/libempathy-gtk.types @@ -22,7 +22,7 @@ empathy_contact_widget_flags_get_type empathy_gst_video_src_channel_get_type empathy_sound_get_type empathy_presence_chooser_get_type -empathy_profile_chooser_get_type +empathy_protocol_chooser_get_type empathy_smiley_manager_get_type empathy_status_preset_dialog_get_type empathy_theme_adium_get_type diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index 4c80e9f98..70e11e412 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -53,7 +53,7 @@ libempathy_gtk_handwritten_source = \ empathy-log-window.c \ empathy-new-message-dialog.c \ empathy-presence-chooser.c \ - empathy-profile-chooser.c \ + empathy-protocol-chooser.c \ empathy-smiley-manager.c \ empathy-sound.c \ empathy-spell.c \ @@ -70,6 +70,7 @@ libempathy_gtk_la_SOURCES = \ # do not distribute generated files nodist_libempathy_gtk_la_SOURCES =\ + empathy-account-widget-private.h \ $(BUILT_SOURCES) libempathy_gtk_la_LIBADD = \ @@ -115,7 +116,7 @@ libempathy_gtk_headers = \ empathy-log-window.h \ empathy-new-message-dialog.h \ empathy-presence-chooser.h \ - empathy-profile-chooser.h \ + empathy-protocol-chooser.h \ empathy-smiley-manager.h \ empathy-sound.h \ empathy-spell.h \ @@ -145,7 +146,7 @@ ui_DATA = \ empathy-account-widget-jabber.ui \ empathy-account-widget-msn.ui \ empathy-account-widget-sip.ui \ - empathy-account-widget-salut.ui \ + empathy-account-widget-local-xmpp.ui \ empathy-account-widget-irc.ui \ empathy-account-widget-icq.ui \ empathy-account-widget-yahoo.ui \ diff --git a/libempathy-gtk/empathy-account-chooser.c b/libempathy-gtk/empathy-account-chooser.c index 34ebc7eac..a91b0eb29 100644 --- a/libempathy-gtk/empathy-account-chooser.c +++ b/libempathy-gtk/empathy-account-chooser.c @@ -29,8 +29,6 @@ #include <glib/gi18n-lib.h> #include <gtk/gtk.h> -#include <libmissioncontrol/mission-control.h> - #include <libempathy/empathy-account-manager.h> #include <libempathy/empathy-utils.h> @@ -547,7 +545,7 @@ account_chooser_find_account_foreach (GtkTreeModel *model, gtk_tree_model_get (model, iter, COL_ACCOUNT_POINTER, &account, -1); - if (empathy_account_equal (account, data->account)) { + if (account == data->account) { data->found = TRUE; *(data->iter) = *iter; g_object_unref (account); @@ -617,7 +615,7 @@ account_chooser_update_iter (EmpathyAccountChooser *chooser, COL_ACCOUNT_POINTER, &account, -1); - icon_name = empathy_icon_name_from_account (account); + icon_name = empathy_account_get_icon_name (account); if (priv->filter) { is_enabled = priv->filter (account, priv->filter_data); } @@ -690,10 +688,8 @@ account_chooser_set_account_foreach (GtkTreeModel *model, if ((data->account == NULL) != (account == NULL)) { equal = FALSE; } - else if (data->account == account) { - equal = TRUE; - } else { - equal = empathy_account_equal (data->account, account); + else { + equal = (data->account == account); } if (account) { @@ -779,7 +775,7 @@ empathy_account_chooser_filter_is_connected (EmpathyAccount *account, { TpConnectionStatus status; - g_object_get (account, "status", &status, NULL); + g_object_get (account, "connection-status", &status, NULL); return status == TP_CONNECTION_STATUS_CONNECTED; } diff --git a/libempathy-gtk/empathy-account-widget-aim.ui b/libempathy-gtk/empathy-account-widget-aim.ui index 7f7ac3a60..2dfdde216 100644 --- a/libempathy-gtk/empathy-account-widget-aim.ui +++ b/libempathy-gtk/empathy-account-widget-aim.ui @@ -15,7 +15,7 @@ <child> <object class="GtkTable" id="table_common_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">3</property> <property name="column_spacing">12</property> <property name="row_spacing">6</property> @@ -28,8 +28,8 @@ <property name="mnemonic_widget">entry_password</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> @@ -63,8 +63,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="x_options"></property> <property name="y_options"></property> </packing> @@ -91,9 +91,30 @@ <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> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> MyScreenName</span></property> + <property name="use_markup">True</property> + </object> + <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> </object> @@ -190,4 +211,92 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_aim_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_screenname_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your AIM screen name?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_screenname_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> MyScreenName</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your AIM password?</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget-generic.ui b/libempathy-gtk/empathy-account-widget-generic.ui index 649307e06..ae97f3c98 100644 --- a/libempathy-gtk/empathy-account-widget-generic.ui +++ b/libempathy-gtk/empathy-account-widget-generic.ui @@ -29,7 +29,7 @@ </packing> </child> <child> - <object class="GtkExpander" id="expander1"> + <object class="GtkExpander" id="expander_advanced_settings"> <property name="visible">True</property> <property name="can_focus">True</property> <child> diff --git a/libempathy-gtk/empathy-account-widget-groupwise.ui b/libempathy-gtk/empathy-account-widget-groupwise.ui index 84157527d..d8ce768f9 100644 --- a/libempathy-gtk/empathy-account-widget-groupwise.ui +++ b/libempathy-gtk/empathy-account-widget-groupwise.ui @@ -14,7 +14,7 @@ <child> <object class="GtkTable" id="table_common_groupwise_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">2</property> <property name="column_spacing">6</property> <property name="row_spacing">6</property> @@ -56,8 +56,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="y_options"></property> </packing> </child> @@ -69,8 +69,8 @@ <property name="use_underline">True</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> @@ -100,6 +100,24 @@ <property name="y_options"></property> </packing> </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> username</span></property> + <property name="use_markup">True</property> + </object> + <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> + </packing> + </child> </object> <packing> <property name="expand">False</property> @@ -194,4 +212,92 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_groupwise_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_id_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your GroupWise User ID?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_id_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> username</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your GroupWise password?</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget-icq.ui b/libempathy-gtk/empathy-account-widget-icq.ui index 5eab0b75b..a36698a09 100644 --- a/libempathy-gtk/empathy-account-widget-icq.ui +++ b/libempathy-gtk/empathy-account-widget-icq.ui @@ -15,7 +15,7 @@ <child> <object class="GtkTable" id="table_common_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">3</property> <property name="column_spacing">12</property> <property name="row_spacing">6</property> @@ -28,8 +28,8 @@ <property name="mnemonic_widget">entry_password</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> @@ -63,8 +63,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="x_options"></property> <property name="y_options"></property> </packing> @@ -91,9 +91,30 @@ <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> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> 123456789</span></property> + <property name="use_markup">True</property> + </object> + <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> </object> @@ -219,4 +240,92 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_icq_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_uin_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your ICQ UIN?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_uin_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> 123456789</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your ICQ password?</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget-irc.c b/libempathy-gtk/empathy-account-widget-irc.c index c0699b23a..e462aa611 100644 --- a/libempathy-gtk/empathy-account-widget-irc.c +++ b/libempathy-gtk/empathy-account-widget-irc.c @@ -27,13 +27,12 @@ #include <glib/gi18n-lib.h> #include <gtk/gtk.h> -#include <libmissioncontrol/mc-protocol.h> - #include <libempathy/empathy-utils.h> #include <libempathy/empathy-irc-network-manager.h> #include "empathy-irc-network-dialog.h" #include "empathy-account-widget.h" +#include "empathy-account-widget-private.h" #include "empathy-account-widget-irc.h" #include "empathy-ui-utils.h" @@ -43,7 +42,7 @@ #define IRC_NETWORKS_FILENAME "irc-networks.xml" typedef struct { - EmpathyAccount *account; + EmpathyAccountWidget *self; EmpathyIrcNetworkManager *network_manager; GtkWidget *vbox_settings; @@ -61,17 +60,19 @@ account_widget_irc_destroy_cb (GtkWidget *widget, EmpathyAccountWidgetIrc *settings) { g_object_unref (settings->network_manager); - g_object_unref (settings->account); g_slice_free (EmpathyAccountWidgetIrc, settings); } static void unset_server_params (EmpathyAccountWidgetIrc *settings) { + EmpathyAccountSettings *ac_settings; + + g_object_get (settings->self, "settings", &ac_settings, NULL); DEBUG ("Unset server, port and use-ssl"); - empathy_account_unset_param (settings->account, "server"); - empathy_account_unset_param (settings->account, "port"); - empathy_account_unset_param (settings->account, "use-ssl"); + empathy_account_settings_unset (ac_settings, "server"); + empathy_account_settings_unset (ac_settings, "port"); + empathy_account_settings_unset (ac_settings, "use-ssl"); } static void @@ -82,6 +83,9 @@ update_server_params (EmpathyAccountWidgetIrc *settings) EmpathyIrcNetwork *network; GSList *servers; gchar *charset; + EmpathyAccountSettings *ac_settings; + + g_object_get (settings->self, "settings", &ac_settings, NULL); if (!gtk_combo_box_get_active_iter ( GTK_COMBO_BOX (settings->combobox_network), &iter)) @@ -97,7 +101,7 @@ update_server_params (EmpathyAccountWidgetIrc *settings) g_object_get (network, "charset", &charset, NULL); DEBUG ("Setting charset to %s", charset); - empathy_account_set_param_string (settings->account, "charset", charset); + empathy_account_settings_set_string (ac_settings, "charset", charset); g_free (charset); servers = empathy_irc_network_get_servers (network); @@ -116,11 +120,11 @@ update_server_params (EmpathyAccountWidgetIrc *settings) NULL); DEBUG ("Setting server to %s", address); - empathy_account_set_param_string (settings->account, "server", address); + empathy_account_settings_set_string (ac_settings, "server", address); DEBUG ("Setting port to %u", port); - empathy_account_set_param_int (settings->account, "port", port); + empathy_account_settings_set_uint32 (ac_settings, "port", port); DEBUG ("Setting use-ssl to %s", ssl ? "TRUE": "FALSE" ); - empathy_account_set_param_boolean (settings->account, "use-ssl", ssl); + empathy_account_settings_set_boolean (ac_settings, "use-ssl", ssl); g_free (address); } @@ -323,25 +327,30 @@ fill_networks_model (EmpathyAccountWidgetIrc *settings, static void account_widget_irc_setup (EmpathyAccountWidgetIrc *settings) { - gchar *nick = NULL; - gchar *fullname = NULL; - gchar *server = NULL; + const gchar *nick = NULL; + const gchar *fullname = NULL; + const gchar *server = NULL; gint port = 6667; - gchar *charset; + const gchar *charset; gboolean ssl = FALSE; EmpathyIrcNetwork *network = NULL; + EmpathyAccountSettings *ac_settings; + + g_object_get (settings->self, "settings", &ac_settings, NULL); - nick = empathy_account_get_param_string (settings->account, "account"); - fullname = empathy_account_get_param_string (settings->account, "fullname"); - server = empathy_account_get_param_string (settings->account, "server"); - charset = empathy_account_get_param_string (settings->account, "charset"); - port = empathy_account_get_param_int (settings->account, "port"); - ssl = empathy_account_get_param_boolean (settings->account, "use-ssl"); + nick = empathy_account_settings_get_string (ac_settings, "account"); + fullname = empathy_account_settings_get_string (ac_settings, + "fullname"); + server = empathy_account_settings_get_string (ac_settings, "server"); + charset = empathy_account_settings_get_string (ac_settings, "charset"); + port = empathy_account_settings_get_uint32 (ac_settings, "port"); + ssl = empathy_account_settings_get_boolean (ac_settings, "use-ssl"); if (!nick) { nick = g_strdup (g_get_user_name ()); - empathy_account_set_param_string (settings->account, "account", nick); + empathy_account_settings_set_string (ac_settings, + "account", nick); } if (!fullname) @@ -351,7 +360,8 @@ account_widget_irc_setup (EmpathyAccountWidgetIrc *settings) { fullname = g_strdup (nick); } - empathy_account_set_param_string (settings->account, "fullname", fullname); + empathy_account_settings_set_string (ac_settings, + "fullname", fullname); } if (server != NULL) @@ -404,33 +414,20 @@ account_widget_irc_setup (EmpathyAccountWidgetIrc *settings) fill_networks_model (settings, network); - - g_free (nick); - g_free (fullname); - g_free (server); - g_free (charset); } -/** - * empathy_account_widget_irc_new: - * @account: the #EmpathyAccount to configure - * - * Creates a new IRC account widget to configure a given #EmpathyAccount - * - * Returns: The toplevel container of the configuration widget - */ -GtkWidget * -empathy_account_widget_irc_new (EmpathyAccount *account) +void +empathy_account_widget_irc_build (EmpathyAccountWidget *self, + const char *filename, + GtkWidget **table_common_settings) { EmpathyAccountWidgetIrc *settings; gchar *dir, *user_file_with_path, *global_file_with_path; - GtkBuilder *gui; GtkListStore *store; GtkCellRenderer *renderer; - gchar *filename; settings = g_slice_new0 (EmpathyAccountWidgetIrc); - settings->account = g_object_ref (account); + settings->self = self; dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR); @@ -453,13 +450,12 @@ empathy_account_widget_irc_new (EmpathyAccount *account) g_free (global_file_with_path); g_free (user_file_with_path); - filename = empathy_file_lookup ("empathy-account-widget-irc.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_irc_settings", &settings->vbox_settings, + self->ui_details->gui = empathy_builder_get_file (filename, + "table_irc_settings", table_common_settings, + "vbox_irc", &self->ui_details->widget, + "table_irc_settings", &settings->vbox_settings, "combobox_network", &settings->combobox_network, NULL); - g_free (filename); /* Fill the networks combobox */ store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING); @@ -483,22 +479,24 @@ empathy_account_widget_irc_new (EmpathyAccount *account) account_widget_irc_setup (settings); - empathy_account_widget_handle_params (account, gui, + empathy_account_widget_handle_params (self, "entry_nick", "account", "entry_fullname", "fullname", "entry_password", "password", "entry_quit_message", "quit-message", NULL); - empathy_builder_connect (gui, settings, - "vbox_irc_settings", "destroy", account_widget_irc_destroy_cb, - "button_network", "clicked", account_widget_irc_button_edit_network_clicked_cb, - "button_add_network", "clicked", account_widget_irc_button_add_network_clicked_cb, - "button_remove_network", "clicked", account_widget_irc_button_remove_clicked_cb, - "combobox_network", "changed", account_widget_irc_combobox_network_changed_cb, + empathy_builder_connect (self->ui_details->gui, settings, + "table_irc_settings", "destroy", account_widget_irc_destroy_cb, + "button_network", "clicked", + account_widget_irc_button_edit_network_clicked_cb, + "button_add_network", "clicked", + account_widget_irc_button_add_network_clicked_cb, + "button_remove_network", "clicked", + account_widget_irc_button_remove_clicked_cb, + "combobox_network", "changed", + account_widget_irc_combobox_network_changed_cb, NULL); - empathy_account_widget_set_default_focus (gui, "entry_nick"); - - return empathy_builder_unref_and_keep_widget (gui, settings->vbox_settings); + self->ui_details->default_focus = g_strdup ("entry_nick"); } diff --git a/libempathy-gtk/empathy-account-widget-irc.h b/libempathy-gtk/empathy-account-widget-irc.h index 40e58bbc3..022158529 100644 --- a/libempathy-gtk/empathy-account-widget-irc.h +++ b/libempathy-gtk/empathy-account-widget-irc.h @@ -22,11 +22,13 @@ #define __EMPATHY_ACCOUNT_WIDGET_IRC_H__ #include <gtk/gtk.h> -#include <libempathy/empathy-account.h> +#include <libempathy-gtk/empathy-account-widget.h> G_BEGIN_DECLS -GtkWidget * empathy_account_widget_irc_new (EmpathyAccount *account); +void empathy_account_widget_irc_build (EmpathyAccountWidget *self, + const char *filename, + GtkWidget **table_common_settings); G_END_DECLS diff --git a/libempathy-gtk/empathy-account-widget-irc.ui b/libempathy-gtk/empathy-account-widget-irc.ui index abb1c9362..a4f7faa7f 100644 --- a/libempathy-gtk/empathy-account-widget-irc.ui +++ b/libempathy-gtk/empathy-account-widget-irc.ui @@ -255,207 +255,216 @@ <action-widget response="-7">button_close</action-widget> </action-widgets> </object> - <object class="GtkTable" id="vbox_irc_settings"> + <object class="GtkVBox" id="vbox_irc"> <property name="visible">True</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> + <property name="orientation">vertical</property> <child> - <object class="GtkEntry" id="entry_quit_message"> + <object class="GtkTable" id="table_irc_settings"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <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="y_options"></property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label_quit_message"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Quit message:</property> - </object> - <packing> - <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> - <object class="GtkEntry" id="entry_fullname"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <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> - <child> - <object class="GtkEntry" id="entry_password"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="visibility">False</property> - <property name="invisible_char">●</property> - </object> - <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> - <object class="GtkLabel" id="label_password"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Password:</property> - </object> - <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> - <object class="GtkLabel" id="label_fullname"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Real name:</property> - </object> - <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> - <object class="GtkEntry" id="entry_nick"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">●</property> - </object> - <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> - <object class="GtkLabel" id="label_nick"> - <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_nick</property> - </object> - <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> - <object class="GtkHBox" id="hbox174"> - <property name="visible">True</property> - <property name="spacing">2</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> - <object class="GtkComboBox" id="combobox_network"> + <object class="GtkEntry" id="entry_quit_message"> <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> </object> <packing> - <property name="position">0</property> + <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="y_options"></property> </packing> </child> <child> - <object class="GtkButton" id="button_add_network"> + <object class="GtkLabel" id="label_quit_message"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Quit message:</property> + </object> + <packing> + <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> + <object class="GtkEntry" id="entry_fullname"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> - <child> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="stock">gtk-add</property> - </object> - </child> + <property name="invisible_char">●</property> </object> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> + <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> <child> - <object class="GtkButton" id="button_network"> + <object class="GtkEntry" id="entry_password"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> - <child> - <object class="GtkImage" id="image834"> - <property name="visible">True</property> - <property name="stock">gtk-edit</property> - </object> - </child> + <property name="visibility">False</property> + <property name="invisible_char">●</property> </object> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">2</property> + <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> + <object class="GtkLabel" id="label_password"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Password:</property> + </object> + <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> + <object class="GtkLabel" id="label_fullname"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Real name:</property> + </object> + <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> - <object class="GtkButton" id="button_remove_network"> + <object class="GtkEntry" id="entry_nick"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> + <property name="invisible_char">●</property> + </object> + <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> + <object class="GtkLabel" id="label_nick"> + <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_nick</property> + </object> + <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> + <object class="GtkHBox" id="hbox174"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <object class="GtkComboBox" id="combobox_network"> + <property name="visible">True</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button_add_network"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <object class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-add</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> <child> - <object class="GtkImage" id="image835"> + <object class="GtkButton" id="button_network"> <property name="visible">True</property> - <property name="stock">gtk-remove</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <object class="GtkImage" id="image834"> + <property name="visible">True</property> + <property name="stock">gtk-edit</property> + </object> + </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="button_remove_network"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <child> + <object class="GtkImage" id="image835"> + <property name="visible">True</property> + <property name="stock">gtk-remove</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> </child> </object> <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">3</property> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_network2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Network:</property> + <property name="use_underline">True</property> + </object> + <packing> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> </packing> </child> </object> <packing> - <property name="left_attach">1</property> - <property name="right_attach">2</property> - <property name="x_options">GTK_FILL</property> - <property name="y_options">GTK_FILL</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label_network2"> - <property name="visible">True</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">Network:</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="x_options">GTK_FILL</property> - <property name="y_options"></property> + <property name="position">0</property> </packing> </child> </object> diff --git a/libempathy-gtk/empathy-account-widget-jabber.ui b/libempathy-gtk/empathy-account-widget-jabber.ui index 4b0aa15ad..d32182257 100644 --- a/libempathy-gtk/empathy-account-widget-jabber.ui +++ b/libempathy-gtk/empathy-account-widget-jabber.ui @@ -21,7 +21,7 @@ <child> <object class="GtkTable" id="table_common_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">3</property> <property name="column_spacing">12</property> <property name="row_spacing">6</property> @@ -35,8 +35,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="y_options"></property> </packing> </child> @@ -81,8 +81,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> @@ -93,15 +93,37 @@ <property name="xalign">0</property> <property name="label" translatable="yes">Pass_word:</property> <property name="use_underline">True</property> + <property name="justify">right</property> <property name="mnemonic_widget">entry_password</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> user@jabber.org</span></property> + <property name="use_markup">True</property> + </object> + <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> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> </object> <packing> <property name="expand">False</property> @@ -114,7 +136,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <child> - <object class="GtkVBox" id="vbox1"> + <object class="GtkVBox" id="vbox_advanced"> <property name="visible">True</property> <property name="orientation">vertical</property> <child> @@ -227,7 +249,7 @@ <property name="label_xalign">0</property> <property name="shadow_type">none</property> <child> - <object class="GtkAlignment" id="alignment1"> + <object class="GtkAlignment" id="alignment_server_settings"> <property name="visible">True</property> <property name="left_padding">12</property> <child> @@ -348,4 +370,112 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_jabber_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkLabel" id="label_id_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your Jabber ID?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_id_create"> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your desired Jabber ID?</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment_simple_jabber_id"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="top_padding">6</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_id_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> user@jabber.org</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">6</property> + <property name="label" translatable="yes">What is your Jabber password?</property> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_create"> + <property name="xalign">0</property> + <property name="ypad">6</property> + <property name="label" translatable="yes">What is your desired Jabber password?</property> + </object> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.5</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">5</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget-salut.ui b/libempathy-gtk/empathy-account-widget-local-xmpp.ui index ca633309d..ca633309d 100644 --- a/libempathy-gtk/empathy-account-widget-salut.ui +++ b/libempathy-gtk/empathy-account-widget-local-xmpp.ui diff --git a/libempathy-gtk/empathy-account-widget-msn.ui b/libempathy-gtk/empathy-account-widget-msn.ui index 1d7bde038..27de65a2a 100644 --- a/libempathy-gtk/empathy-account-widget-msn.ui +++ b/libempathy-gtk/empathy-account-widget-msn.ui @@ -14,7 +14,7 @@ <child> <object class="GtkTable" id="table_common_msn_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">2</property> <property name="column_spacing">6</property> <property name="row_spacing">6</property> @@ -56,8 +56,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="y_options"></property> </packing> </child> @@ -69,8 +69,8 @@ <property name="use_underline">True</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> @@ -100,6 +100,24 @@ <property name="y_options"></property> </packing> </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> user@hotmail.com</span></property> + <property name="use_markup">True</property> + </object> + <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> + </packing> + </child> </object> <packing> <property name="expand">False</property> @@ -194,4 +212,92 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_msn_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_id_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your Windows Live user name?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_id_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> user@hotmail.com</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your Windows Live password?</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget-private.h b/libempathy-gtk/empathy-account-widget-private.h new file mode 100644 index 000000000..aaa24e58f --- /dev/null +++ b/libempathy-gtk/empathy-account-widget-private.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2009 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +#ifndef __EMPATHY_ACCOUNT_WIDGET_PRIVATE_H__ +#define __EMPATHY_ACCOUNT_WIDGET_PRIVATE_H__ + +#include <libempathy-gtk/empathy-account-widget.h> +#include <glib.h> +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +struct _EmpathyAccountWidgetUIDetails { + GtkWidget *widget; + + GtkBuilder *gui; + + char *default_focus; + gboolean add_forget; +}; + + +void empathy_account_widget_handle_params (EmpathyAccountWidget *self, + const gchar *first_widget, + ...); + +G_END_DECLS + +#endif /* __EMPATHY_ACCOUNT_WIDGET_PRIVATE_H__ */
\ No newline at end of file diff --git a/libempathy-gtk/empathy-account-widget-sip.c b/libempathy-gtk/empathy-account-widget-sip.c index 05e917e53..db39ddae4 100644 --- a/libempathy-gtk/empathy-account-widget-sip.c +++ b/libempathy-gtk/empathy-account-widget-sip.c @@ -28,17 +28,15 @@ #include <glib/gi18n-lib.h> #include <gtk/gtk.h> -#include <libmissioncontrol/mc-protocol.h> - #include <libempathy/empathy-utils.h> #include "empathy-account-widget.h" +#include "empathy-account-widget-private.h" #include "empathy-account-widget-sip.h" #include "empathy-ui-utils.h" typedef struct { - EmpathyAccount *account; - + EmpathyAccountWidget *self; GtkWidget *vbox_settings; GtkWidget *entry_stun_server; @@ -50,7 +48,6 @@ static void account_widget_sip_destroy_cb (GtkWidget *widget, EmpathyAccountWidgetSip *settings) { - g_object_unref (settings->account); g_slice_free (EmpathyAccountWidgetSip, settings); } @@ -66,55 +63,65 @@ account_widget_sip_discover_stun_toggled_cb ( gtk_widget_set_sensitive (settings->spinbutton_stun_part, !active); } -/** - * empathy_account_widget_sip_new: - * @account: the #EmpathyAccount to configure - * - * Creates a new SIP account widget to configure a given #EmpathyAccount - * - * Returns: The toplevel container of the configuration widget - */ -GtkWidget * -empathy_account_widget_sip_new (EmpathyAccount *account) +void +empathy_account_widget_sip_build (EmpathyAccountWidget *self, + const char *filename, + GtkWidget **table_common_settings) { EmpathyAccountWidgetSip *settings; - GtkBuilder *gui; - gchar *filename; - - settings = g_slice_new0 (EmpathyAccountWidgetSip); - settings->account = g_object_ref (account); - - filename = empathy_file_lookup ("empathy-account-widget-sip.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_sip_settings", &settings->vbox_settings, - "entry_stun-server", &settings->entry_stun_server, - "spinbutton_stun-port", &settings->spinbutton_stun_part, - "checkbutton_discover-stun", &settings->checkbutton_discover_stun, - NULL); - g_free (filename); - - empathy_account_widget_handle_params (account, gui, - "entry_userid", "account", - "entry_password", "password", - "checkbutton_discover-stun", "discover-stun", - "entry_stun-server", "stun-server", - "spinbutton_stun-port", "stun-port", - NULL); - - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); - - account_widget_sip_discover_stun_toggled_cb (settings->checkbutton_discover_stun, - settings); - - empathy_builder_connect (gui, settings, - "vbox_sip_settings", "destroy", account_widget_sip_destroy_cb, - "checkbutton_discover-stun", "toggled", account_widget_sip_discover_stun_toggled_cb, - NULL); - - empathy_account_widget_set_default_focus (gui, "entry_userid"); - - return empathy_builder_unref_and_keep_widget (gui, settings->vbox_settings); + GtkWidget *vbox_settings; + gboolean is_simple; + + g_object_get (self, "simple", &is_simple, NULL); + + if (is_simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_sip_simple", &vbox_settings, + NULL); + + empathy_account_widget_handle_params (self, + "entry_userid_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_userid_simple"); + } + else + { + settings = g_slice_new0 (EmpathyAccountWidgetSip); + settings->self = self; + + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", table_common_settings, + "vbox_sip_settings", &vbox_settings, + "entry_stun-server", &settings->entry_stun_server, + "spinbutton_stun-port", &settings->spinbutton_stun_part, + "checkbutton_discover-stun", &settings->checkbutton_discover_stun, + NULL); + settings->vbox_settings = vbox_settings; + + empathy_account_widget_handle_params (self, + "entry_userid", "account", + "entry_password", "password", + "checkbutton_discover-stun", "discover-stun", + "entry_stun-server", "stun-server", + "spinbutton_stun-port", "stun-port", + NULL); + + account_widget_sip_discover_stun_toggled_cb ( + settings->checkbutton_discover_stun, + settings); + + empathy_builder_connect (self->ui_details->gui, settings, + "vbox_sip_settings", "destroy", account_widget_sip_destroy_cb, + "checkbutton_discover-stun", "toggled", + account_widget_sip_discover_stun_toggled_cb, + NULL); + + self->ui_details->add_forget = TRUE; + self->ui_details->default_focus = g_strdup ("entry_userid"); + } + + self->ui_details->widget = vbox_settings; } diff --git a/libempathy-gtk/empathy-account-widget-sip.h b/libempathy-gtk/empathy-account-widget-sip.h index 69f60aacc..6334a745b 100644 --- a/libempathy-gtk/empathy-account-widget-sip.h +++ b/libempathy-gtk/empathy-account-widget-sip.h @@ -22,11 +22,13 @@ #define __EMPATHY_ACCOUNT_WIDGET_SIP_H__ #include <gtk/gtk.h> -#include <libempathy/empathy-account.h> +#include <libempathy-gtk/empathy-account-widget.h> G_BEGIN_DECLS -GtkWidget * empathy_account_widget_sip_new (EmpathyAccount *account); +void empathy_account_widget_sip_build (EmpathyAccountWidget *self, + const char *filename, + GtkWidget **table_common_settings); G_END_DECLS diff --git a/libempathy-gtk/empathy-account-widget-sip.ui b/libempathy-gtk/empathy-account-widget-sip.ui index 406f22c94..e8491a6a5 100644 --- a/libempathy-gtk/empathy-account-widget-sip.ui +++ b/libempathy-gtk/empathy-account-widget-sip.ui @@ -11,9 +11,9 @@ <property name="visible">True</property> <property name="orientation">vertical</property> <child> - <object class="GtkTable" id="table1"> + <object class="GtkTable" id="table_common_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">2</property> <property name="column_spacing">12</property> <property name="row_spacing">6</property> @@ -26,8 +26,8 @@ <property name="mnemonic_widget">entry_password</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> @@ -92,9 +92,27 @@ <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> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> user@my.sip.server</span></property> + <property name="use_markup">True</property> + </object> + <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> </object> @@ -109,7 +127,7 @@ <property name="visible">True</property> <property name="can_focus">True</property> <child> - <object class="GtkAlignment" id="alignment1"> + <object class="GtkAlignment" id="alignment3"> <property name="visible">True</property> <property name="xalign">0</property> <property name="left_padding">12</property> @@ -212,4 +230,92 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_sip_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_userid_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your SIP login ID?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_userid_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> user@my.sip.server</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your SIP account password?</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget-yahoo.ui b/libempathy-gtk/empathy-account-widget-yahoo.ui index 31e932674..554e0dbec 100644 --- a/libempathy-gtk/empathy-account-widget-yahoo.ui +++ b/libempathy-gtk/empathy-account-widget-yahoo.ui @@ -16,7 +16,7 @@ <child> <object class="GtkTable" id="table_common_settings"> <property name="visible">True</property> - <property name="n_rows">2</property> + <property name="n_rows">3</property> <property name="n_columns">3</property> <property name="column_spacing">12</property> <property name="row_spacing">6</property> @@ -29,8 +29,8 @@ <property name="mnemonic_widget">entry_password</property> </object> <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> + <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> @@ -51,8 +51,8 @@ <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="top_attach">2</property> + <property name="bottom_attach">3</property> <property name="x_options">GTK_FILL</property> <property name="y_options"></property> </packing> @@ -92,9 +92,30 @@ <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> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label_username_example"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">3</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> username</span></property> + <property name="use_markup">True</property> + </object> + <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> </object> @@ -294,4 +315,92 @@ </packing> </child> </object> + <object class="GtkVBox" id="vbox_yahoo_simple"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label_id_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your Yahoo! ID?</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="bottom_padding">3</property> + <property name="left_padding">12</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="GtkEntry" id="entry_id_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">•</property> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_example"> + <property name="visible">True</property> + <property name="xalign">0.10000000149011612</property> + <property name="label" translatable="yes"><span size="small"><b>Example:</b> username</span></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label_password_simple"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">What is your Yahoo! password?</property> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xscale">0.34999999403953552</property> + <property name="yscale">0.34999999403953552</property> + <property name="left_padding">12</property> + <child> + <object class="GtkEntry" id="entry_password_simple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">•</property> + </object> + </child> + </object> + <packing> + <property name="position">3</property> + </packing> + </child> + </object> </interface> diff --git a/libempathy-gtk/empathy-account-widget.c b/libempathy-gtk/empathy-account-widget.c index 0c2c35177..0927d109c 100644 --- a/libempathy-gtk/empathy-account-widget.c +++ b/libempathy-gtk/empathy-account-widget.c @@ -1,7 +1,6 @@ -/* -*- 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. + * Copyright (C) 2007-2009 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 @@ -20,6 +19,8 @@ * * Authors: Xavier Claessens <xclaesse@gmail.com> * Martyn Russell <martyn@imendio.com> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + * Jonathan Tellier <jonathan.tellier@gmail.com> */ #include <config.h> @@ -29,702 +30,1385 @@ #include <gtk/gtk.h> #include <glib/gi18n-lib.h> -#include <libmissioncontrol/mc-protocol.h> - #include <libempathy/empathy-utils.h> #include <libempathy/empathy-account.h> +#include <telepathy-glib/connection-manager.h> +#include <telepathy-glib/util.h> +#include <dbus/dbus-protocol.h> + #include "empathy-account-widget.h" +#include "empathy-account-widget-private.h" +#include "empathy-account-widget-sip.h" +#include "empathy-account-widget-irc.h" #include "empathy-ui-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> -static gboolean -account_widget_entry_focus_cb (GtkWidget *widget, - GdkEventFocus *event, - EmpathyAccount *account) -{ - const gchar *str; - const gchar *param_name; - - str = gtk_entry_get_text (GTK_ENTRY (widget)); - param_name = g_object_get_data (G_OBJECT (widget), "param_name"); - - if (EMP_STR_EMPTY (str)) { - gchar *value = NULL; - - empathy_account_unset_param (account, param_name); - value = empathy_account_get_param_string (account, param_name); - DEBUG ("Unset %s and restore to %s", param_name, value); - gtk_entry_set_text (GTK_ENTRY (widget), value ? value : ""); - g_free (value); - } else { - McProfile *profile; - const gchar *domain = NULL; - gchar *dup_str = NULL; - - profile = empathy_account_get_profile (account); - if (mc_profile_get_capabilities (profile) & - MC_PROFILE_CAPABILITY_SPLIT_ACCOUNT) { - domain = mc_profile_get_default_account_domain (profile); - } - - if (domain && !strstr (str, "@") && - strcmp (param_name, "account") == 0) { - DEBUG ("Adding @%s suffix to account", domain); - str = dup_str = g_strconcat (str, "@", domain, NULL); - gtk_entry_set_text (GTK_ENTRY (widget), str); - } - DEBUG ("Setting %s to %s", param_name, - strstr (param_name, "password") ? "***" : str); - empathy_account_set_param_string (account, param_name, str); - g_free (dup_str); - g_object_unref (profile); - } - - return FALSE; +G_DEFINE_TYPE (EmpathyAccountWidget, empathy_account_widget, G_TYPE_OBJECT) + +typedef struct { + char *protocol; + EmpathyAccountSettings *settings; + + GtkWidget *table_common_settings; + GtkWidget *apply_button; + GtkWidget *cancel_button; + GtkWidget *entry_password; + GtkWidget *button_forget; + GtkWidget *spinbutton_port; + GtkWidget *enabled_checkbox; + + gboolean simple; + + /* An EmpathyAccountWidget can be used to either create an account or + * modify it. When we are creating an account, this member is set to TRUE */ + gboolean creating_account; + + /* After having applied changes to a user account, we automatically + * disconnect him. Once he's disconnected, he will be reconnected, + * depending on the value of this member which should be set to the checked + * state of the "Enabled" checkbox. This is done so the new information + * entered by the user is validated on the server. */ + gboolean re_enable_accound; + + gboolean dispose_run; +} EmpathyAccountWidgetPriv; + +enum { + PROP_PROTOCOL = 1, + PROP_SETTINGS, + PROP_SIMPLE, + PROP_CREATING_ACCOUNT +}; + +enum { + HANDLE_APPLY, + ACCOUNT_CREATED, + CANCELLED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountWidget) +#define CHANGED_TIMEOUT 300 + +static void +account_widget_set_control_buttons_sensitivity (EmpathyAccountWidget *self, + gboolean sensitive) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + if (!priv->simple) + { + gtk_widget_set_sensitive (priv->apply_button, sensitive); + gtk_widget_set_sensitive (priv->cancel_button, sensitive); + } } static void -account_widget_int_changed_cb (GtkWidget *widget, - EmpathyAccount *account) +account_widget_handle_control_buttons_sensitivity (EmpathyAccountWidget *self) { - const gchar *param_name; - gint value; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + gboolean is_valid; - value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)); - param_name = g_object_get_data (G_OBJECT (widget), "param_name"); + is_valid = empathy_account_settings_is_valid (priv->settings); - if (value == 0) { - empathy_account_unset_param (account, param_name); - value = empathy_account_get_param_int (account, param_name); - DEBUG ("Unset %s and restore to %d", param_name, value); - gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value); - } else { - DEBUG ("Setting %s to %d", param_name, value); - empathy_account_set_param_int (account, param_name, value); - } + if (!priv->simple) + { + gtk_widget_set_sensitive (priv->apply_button, is_valid); + gtk_widget_set_sensitive (priv->cancel_button, is_valid); + } + + g_signal_emit (self, signals[HANDLE_APPLY], 0, is_valid); } static void -account_widget_checkbutton_toggled_cb (GtkWidget *widget, - EmpathyAccount *account) +account_widget_entry_changed_common (EmpathyAccountWidget *self, + GtkEntry *entry, gboolean focus) +{ + const gchar *str; + const gchar *param_name; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + str = gtk_entry_get_text (entry); + param_name = g_object_get_data (G_OBJECT (entry), "param_name"); + + if (EMP_STR_EMPTY (str)) + { + const gchar *value = NULL; + + empathy_account_settings_unset (priv->settings, param_name); + + if (focus) + { + value = empathy_account_settings_get_string (priv->settings, + param_name); + DEBUG ("Unset %s and restore to %s", param_name, value); + gtk_entry_set_text (entry, value ? value : ""); + } + } + else + { + DEBUG ("Setting %s to %s", param_name, + tp_strdiff (param_name, "password") ? str : "***"); + empathy_account_settings_set_string (priv->settings, param_name, str); + } +} + +static gboolean +account_widget_entry_focus_cb (GtkWidget *widget, + GdkEventFocus *event, + EmpathyAccountWidget *self) { - gboolean value; - gboolean default_value; - const gchar *param_name; + account_widget_entry_changed_common (self, GTK_ENTRY (widget), TRUE); - value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); - param_name = g_object_get_data (G_OBJECT (widget), "param_name"); + return FALSE; +} + +static void +account_widget_entry_changed_cb (GtkEditable *entry, + EmpathyAccountWidget *self) +{ + account_widget_entry_changed_common (self, GTK_ENTRY (entry), FALSE); + account_widget_handle_control_buttons_sensitivity (self); +} - /* FIXME: This is ugly! checkbox don't have a "not-set" value so we - * always unset the param and set the value if different from the - * default value. */ - empathy_account_unset_param (account, param_name); - default_value = empathy_account_get_param_boolean (account, param_name); +static void +account_widget_int_changed_cb (GtkWidget *widget, + EmpathyAccountWidget *self) +{ + const gchar *param_name; + gint value; + const gchar *signature; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (widget)); + param_name = g_object_get_data (G_OBJECT (widget), "param_name"); + + signature = empathy_account_settings_get_dbus_signature (priv->settings, + param_name); + g_return_if_fail (signature != NULL); + + DEBUG ("Setting %s to %d", param_name, value); + + switch ((int)*signature) + { + case DBUS_TYPE_INT16: + case DBUS_TYPE_INT32: + empathy_account_settings_set_int32 (priv->settings, param_name, value); + break; + case DBUS_TYPE_INT64: + empathy_account_settings_set_int64 (priv->settings, param_name, value); + break; + case DBUS_TYPE_UINT16: + case DBUS_TYPE_UINT32: + empathy_account_settings_set_uint32 (priv->settings, param_name, value); + break; + case DBUS_TYPE_UINT64: + empathy_account_settings_set_uint64 (priv->settings, param_name, value); + break; + default: + g_return_if_reached (); + } + + account_widget_handle_control_buttons_sensitivity (self); +} - if (default_value == value) { - DEBUG ("Unset %s and restore to %d", param_name, default_value); - } else { - DEBUG ("Setting %s to %d", param_name, value); - empathy_account_set_param_boolean (account, param_name, value); - } +static void +account_widget_checkbutton_toggled_cb (GtkWidget *widget, + EmpathyAccountWidget *self) +{ + gboolean value; + gboolean default_value; + const gchar *param_name; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + param_name = g_object_get_data (G_OBJECT (widget), "param_name"); + + /* FIXME: This is ugly! checkbox don't have a "not-set" value so we + * always unset the param and set the value if different from the + * default value. */ + empathy_account_settings_unset (priv->settings, param_name); + default_value = empathy_account_settings_get_boolean (priv->settings, + param_name); + + if (default_value == value) + { + DEBUG ("Unset %s and restore to %d", param_name, default_value); + } + else + { + DEBUG ("Setting %s to %d", param_name, value); + empathy_account_settings_set_boolean (priv->settings, param_name, value); + } + + account_widget_handle_control_buttons_sensitivity (self); } static void account_widget_forget_clicked_cb (GtkWidget *button, - GtkWidget *entry) + EmpathyAccountWidget *self) { - EmpathyAccount *account; - const gchar *param_name; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + const gchar *param_name; - param_name = g_object_get_data (G_OBJECT (entry), "param_name"); - account = g_object_get_data (G_OBJECT (entry), "account"); + param_name = g_object_get_data (G_OBJECT (priv->entry_password), + "param_name"); - DEBUG ("Unset %s", param_name); - empathy_account_unset_param (account, param_name); - gtk_entry_set_text (GTK_ENTRY (entry), ""); + DEBUG ("Unset %s", param_name); + empathy_account_settings_unset (priv->settings, param_name); + gtk_entry_set_text (GTK_ENTRY (priv->entry_password), ""); + + account_widget_handle_control_buttons_sensitivity (self); } static void account_widget_password_changed_cb (GtkWidget *entry, - GtkWidget *button) + EmpathyAccountWidget *self) { - const gchar *str; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + const gchar *str; - str = gtk_entry_get_text (GTK_ENTRY (entry)); - gtk_widget_set_sensitive (button, !EMP_STR_EMPTY (str)); + str = gtk_entry_get_text (GTK_ENTRY (entry)); + gtk_widget_set_sensitive (priv->button_forget, !EMP_STR_EMPTY (str)); } static void account_widget_jabber_ssl_toggled_cb (GtkWidget *checkbutton_ssl, - GtkWidget *spinbutton_port) + EmpathyAccountWidget *self) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + gboolean value; + gint32 port = 0; + + value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl)); + port = empathy_account_settings_get_uint32 (priv->settings, "port"); + + if (value) + { + if (port == 5222 || port == 0) + port = 5223; + } + else + { + if (port == 5223 || port == 0) + port = 5222; + } + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->spinbutton_port), port); +} + +static void +account_widget_setup_widget (EmpathyAccountWidget *self, + GtkWidget *widget, + const gchar *param_name) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + g_object_set_data_full (G_OBJECT (widget), "param_name", + g_strdup (param_name), g_free); + + if (GTK_IS_SPIN_BUTTON (widget)) + { + gint value = 0; + const gchar *signature; + + signature = empathy_account_settings_get_dbus_signature (priv->settings, + param_name); + g_return_if_fail (signature != NULL); + + switch ((int)*signature) + { + case DBUS_TYPE_INT16: + case DBUS_TYPE_INT32: + value = empathy_account_settings_get_int32 (priv->settings, + param_name); + break; + case DBUS_TYPE_INT64: + value = empathy_account_settings_get_int64 (priv->settings, + param_name); + break; + case DBUS_TYPE_UINT16: + case DBUS_TYPE_UINT32: + value = empathy_account_settings_get_uint32 (priv->settings, + param_name); + break; + case DBUS_TYPE_UINT64: + value = empathy_account_settings_get_uint64 (priv->settings, + param_name); + break; + default: + g_return_if_reached (); + } + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value); + + g_signal_connect (widget, "value-changed", + G_CALLBACK (account_widget_int_changed_cb), + self); + } + else if (GTK_IS_ENTRY (widget)) + { + const gchar *str = NULL; + + str = empathy_account_settings_get_string (priv->settings, param_name); + gtk_entry_set_text (GTK_ENTRY (widget), str ? str : ""); + + if (strstr (param_name, "password")) + { + gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE); + } + + g_signal_connect (widget, "focus-out-event", + G_CALLBACK (account_widget_entry_focus_cb), + self); + g_signal_connect (widget, "changed", + G_CALLBACK (account_widget_entry_changed_cb), self); + } + else if (GTK_IS_TOGGLE_BUTTON (widget)) + { + gboolean value = FALSE; + + value = empathy_account_settings_get_boolean (priv->settings, + param_name); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value); + + g_signal_connect (widget, "toggled", + G_CALLBACK (account_widget_checkbutton_toggled_cb), + self); + } + else + { + DEBUG ("Unknown type of widget for param %s", param_name); + } +} + +static gchar * +account_widget_generic_format_param_name (const gchar *param_name) { - EmpathyAccount *account; - gboolean value; - gint port = 0; + gchar *str; + gchar *p; + + str = g_strdup (param_name); + + if (str && g_ascii_isalpha (str[0])) + str[0] = g_ascii_toupper (str[0]); - value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_ssl)); - account = g_object_get_data (G_OBJECT (spinbutton_port), "account"); - port = empathy_account_get_param_int (account, "port"); + while ((p = strchr (str, '-')) != NULL) + { + if (p[1] != '\0' && g_ascii_isalpha (p[1])) + { + p[0] = ' '; + p[1] = g_ascii_toupper (p[1]); + } - if (value) { - if (port == 5222 || port == 0) { - port = 5223; - } - } else { - if (port == 5223 || port == 0) { - port = 5222; - } - } + p++; + } - gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_port), port); + return str; } static void -account_widget_setup_widget (GtkWidget *widget, - EmpathyAccount *account, - const gchar *param_name) +accounts_widget_generic_setup (EmpathyAccountWidget *self, + GtkWidget *table_common_settings, + GtkWidget *table_advanced_settings) { - g_object_set_data_full (G_OBJECT (widget), "param_name", - g_strdup (param_name), g_free); - g_object_set_data_full (G_OBJECT (widget), "account", - g_object_ref (account), g_object_unref); - - if (GTK_IS_SPIN_BUTTON (widget)) { - gint value = 0; - - value = empathy_account_get_param_int (account, param_name); - gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value); + TpConnectionManagerParam *params, *param; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + params = empathy_account_settings_get_tp_params (priv->settings); + + for (param = params; param != NULL && param->name != NULL; param++) + { + GtkWidget *table_settings; + guint n_rows = 0; + GtkWidget *widget = NULL; + gchar *param_name_formatted; + + if (param->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED) + table_settings = table_common_settings; + else if (priv->simple) + return; + else + table_settings = table_advanced_settings; + + param_name_formatted = account_widget_generic_format_param_name + (param->name); + g_object_get (table_settings, "n-rows", &n_rows, NULL); + gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2); + + if (param->dbus_signature[0] == 's') + { + gchar *str; + + str = g_strdup_printf (_("%s:"), param_name_formatted); + widget = gtk_label_new (str); + gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5); + g_free (str); + + gtk_table_attach (GTK_TABLE (table_settings), + widget, + 0, 1, + n_rows - 1, n_rows, + GTK_FILL, 0, + 0, 0); + gtk_widget_show (widget); + + widget = gtk_entry_new (); + if (strcmp (param->name, "account") == 0) + { + g_signal_connect (widget, "realize", + G_CALLBACK (gtk_widget_grab_focus), + NULL); + } + gtk_table_attach (GTK_TABLE (table_settings), + widget, + 1, 2, + n_rows - 1, n_rows, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + gtk_widget_show (widget); + } + /* int types: ynqiuxt. double type is 'd' */ + else if (param->dbus_signature[0] == 'y' || + param->dbus_signature[0] == 'n' || + param->dbus_signature[0] == 'q' || + param->dbus_signature[0] == 'i' || + param->dbus_signature[0] == 'u' || + param->dbus_signature[0] == 'x' || + param->dbus_signature[0] == 't' || + param->dbus_signature[0] == 'd') + { + gchar *str = NULL; + gdouble minint = 0; + gdouble maxint = 0; + gdouble step = 1; + + switch (param->dbus_signature[0]) + { + case 'y': minint = G_MININT8; maxint = G_MAXINT8; break; + case 'n': minint = G_MININT16; maxint = G_MAXINT16; break; + case 'q': minint = 0; maxint = G_MAXUINT16; break; + case 'i': minint = G_MININT32; maxint = G_MAXINT32; break; + case 'u': minint = 0; maxint = G_MAXUINT32; break; + case 'x': minint = G_MININT64; maxint = G_MAXINT64; break; + case 't': minint = 0; maxint = G_MAXUINT64; break; + case 'd': minint = G_MININT32; maxint = G_MAXINT32; + step = 0.1; break; + } + + str = g_strdup_printf (_("%s:"), param_name_formatted); + widget = gtk_label_new (str); + gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5); + g_free (str); + + gtk_table_attach (GTK_TABLE (table_settings), + widget, + 0, 1, + n_rows - 1, n_rows, + GTK_FILL, 0, + 0, 0); + gtk_widget_show (widget); + + widget = gtk_spin_button_new_with_range (minint, maxint, step); + gtk_table_attach (GTK_TABLE (table_settings), + widget, + 1, 2, + n_rows - 1, n_rows, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + gtk_widget_show (widget); + } + else if (param->dbus_signature[0] == 'b') + { + widget = gtk_check_button_new_with_label (param_name_formatted); + gtk_table_attach (GTK_TABLE (table_settings), + widget, + 0, 2, + n_rows - 1, n_rows, + GTK_FILL | GTK_EXPAND, 0, + 0, 0); + gtk_widget_show (widget); + } + else + { + DEBUG ("Unknown signature for param %s: %s", + param_name_formatted, param->dbus_signature); + } + + if (widget) + account_widget_setup_widget (self, widget, param->name); + + g_free (param_name_formatted); + } +} - g_signal_connect (widget, "value-changed", - G_CALLBACK (account_widget_int_changed_cb), - account); - } - else if (GTK_IS_ENTRY (widget)) { - gchar *str = NULL; +static void +account_widget_handle_params_valist (EmpathyAccountWidget *self, + const gchar *first_widget, + va_list args) +{ + GObject *object; + const gchar *name; - str = empathy_account_get_param_string (account, param_name); - gtk_entry_set_text (GTK_ENTRY (widget), str ? str : ""); - g_free (str); + for (name = first_widget; name; name = va_arg (args, const gchar *)) + { + const gchar *param_name; - if (strstr (param_name, "password")) { - gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE); - } + param_name = va_arg (args, const gchar *); + object = gtk_builder_get_object (self->ui_details->gui, name); - g_signal_connect (widget, "focus-out-event", - G_CALLBACK (account_widget_entry_focus_cb), - account); - } - else if (GTK_IS_TOGGLE_BUTTON (widget)) { - gboolean value = FALSE; + if (!object) + { + g_warning ("Builder is missing object '%s'.", name); + continue; + } - value = empathy_account_get_param_boolean (account, param_name); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value); + account_widget_setup_widget (self, GTK_WIDGET (object), param_name); + } +} - g_signal_connect (widget, "toggled", - G_CALLBACK (account_widget_checkbutton_toggled_cb), - account); - } else { - DEBUG ("Unknown type of widget for param %s", param_name); - } +static void +account_widget_cancel_clicked_cb (GtkWidget *button, + EmpathyAccountWidget *self) +{ + g_signal_emit (self, signals[CANCELLED], 0); } -static gchar * -account_widget_generic_format_param_name (const gchar *param_name) +static void +account_widget_account_enabled_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - gchar *str; - gchar *p; - - str = g_strdup (param_name); - - if (str && g_ascii_isalpha (str[0])) { - str[0] = g_ascii_toupper (str[0]); - } - - while ((p = strchr (str, '-')) != NULL) { - if (p[1] != '\0' && g_ascii_isalpha (p[1])) { - p[0] = ' '; - p[1] = g_ascii_toupper (p[1]); - } - - p++; - } - - return str; -} - -static void -accounts_widget_generic_setup (EmpathyAccount *account, - GtkWidget *table_common_settings, - GtkWidget *table_advanced_settings) -{ - McProtocol *protocol; - McProfile *profile; - GSList *params, *l; - - profile = empathy_account_get_profile (account); - protocol = mc_profile_get_protocol (profile); - - if (!protocol) { - /* The CM is not installed, MC shouldn't list them - * see SF bug #1688779 - * FIXME: We should display something asking the user to - * install the CM - */ - g_object_unref (profile); - return; - } - - params = mc_protocol_get_params (protocol); - - for (l = params; l; l = l->next) { - McProtocolParam *param; - GtkWidget *table_settings; - guint n_rows = 0; - GtkWidget *widget = NULL; - gchar *param_name_formatted; - - param = l->data; - if (param->flags & MC_PROTOCOL_PARAM_REQUIRED) { - table_settings = table_common_settings; - } else { - table_settings = table_advanced_settings; - } - param_name_formatted = account_widget_generic_format_param_name (param->name); - g_object_get (table_settings, "n-rows", &n_rows, NULL); - gtk_table_resize (GTK_TABLE (table_settings), ++n_rows, 2); - - if (param->signature[0] == 's') { - gchar *str; - - str = g_strdup_printf (_("%s:"), param_name_formatted); - widget = gtk_label_new (str); - gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5); - g_free (str); - - gtk_table_attach (GTK_TABLE (table_settings), - widget, - 0, 1, - n_rows - 1, n_rows, - GTK_FILL, 0, - 0, 0); - gtk_widget_show (widget); - - widget = gtk_entry_new (); - if (strcmp (param->name, "account") == 0) { - g_signal_connect (widget, "realize", - G_CALLBACK (gtk_widget_grab_focus), - NULL); - } - gtk_table_attach (GTK_TABLE (table_settings), - widget, - 1, 2, - n_rows - 1, n_rows, - GTK_FILL | GTK_EXPAND, 0, - 0, 0); - gtk_widget_show (widget); - } - /* int types: ynqiuxt. double type is 'd' */ - else if (param->signature[0] == 'y' || - param->signature[0] == 'n' || - param->signature[0] == 'q' || - param->signature[0] == 'i' || - param->signature[0] == 'u' || - param->signature[0] == 'x' || - param->signature[0] == 't' || - param->signature[0] == 'd') { - gchar *str = NULL; - gdouble minint = 0; - gdouble maxint = 0; - gdouble step = 1; - - switch (param->signature[0]) { - case 'y': minint = G_MININT8; maxint = G_MAXINT8; break; - case 'n': minint = G_MININT16; maxint = G_MAXINT16; break; - case 'q': minint = 0; maxint = G_MAXUINT16; break; - case 'i': minint = G_MININT32; maxint = G_MAXINT32; break; - case 'u': minint = 0; maxint = G_MAXUINT32; break; - case 'x': minint = G_MININT64; maxint = G_MAXINT64; break; - case 't': minint = 0; maxint = G_MAXUINT64; break; - case 'd': minint = G_MININT32; maxint = G_MAXINT32; step = 0.1; break; - } - - str = g_strdup_printf (_("%s:"), param_name_formatted); - widget = gtk_label_new (str); - gtk_misc_set_alignment (GTK_MISC (widget), 0, 0.5); - g_free (str); - - gtk_table_attach (GTK_TABLE (table_settings), - widget, - 0, 1, - n_rows - 1, n_rows, - GTK_FILL, 0, - 0, 0); - gtk_widget_show (widget); - - widget = gtk_spin_button_new_with_range (minint, maxint, step); - gtk_table_attach (GTK_TABLE (table_settings), - widget, - 1, 2, - n_rows - 1, n_rows, - GTK_FILL | GTK_EXPAND, 0, - 0, 0); - gtk_widget_show (widget); - } - else if (param->signature[0] == 'b') { - widget = gtk_check_button_new_with_label (param_name_formatted); - gtk_table_attach (GTK_TABLE (table_settings), - widget, - 0, 2, - n_rows - 1, n_rows, - GTK_FILL | GTK_EXPAND, 0, - 0, 0); - gtk_widget_show (widget); - } else { - DEBUG ("Unknown signature for param %s: %s", - param_name_formatted, param->signature); - } - - if (widget) { - account_widget_setup_widget (widget, account, param->name); - } - - g_free (param_name_formatted); - } - - mc_protocol_free_params_list (params); - g_object_unref (profile); - g_object_unref (protocol); -} - -static void -account_widget_handle_params_valist (EmpathyAccount *account, - GtkBuilder *gui, - const gchar *first_widget, - va_list args) -{ - GObject *object; - const gchar *name; - - for (name = first_widget; name; name = va_arg (args, const gchar *)) { - const gchar *param_name; - - param_name = va_arg (args, const gchar *); - object = gtk_builder_get_object (gui, name); - - if (!object) { - g_warning ("Builder is missing object '%s'.", name); - continue; - } - - account_widget_setup_widget (GTK_WIDGET (object), account, param_name); - } + GError *error = NULL; + EmpathyAccount *account = EMPATHY_ACCOUNT (source_object); + EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data); + + empathy_account_set_enabled_finish (account, res, &error); + + if (error != NULL) + { + DEBUG ("Could not automatically enable new account: %s", error->message); + g_error_free (error); + } + else + { + g_signal_emit (widget, signals[ACCOUNT_CREATED], 0); + } } -void -empathy_account_widget_handle_params (EmpathyAccount *account, - GtkBuilder *gui, - const gchar *first_widget, - ...) +static void +account_widget_applied_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - va_list args; + GError *error = NULL; + EmpathyAccount *account; + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source_object); + EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data); + EmpathyAccountWidgetPriv *priv = GET_PRIV (widget); + + empathy_account_settings_apply_finish (settings, res, &error); + + if (error != NULL) + { + DEBUG ("Could not apply changes to account: %s", error->message); + g_error_free (error); + return; + } + + account = empathy_account_settings_get_account (priv->settings); + + if (priv->creating_account) + { + /* By default, when an account is created, we enable it. */ + empathy_account_set_enabled_async (account, TRUE, + account_widget_account_enabled_cb, widget); + } + else if (account != NULL && priv->enabled_checkbox != NULL) + { + gboolean enabled_checked; + + enabled_checked = gtk_toggle_button_get_active ( + GTK_TOGGLE_BUTTON (priv->enabled_checkbox)); + + if (empathy_account_is_enabled (account)) + { + /* We want to disable the account (and possibly re-enable it) to make + * sure that the new settings are effective */ + priv->re_enable_accound = enabled_checked; + empathy_account_set_enabled_async (account, FALSE, NULL, NULL); + } + else + { + /* The account is already disable so we just enable it according + * to the value of the "Enabled" checkbox */ + empathy_account_set_enabled_async (account, enabled_checked, + NULL, NULL); + } + } + + account_widget_set_control_buttons_sensitivity (widget, FALSE); +} - g_return_if_fail (GTK_IS_BUILDER (gui)); +static void +account_widget_apply_clicked_cb (GtkWidget *button, + EmpathyAccountWidget *self) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); - va_start (args, first_widget); - account_widget_handle_params_valist (account, gui, first_widget, args); - va_end (args); + empathy_account_settings_apply_async (priv->settings, + account_widget_applied_cb, self); } -void -empathy_account_widget_add_forget_button (EmpathyAccount *account, - GtkBuilder *gui, - const gchar *button, - const gchar *entry) +static void +account_widget_setup_generic (EmpathyAccountWidget *self) { - GtkWidget *button_forget; - GtkWidget *entry_password; - gchar *password = NULL; + GtkWidget *table_common_settings; + GtkWidget *table_advanced_settings; - button_forget = GTK_WIDGET (gtk_builder_get_object (gui, button)); - entry_password = GTK_WIDGET (gtk_builder_get_object (gui, entry)); + table_common_settings = GTK_WIDGET (gtk_builder_get_object + (self->ui_details->gui, "table_common_settings")); + table_advanced_settings = GTK_WIDGET (gtk_builder_get_object + (self->ui_details->gui, "table_advanced_settings")); - password = empathy_account_get_param_string (account, "password"); - gtk_widget_set_sensitive (button_forget, !EMP_STR_EMPTY (password)); - g_free (password); + accounts_widget_generic_setup (self, table_common_settings, + table_advanced_settings); - g_signal_connect (button_forget, "clicked", - G_CALLBACK (account_widget_forget_clicked_cb), - entry_password); - g_signal_connect (entry_password, "changed", - G_CALLBACK (account_widget_password_changed_cb), - button_forget); + g_object_unref (self->ui_details->gui); } -void -empathy_account_widget_set_default_focus (GtkBuilder *gui, - const gchar *entry) +static void +account_widget_settings_ready_cb (EmpathyAccountSettings *settings, + GParamSpec *pspec, + gpointer user_data) { - GObject *default_focus_entry; + EmpathyAccountWidget *self = user_data; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); - default_focus_entry = gtk_builder_get_object (gui, entry); - g_signal_connect (default_focus_entry, "realize", - G_CALLBACK (gtk_widget_grab_focus), - NULL); + if (empathy_account_settings_is_ready (priv->settings)) + account_widget_setup_generic (self); } -GtkWidget * -empathy_account_widget_generic_new (EmpathyAccount *account) +static void +account_widget_build_generic (EmpathyAccountWidget *self, + const char *filename) { - GtkBuilder *gui; - GtkWidget *widget; - GtkWidget *table_common_settings; - GtkWidget *table_advanced_settings; - gchar *filename; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + GtkWidget *expander_advanced; - filename = empathy_file_lookup ("empathy-account-widget-generic.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_generic_settings", &widget, - "table_common_settings", &table_common_settings, - "table_advanced_settings", &table_advanced_settings, - NULL); - g_free (filename); + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", &priv->table_common_settings, + "vbox_generic_settings", &self->ui_details->widget, + "expander_advanced_settings", &expander_advanced, + NULL); - accounts_widget_generic_setup (account, table_common_settings, table_advanced_settings); + if (priv->simple) + gtk_widget_hide (expander_advanced); - return empathy_builder_unref_and_keep_widget (gui, widget); + g_object_ref (self->ui_details->gui); + + if (empathy_account_settings_is_ready (priv->settings)) + account_widget_setup_generic (self); + else + g_signal_connect (priv->settings, "notify::ready", + G_CALLBACK (account_widget_settings_ready_cb), self); } -GtkWidget * -empathy_account_widget_salut_new (EmpathyAccount *account) +static void +account_widget_build_salut (EmpathyAccountWidget *self, + const char *filename) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", &priv->table_common_settings, + "vbox_salut_settings", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_published", "published-name", + "entry_nickname", "nickname", + "entry_first_name", "first-name", + "entry_last_name", "last-name", + "entry_email", "email", + "entry_jid", "jid", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_nickname"); +} + +static void +account_widget_build_msn (EmpathyAccountWidget *self, + const char *filename) { - GtkBuilder *gui; - GtkWidget *widget; - gchar *filename; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + if (priv->simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_msn_simple", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id_simple"); + } + else + { + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_msn_settings", &priv->table_common_settings, + "vbox_msn_settings", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id", "account", + "entry_password", "password", + "entry_server", "server", + "spinbutton_port", "port", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id"); + self->ui_details->add_forget = TRUE; + } +} - filename = empathy_file_lookup ("empathy-account-widget-salut.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_salut_settings", &widget, - NULL); - g_free (filename); +static void +account_widget_build_jabber (EmpathyAccountWidget *self, + const char *filename) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + GtkWidget *spinbutton_port; + GtkWidget *checkbutton_ssl; + GtkWidget *label_id, *label_password; + GtkWidget *label_id_create, *label_password_create; + + if (priv->simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_jabber_simple", &self->ui_details->widget, + "label_id_simple", &label_id, + "label_id_create", &label_id_create, + "label_password_simple", &label_password, + "label_password_create", &label_password_create, + NULL); + + if (empathy_account_settings_get_boolean (priv->settings, "register")) + { + gtk_widget_hide (label_id); + gtk_widget_hide (label_password); + gtk_widget_show (label_id_create); + gtk_widget_show (label_password_create); + } + + empathy_account_widget_handle_params (self, + "entry_id_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id_simple"); + } + else + { + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", &priv->table_common_settings, + "vbox_jabber_settings", &self->ui_details->widget, + "spinbutton_port", &spinbutton_port, + "checkbutton_ssl", &checkbutton_ssl, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id", "account", + "entry_password", "password", + "entry_resource", "resource", + "entry_server", "server", + "spinbutton_port", "port", + "spinbutton_priority", "priority", + "checkbutton_ssl", "old-ssl", + "checkbutton_ignore_ssl_errors", "ignore-ssl-errors", + "checkbutton_encryption", "require-encryption", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id"); + self->ui_details->add_forget = TRUE; + priv->spinbutton_port = spinbutton_port; + + g_signal_connect (checkbutton_ssl, "toggled", + G_CALLBACK (account_widget_jabber_ssl_toggled_cb), + self); + } +} - empathy_account_widget_handle_params (account, gui, - "entry_published", "published-name", - "entry_nickname", "nickname", - "entry_first_name", "first-name", - "entry_last_name", "last-name", - "entry_email", "email", - "entry_jid", "jid", - NULL); +static void +account_widget_build_icq (EmpathyAccountWidget *self, + const char *filename) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + GtkWidget *spinbutton_port; + + if (priv->simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_icq_simple", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_uin_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_uin_simple"); + } + else + { + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", &priv->table_common_settings, + "vbox_icq_settings", &self->ui_details->widget, + "spinbutton_port", &spinbutton_port, + NULL); + + empathy_account_widget_handle_params (self, + "entry_uin", "account", + "entry_password", "password", + "entry_server", "server", + "spinbutton_port", "port", + "entry_charset", "charset", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_uin"); + self->ui_details->add_forget = TRUE; + } +} - empathy_account_widget_set_default_focus (gui, "entry_nickname"); +static void +account_widget_build_aim (EmpathyAccountWidget *self, + const char *filename) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + GtkWidget *spinbutton_port; + + if (priv->simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_aim_simple", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_screenname_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_screenname_simple"); + } + else + { + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", &priv->table_common_settings, + "vbox_aim_settings", &self->ui_details->widget, + "spinbutton_port", &spinbutton_port, + NULL); + + empathy_account_widget_handle_params (self, + "entry_screenname", "account", + "entry_password", "password", + "entry_server", "server", + "spinbutton_port", "port", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_screenname"); + self->ui_details->add_forget = TRUE; + } +} - return empathy_builder_unref_and_keep_widget (gui, widget); +static void +account_widget_build_yahoo (EmpathyAccountWidget *self, + const char *filename) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + if (priv->simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_yahoo_simple", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id_simple"); + } + else + { + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_settings", &priv->table_common_settings, + "vbox_yahoo_settings", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id", "account", + "entry_password", "password", + "entry_server", "server", + "entry_locale", "room-list-locale", + "entry_charset", "charset", + "spinbutton_port", "port", + "checkbutton_yahoojp", "yahoojp", + "checkbutton_ignore_invites", "ignore-invites", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id"); + self->ui_details->add_forget = TRUE; + } } -GtkWidget * -empathy_account_widget_msn_new (EmpathyAccount *account) +static void +account_widget_build_groupwise (EmpathyAccountWidget *self, + const char *filename) { - GtkBuilder *gui; - GtkWidget *widget; - gchar *filename; + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + if (priv->simple) + { + self->ui_details->gui = empathy_builder_get_file (filename, + "vbox_groupwise_simple", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id_simple", "account", + "entry_password_simple", "password", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id_simple"); + } + else + { + self->ui_details->gui = empathy_builder_get_file (filename, + "table_common_groupwise_settings", &priv->table_common_settings, + "vbox_groupwise_settings", &self->ui_details->widget, + NULL); + + empathy_account_widget_handle_params (self, + "entry_id", "account", + "entry_password", "password", + "entry_server", "server", + "spinbutton_port", "port", + NULL); + + self->ui_details->default_focus = g_strdup ("entry_id"); + self->ui_details->add_forget = TRUE; + } +} - filename = empathy_file_lookup ("empathy-account-widget-msn.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_msn_settings", &widget, - NULL); - g_free (filename); +static void +account_widget_destroy_cb (GtkWidget *widget, + EmpathyAccountWidget *self) +{ + g_object_unref (self); +} - empathy_account_widget_handle_params (account, gui, - "entry_id", "account", - "entry_password", "password", - "entry_server", "server", - "spinbutton_port", "port", - NULL); +static void +empathy_account_widget_enabled_cb (EmpathyAccount *account, + GParamSpec *spec, + gpointer user_data) +{ + EmpathyAccountWidget *widget = EMPATHY_ACCOUNT_WIDGET (user_data); + EmpathyAccountWidgetPriv *priv = GET_PRIV (widget); + gboolean enabled = empathy_account_is_enabled (account); + + if (!enabled && priv->re_enable_accound) + { + /* The account has been disabled because we were applying changes. + * However, the user wants the account to be enabled so let's re-enable + * it */ + empathy_account_set_enabled_async (account, TRUE, NULL, NULL); + } + else if (priv->enabled_checkbox != NULL) + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->enabled_checkbox), + enabled); + } +} - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); +static void +account_widget_enabled_toggled_cb (GtkToggleButton *toggle_button, + gpointer user_data) +{ + account_widget_handle_control_buttons_sensitivity ( + EMPATHY_ACCOUNT_WIDGET (user_data)); +} - empathy_account_widget_set_default_focus (gui, "entry_id"); +static void +do_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (object); + + switch (prop_id) + { + case PROP_PROTOCOL: + priv->protocol = g_value_dup_string (value); + break; + case PROP_SETTINGS: + priv->settings = g_value_dup_object (value); + break; + case PROP_SIMPLE: + priv->simple = g_value_get_boolean (value); + break; + case PROP_CREATING_ACCOUNT: + priv->creating_account = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} - return empathy_builder_unref_and_keep_widget (gui, widget); +static void +do_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountWidgetPriv *priv = GET_PRIV (object); + + switch (prop_id) + { + case PROP_PROTOCOL: + g_value_set_string (value, priv->protocol); + break; + case PROP_SETTINGS: + g_value_set_object (value, priv->settings); + break; + case PROP_SIMPLE: + g_value_set_boolean (value, priv->simple); + break; + case PROP_CREATING_ACCOUNT: + g_value_set_boolean (value, priv->creating_account); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } } -GtkWidget * -empathy_account_widget_jabber_new (EmpathyAccount *account) -{ - GtkBuilder *gui; - GtkWidget *widget; - GtkWidget *spinbutton_port; - GtkWidget *checkbutton_ssl; - gchar *filename; - - filename = empathy_file_lookup ("empathy-account-widget-jabber.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_jabber_settings", &widget, - "spinbutton_port", &spinbutton_port, - "checkbutton_ssl", &checkbutton_ssl, - NULL); - g_free (filename); - - empathy_account_widget_handle_params (account, gui, - "entry_id", "account", - "entry_password", "password", - "entry_resource", "resource", - "entry_server", "server", - "spinbutton_port", "port", - "spinbutton_priority", "priority", - "checkbutton_ssl", "old-ssl", - "checkbutton_ignore_ssl_errors", "ignore-ssl-errors", - "checkbutton_encryption", "require-encryption", - NULL); - - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); - - empathy_account_widget_set_default_focus (gui, "entry_id"); - - g_signal_connect (checkbutton_ssl, "toggled", - G_CALLBACK (account_widget_jabber_ssl_toggled_cb), - spinbutton_port); - - return empathy_builder_unref_and_keep_widget (gui, widget); +static void +do_constructed (GObject *obj) +{ + EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj); + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + EmpathyAccount *account; + char *uiname, *filename; + + uiname = g_strconcat ("empathy-account-widget-", priv->protocol, + ".ui", NULL); + filename = empathy_file_lookup (uiname, "libempathy-gtk"); + + if (!tp_strdiff (priv->protocol, "local-xmpp")) + account_widget_build_salut (self, filename); + else if (!tp_strdiff (priv->protocol, "msn")) + account_widget_build_msn (self, filename); + else if (!tp_strdiff (priv->protocol, "jabber")) + account_widget_build_jabber (self, filename); + else if (!tp_strdiff (priv->protocol, "icq")) + account_widget_build_icq (self, filename); + else if (!tp_strdiff (priv->protocol, "aim")) + account_widget_build_aim (self, filename); + else if (!tp_strdiff (priv->protocol, "yahoo")) + account_widget_build_yahoo (self, filename); + else if (!tp_strdiff (priv->protocol, "groupwise")) + account_widget_build_groupwise (self, filename); + else if (!tp_strdiff (priv->protocol, "irc")) + empathy_account_widget_irc_build (self, filename, + &priv->table_common_settings); + else if (!tp_strdiff (priv->protocol, "sip")) + empathy_account_widget_sip_build (self, filename, + &priv->table_common_settings); + else if (!tp_strdiff (priv->protocol, "generic")) + account_widget_build_generic (self, filename); + else + { + g_free (filename); + + filename = empathy_file_lookup ( + "empathy-account-widget-generic.ui", "libempathy-gtk"); + account_widget_build_generic (self, filename); + } + + g_free (uiname); + g_free (filename); + + /* handle default focus */ + if (self->ui_details->default_focus != NULL) + { + GObject *default_focus_entry; + + default_focus_entry = gtk_builder_get_object + (self->ui_details->gui, self->ui_details->default_focus); + g_signal_connect (default_focus_entry, "realize", + G_CALLBACK (gtk_widget_grab_focus), + NULL); + } + + /* handle forget button */ + if (self->ui_details->add_forget) + { + const gchar *password = NULL; + + priv->button_forget = GTK_WIDGET (gtk_builder_get_object + (self->ui_details->gui, "button_forget")); + priv->entry_password = GTK_WIDGET (gtk_builder_get_object + (self->ui_details->gui, "entry_password")); + + password = empathy_account_settings_get_string (priv->settings, + "password"); + gtk_widget_set_sensitive (priv->button_forget, + !EMP_STR_EMPTY (password)); + + g_signal_connect (priv->button_forget, "clicked", + G_CALLBACK (account_widget_forget_clicked_cb), + self); + g_signal_connect (priv->entry_password, "changed", + G_CALLBACK (account_widget_password_changed_cb), + self); + } + + /* handle apply and cancel button */ + if (!priv->simple) + { + GtkWidget *hbox = gtk_hbox_new (TRUE, 3); + + priv->cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL); + priv->apply_button = gtk_button_new_from_stock ( + priv->creating_account ? GTK_STOCK_CONNECT : GTK_STOCK_APPLY); + + gtk_box_pack_end (GTK_BOX (hbox), priv->apply_button, TRUE, + TRUE, 3); + gtk_box_pack_end (GTK_BOX (hbox), priv->cancel_button, TRUE, + TRUE, 3); + + gtk_box_pack_end (GTK_BOX (self->ui_details->widget), hbox, FALSE, + FALSE, 3); + + g_signal_connect (priv->cancel_button, "clicked", + G_CALLBACK (account_widget_cancel_clicked_cb), + self); + g_signal_connect (priv->apply_button, "clicked", + G_CALLBACK (account_widget_apply_clicked_cb), + self); + gtk_widget_show_all (hbox); + account_widget_set_control_buttons_sensitivity (self, FALSE); + } + + account = empathy_account_settings_get_account (priv->settings); + + if (account != NULL) + { + g_signal_connect (account, "notify::enabled", + G_CALLBACK (empathy_account_widget_enabled_cb), self); + } + + /* handle the "Enabled" checkbox. We only add it when modifying an account */ + if (!priv->creating_account && priv->table_common_settings != NULL) + { + guint nb_rows, nb_columns; + + priv->enabled_checkbox = + gtk_check_button_new_with_label (_("Enabled")); + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (priv->enabled_checkbox), + empathy_account_is_enabled (account)); + + g_object_get (priv->table_common_settings, "n-rows", &nb_rows, + "n-columns", &nb_columns, NULL); + + gtk_table_resize (GTK_TABLE (priv->table_common_settings), ++nb_rows, + nb_columns); + + gtk_table_attach (GTK_TABLE (priv->table_common_settings), + priv->enabled_checkbox, 0, nb_columns, nb_rows - 1, nb_rows, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + + gtk_widget_show (priv->enabled_checkbox); + + g_signal_connect (G_OBJECT (priv->enabled_checkbox), "toggled", + G_CALLBACK (account_widget_enabled_toggled_cb), self); + } + + /* hook up to widget destruction to unref ourselves */ + g_signal_connect (self->ui_details->widget, "destroy", + G_CALLBACK (account_widget_destroy_cb), self); + + empathy_builder_unref_and_keep_widget (self->ui_details->gui, + self->ui_details->widget); + self->ui_details->gui = NULL; } -GtkWidget * -empathy_account_widget_icq_new (EmpathyAccount *account) +static void +do_dispose (GObject *obj) { - GtkBuilder *gui; - GtkWidget *widget; - GtkWidget *spinbutton_port; - gchar *filename; + EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj); + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); + + if (priv->dispose_run) + return; - filename = empathy_file_lookup ("empathy-account-widget-icq.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_icq_settings", &widget, - "spinbutton_port", &spinbutton_port, - NULL); - g_free (filename); + priv->dispose_run = TRUE; - empathy_account_widget_handle_params (account, gui, - "entry_uin", "account", - "entry_password", "password", - "entry_server", "server", - "spinbutton_port", "port", - "entry_charset", "charset", - NULL); + empathy_account_settings_is_ready (priv->settings); - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); + if (priv->settings != NULL) + { + EmpathyAccount *account; + account = empathy_account_settings_get_account (priv->settings); - empathy_account_widget_set_default_focus (gui, "entry_uin"); + if (account != NULL) + { + g_signal_handlers_disconnect_by_func (account, + empathy_account_widget_enabled_cb, self); + } - return empathy_builder_unref_and_keep_widget (gui, widget); + g_object_unref (priv->settings); + priv->settings = NULL; + } + + if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose != NULL) + G_OBJECT_CLASS (empathy_account_widget_parent_class)->dispose (obj); } -GtkWidget * -empathy_account_widget_aim_new (EmpathyAccount *account) +static void +do_finalize (GObject *obj) { - GtkBuilder *gui; - GtkWidget *widget; - GtkWidget *spinbutton_port; - gchar *filename; - - filename = empathy_file_lookup ("empathy-account-widget-aim.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_aim_settings", &widget, - "spinbutton_port", &spinbutton_port, - NULL); - g_free (filename); + EmpathyAccountWidget *self = EMPATHY_ACCOUNT_WIDGET (obj); + EmpathyAccountWidgetPriv *priv = GET_PRIV (self); - empathy_account_widget_handle_params (account, gui, - "entry_screenname", "account", - "entry_password", "password", - "entry_server", "server", - "spinbutton_port", "port", - NULL); + g_free (self->ui_details->default_focus); + g_slice_free (EmpathyAccountWidgetUIDetails, self->ui_details); - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); + g_free (priv->protocol); - empathy_account_widget_set_default_focus (gui, "entry_screenname"); + if (G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize != NULL) + G_OBJECT_CLASS (empathy_account_widget_parent_class)->finalize (obj); +} - return empathy_builder_unref_and_keep_widget (gui, widget); +static void +empathy_account_widget_class_init (EmpathyAccountWidgetClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + oclass->get_property = do_get_property; + oclass->set_property = do_set_property; + oclass->constructed = do_constructed; + oclass->dispose = do_dispose; + oclass->finalize = do_finalize; + + param_spec = g_param_spec_string ("protocol", + "protocol", "The protocol of the account", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PROTOCOL, param_spec); + + param_spec = g_param_spec_object ("settings", + "settings", "The settings of the account", + EMPATHY_TYPE_ACCOUNT_SETTINGS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_SETTINGS, param_spec); + + param_spec = g_param_spec_boolean ("simple", + "simple", "Whether the account widget is a simple or an advanced one", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_SIMPLE, param_spec); + + param_spec = g_param_spec_boolean ("creating-account", + "creating-account", + "TRUE if we're creating an account, FALSE if we're modifying it", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_CREATING_ACCOUNT, param_spec); + + signals[HANDLE_APPLY] = + g_signal_new ("handle-apply", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, + 1, G_TYPE_BOOLEAN); + + /* This signal is emitted when an account has been created and enabled. */ + signals[ACCOUNT_CREATED] = + g_signal_new ("account-created", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + signals[CANCELLED] = + g_signal_new ("cancelled", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private (klass, sizeof (EmpathyAccountWidgetPriv)); } -GtkWidget * -empathy_account_widget_yahoo_new (EmpathyAccount *account) +static void +empathy_account_widget_init (EmpathyAccountWidget *self) { - GtkBuilder *gui; - GtkWidget *widget; - gchar *filename; + EmpathyAccountWidgetPriv *priv = + G_TYPE_INSTANCE_GET_PRIVATE ((self), EMPATHY_TYPE_ACCOUNT_WIDGET, + EmpathyAccountWidgetPriv); - filename = empathy_file_lookup ("empathy-account-widget-yahoo.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_yahoo_settings", &widget, - NULL); - g_free (filename); + self->priv = priv; + priv->dispose_run = FALSE; - empathy_account_widget_handle_params (account, gui, - "entry_id", "account", - "entry_password", "password", - "entry_server", "server", - "entry_locale", "room-list-locale", - "entry_charset", "charset", - "spinbutton_port", "port", - "checkbutton_yahoojp", "yahoojp", - "checkbutton_ignore_invites", "ignore-invites", - NULL); + self->ui_details = g_slice_new0 (EmpathyAccountWidgetUIDetails); +} - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); +/* public methods */ - empathy_account_widget_set_default_focus (gui, "entry_id"); +void +empathy_account_widget_handle_params (EmpathyAccountWidget *self, + const gchar *first_widget, + ...) +{ + va_list args; - return empathy_builder_unref_and_keep_widget (gui, widget); + va_start (args, first_widget); + account_widget_handle_params_valist (self, first_widget, args); + va_end (args); } GtkWidget * -empathy_account_widget_groupwise_new (EmpathyAccount *account) +empathy_account_widget_get_widget (EmpathyAccountWidget *widget) { - GtkBuilder *gui; - GtkWidget *widget; - gchar *filename; - - filename = empathy_file_lookup ("empathy-account-widget-groupwise.ui", - "libempathy-gtk"); - gui = empathy_builder_get_file (filename, - "vbox_groupwise_settings", &widget, - NULL); - g_free (filename); + return widget->ui_details->widget; +} - empathy_account_widget_handle_params (account, gui, - "entry_id", "account", - "entry_password", "password", - "entry_server", "server", - "spinbutton_port", "port", - NULL); +EmpathyAccountWidget * +empathy_account_widget_new_for_protocol (const char *protocol, + EmpathyAccountSettings *settings, + gboolean simple) +{ + EmpathyAccountWidget *self; - empathy_account_widget_add_forget_button (account, gui, - "button_forget", - "entry_password"); + g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), NULL); + g_return_val_if_fail (protocol != NULL, NULL); - empathy_account_widget_set_default_focus (gui, "entry_id"); + self = g_object_new + (EMPATHY_TYPE_ACCOUNT_WIDGET, "protocol", protocol, + "settings", settings, "simple", simple, + "creating-account", + empathy_account_settings_get_account (settings) == NULL, + NULL); - return empathy_builder_unref_and_keep_widget (gui, widget); + return self; } - diff --git a/libempathy-gtk/empathy-account-widget.h b/libempathy-gtk/empathy-account-widget.h index 7a76db9e0..415934a2d 100644 --- a/libempathy-gtk/empathy-account-widget.h +++ b/libempathy-gtk/empathy-account-widget.h @@ -1,4 +1,3 @@ -/* -*- 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. @@ -22,34 +21,51 @@ * Martyn Russell <martyn@imendio.com> */ -#ifndef __EMPATHY_ACCOUNT_WIDGET_GENERIC_H__ -#define __EMPATHY_ACCOUNT_WIDGET_GENERIC_H__ +#ifndef __EMPATHY_ACCOUNT_WIDGET_H__ +#define __EMPATHY_ACCOUNT_WIDGET_H__ #include <gtk/gtk.h> -#include <libempathy/empathy-account.h> +#include <libempathy/empathy-account-settings.h> G_BEGIN_DECLS -void empathy_account_widget_handle_params (EmpathyAccount *account, - GtkBuilder *gui, - const gchar *first_widget, - ...); -void empathy_account_widget_add_forget_button (EmpathyAccount *account, - GtkBuilder *gui, - const gchar *button, - const gchar *entry); -void empathy_account_widget_set_default_focus (GtkBuilder *gui, - const gchar *entry); -GtkWidget *empathy_account_widget_generic_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_salut_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_msn_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_jabber_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_icq_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_aim_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_yahoo_new (EmpathyAccount *account); -GtkWidget *empathy_account_widget_groupwise_new (EmpathyAccount *account); +#define EMPATHY_TYPE_ACCOUNT_WIDGET empathy_account_widget_get_type() +#define EMPATHY_ACCOUNT_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_ACCOUNT_WIDGET, EmpathyAccountWidget)) +#define EMPATHY_ACCOUNT_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_ACCOUNT_WIDGET, EmpathyAccountWidgetClass)) +#define EMPATHY_IS_ACCOUNT_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_ACCOUNT_WIDGET)) +#define EMPATHY_IS_ACCOUNT_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_ACCOUNT_WIDGET)) +#define EMPATHY_ACCOUNT_WIDGET_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT_WIDGET, EmpathyAccountWidgetClass)) + +typedef struct _EmpathyAccountWidgetUIDetails EmpathyAccountWidgetUIDetails; + +typedef struct { + GObject parent; + + EmpathyAccountWidgetUIDetails *ui_details; + + /* private */ + gpointer priv; +} EmpathyAccountWidget; + +typedef struct { + GObjectClass parent_class; +} EmpathyAccountWidgetClass; + +GType empathy_account_widget_get_type (void); + +GtkWidget *empathy_account_widget_get_widget (EmpathyAccountWidget *widget); + +EmpathyAccountWidget * empathy_account_widget_new_for_protocol ( + const char *protocol, + EmpathyAccountSettings *settings, + gboolean simple); G_END_DECLS -#endif /* __EMPATHY_ACCOUNT_WIDGET_GENERIC_H__ */ +#endif /* __EMPATHY_ACCOUNT_WIDGET_H__ */ diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index 9fa51fb85..9096beeae 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -203,8 +203,9 @@ chat_new_connection_cb (EmpathyAccountManager *manager, EmpathyChatPriv *priv = GET_PRIV (chat); EmpathyAccount *account; - account = empathy_account_manager_get_account (manager, connection); - if (!priv->tp_chat && empathy_account_equal (account, priv->account) && + account = empathy_account_manager_get_account_for_connection (manager, + connection); + if (!priv->tp_chat && account == priv->account && priv->handle_type != TP_HANDLE_TYPE_NONE && !EMP_STR_EMPTY (priv->id)) { @@ -1781,7 +1782,8 @@ empathy_chat_set_tp_chat (EmpathyChat *chat, priv->tp_chat = g_object_ref (tp_chat); connection = empathy_tp_chat_get_connection (priv->tp_chat); - priv->account = empathy_account_manager_get_account (priv->account_manager, + priv->account = empathy_account_manager_get_account_for_connection ( + priv->account_manager, connection); g_object_ref (priv->account); diff --git a/libempathy-gtk/empathy-contact-dialogs.c b/libempathy-gtk/empathy-contact-dialogs.c index 0ec8c8e3e..5c77a787e 100644 --- a/libempathy-gtk/empathy-contact-dialogs.c +++ b/libempathy-gtk/empathy-contact-dialogs.c @@ -27,8 +27,6 @@ #include <gtk/gtk.h> #include <glib/gi18n-lib.h> -#include <libmissioncontrol/mission-control.h> - #include <libempathy/empathy-contact-manager.h> #include <libempathy/empathy-account-manager.h> #include <libempathy/empathy-contact-list.h> diff --git a/libempathy-gtk/empathy-contact-list-view.c b/libempathy-gtk/empathy-contact-list-view.c index a4dfa0f59..dcbbb18bf 100644 --- a/libempathy-gtk/empathy-contact-list-view.c +++ b/libempathy-gtk/empathy-contact-list-view.c @@ -302,7 +302,7 @@ contact_list_view_drag_data_received (GtkWidget *view, account_id = strv[0]; contact_id = strv[1]; account_manager = empathy_account_manager_dup_singleton (); - account = empathy_account_manager_lookup (account_manager, account_id); + account = empathy_account_manager_get_account (account_manager, account_id); if (account) { TpConnection *connection; diff --git a/libempathy-gtk/empathy-irc-network-dialog.c b/libempathy-gtk/empathy-irc-network-dialog.c index e6b4a6f7f..8d4676417 100644 --- a/libempathy-gtk/empathy-irc-network-dialog.c +++ b/libempathy-gtk/empathy-irc-network-dialog.c @@ -27,8 +27,6 @@ #include <glib/gi18n-lib.h> #include <gtk/gtk.h> -#include <libmissioncontrol/mc-protocol.h> - #include <libempathy/empathy-utils.h> #include <libempathy/empathy-account.h> diff --git a/libempathy-gtk/empathy-log-window.c b/libempathy-gtk/empathy-log-window.c index f05017c9c..11ddca74b 100644 --- a/libempathy-gtk/empathy-log-window.c +++ b/libempathy-gtk/empathy-log-window.c @@ -419,7 +419,7 @@ log_window_find_populate (EmpathyLogWindow *window, date_readable = empathy_log_manager_get_date_readable (hit->date); account_name = empathy_account_get_display_name (hit->account); - account_icon = empathy_icon_name_from_account (hit->account); + account_icon = empathy_account_get_icon_name (hit->account); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, @@ -774,7 +774,7 @@ log_window_chats_set_selected (EmpathyLogWindow *window, COL_CHAT_IS_CHATROOM, &this_is_chatroom, -1); - if (empathy_account_equal (this_account, account) && + if (this_account == account && strcmp (this_chat_id, chat_id) == 0 && this_is_chatroom == is_chatroom) { gtk_tree_selection_select_iter (selection, &iter); diff --git a/libempathy-gtk/empathy-new-message-dialog.c b/libempathy-gtk/empathy-new-message-dialog.c index 77b368bd9..66b2adb2d 100644 --- a/libempathy-gtk/empathy-new-message-dialog.c +++ b/libempathy-gtk/empathy-new-message-dialog.c @@ -27,8 +27,6 @@ #include <gtk/gtk.h> #include <glib/gi18n-lib.h> -#include <libmissioncontrol/mission-control.h> - #include <libempathy/empathy-call-factory.h> #include <libempathy/empathy-tp-contact-factory.h> #include <libempathy/empathy-contact-manager.h> diff --git a/libempathy-gtk/empathy-profile-chooser.c b/libempathy-gtk/empathy-profile-chooser.c deleted file mode 100644 index b3cbf90d0..000000000 --- a/libempathy-gtk/empathy-profile-chooser.c +++ /dev/null @@ -1,324 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ -/* - * Copyright (C) 2007-2009 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> - * Jonny Lamb <jonny.lamb@collabora.co.uk> - */ - -#include <config.h> - -#include <string.h> - -#include <gtk/gtk.h> -#include <libmissioncontrol/mc-profile.h> -#include <libmissioncontrol/mc-protocol.h> - -#include <libempathy/empathy-utils.h> - -#include "empathy-profile-chooser.h" -#include "empathy-ui-utils.h" - -/** - * SECTION:empathy-profile-chooser - * @title: EmpathyProfileChooser - * @short_description: A widget used to choose from a list of profiles - * @include: libempathy-gtk/empathy-profile-chooser.h - * - * #EmpathyProfileChooser is a widget which extends #GtkComboBox to provides a - * chooser of available profiles. - */ - -/** - * EmpathyProfileChooser: - * @parent: parent object - * - * Widget which extends #GtkComboBox to provide a chooser of available - * profiles. - */ - -#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyProfileChooser) -typedef struct -{ - GtkListStore *store; - gboolean dispose_run; -} EmpathyProfileChooserPriv; - -enum -{ - COL_ICON, - COL_LABEL, - COL_PROFILE, - COL_COUNT -}; - -G_DEFINE_TYPE (EmpathyProfileChooser, empathy_profile_chooser, - GTK_TYPE_COMBO_BOX); - -static gint -profile_chooser_sort_profile_value (McProfile *profile) -{ - guint i; - const gchar *profile_name; - const gchar *names[] = { - "jabber", - "salut", - "gtalk", - NULL - }; - - profile_name = mc_profile_get_unique_name (profile); - - for (i = 0 ; names[i]; i++) - { - if (strcmp (profile_name, names[i]) == 0) - return i; - } - - return i; -} - -static gint -profile_chooser_sort_func (GtkTreeModel *model, - GtkTreeIter *iter_a, - GtkTreeIter *iter_b, - gpointer user_data) -{ - McProfile *profile_a; - McProfile *profile_b; - gint cmp; - - gtk_tree_model_get (model, iter_a, - COL_PROFILE, &profile_a, - -1); - gtk_tree_model_get (model, iter_b, - COL_PROFILE, &profile_b, - -1); - - cmp = profile_chooser_sort_profile_value (profile_a); - cmp -= profile_chooser_sort_profile_value (profile_b); - if (cmp == 0) - { - cmp = strcmp (mc_profile_get_display_name (profile_a), - mc_profile_get_display_name (profile_b)); - } - - g_object_unref (profile_a); - g_object_unref (profile_b); - - return cmp; -} - -static void -profile_chooser_constructed (GObject *object) -{ - EmpathyProfileChooser *profile_chooser; - EmpathyProfileChooserPriv *priv; - - GList *profiles, *l, *seen; - GtkCellRenderer *renderer; - GtkTreeIter iter; - gboolean iter_set = FALSE; - McManager *btf_cm; - - priv = GET_PRIV (object); - profile_chooser = EMPATHY_PROFILE_CHOOSER (object); - - /* set up combo box with new store */ - priv->store = gtk_list_store_new (COL_COUNT, - G_TYPE_STRING, /* Icon name */ - G_TYPE_STRING, /* Label */ - MC_TYPE_PROFILE); /* Profile */ - - gtk_combo_box_set_model (GTK_COMBO_BOX (object), - GTK_TREE_MODEL (priv->store)); - - renderer = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, FALSE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer, - "icon-name", COL_ICON, - NULL); - g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer, - "text", COL_LABEL, - NULL); - - btf_cm = mc_manager_lookup ("butterfly"); - profiles = mc_profiles_list (); - seen = NULL; - for (l = profiles; l; l = g_list_next (l)) - { - McProfile *profile; - McProtocol *protocol; - const gchar *unique_name; - - profile = l->data; - - /* Check if the CM is installed, otherwise skip that profile. - * Workaround SF bug #1688779 */ - protocol = mc_profile_get_protocol (profile); - if (!protocol) - continue; - - g_object_unref (protocol); - - /* Skip MSN-Haze if we have butterfly */ - unique_name = mc_profile_get_unique_name (profile); - if (btf_cm && strcmp (unique_name, "msn-haze") == 0) - continue; - - if (g_list_find_custom (seen, unique_name, (GCompareFunc) strcmp)) - continue; - - seen = g_list_append (seen, (char *) unique_name); - - gtk_list_store_insert_with_values (priv->store, &iter, 0, - COL_ICON, mc_profile_get_icon_name (profile), - COL_LABEL, mc_profile_get_display_name (profile), - COL_PROFILE, profile, - -1); - iter_set = TRUE; - } - - g_list_free (seen); - - if (btf_cm) - g_object_unref (btf_cm); - - /* Set the profile sort function */ - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->store), - COL_PROFILE, - profile_chooser_sort_func, - NULL, NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store), - COL_PROFILE, - GTK_SORT_ASCENDING); - - if (iter_set) - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (object), &iter); - - mc_profiles_free_list (profiles); - - if (G_OBJECT_CLASS (empathy_profile_chooser_parent_class)->constructed) - G_OBJECT_CLASS (empathy_profile_chooser_parent_class)->constructed (object); -} - -static void -empathy_profile_chooser_init (EmpathyProfileChooser *profile_chooser) -{ - EmpathyProfileChooserPriv *priv = - G_TYPE_INSTANCE_GET_PRIVATE (profile_chooser, - EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooserPriv); - - priv->dispose_run = FALSE; - - profile_chooser->priv = priv; -} - -static void -profile_chooser_dispose (GObject *object) -{ - EmpathyProfileChooser *profile_chooser = EMPATHY_PROFILE_CHOOSER (object); - EmpathyProfileChooserPriv *priv = GET_PRIV (profile_chooser); - - if (priv->dispose_run) - return; - - priv->dispose_run = TRUE; - - if (priv->store) - { - g_object_unref (priv->store); - priv->store = NULL; - } - - (G_OBJECT_CLASS (empathy_profile_chooser_parent_class)->dispose) (object); -} - -static void -empathy_profile_chooser_class_init (EmpathyProfileChooserClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = profile_chooser_constructed; - object_class->dispose = profile_chooser_dispose; - - g_type_class_add_private (object_class, sizeof (EmpathyProfileChooserPriv)); -} - -/** - * empathy_profile_chooser_dup_selected: - * @profile_chooser: an #EmpathyProfileChooser - * - * Returns a new reference to the selected #McProfile in @profile_chooser. The - * returned #McProfile should be unrefed with g_object_unref() when finished - * with. - * - * Return value: a new reference to the selected #McProfile - */ -McProfile * -empathy_profile_chooser_dup_selected (EmpathyProfileChooser *profile_chooser) -{ - EmpathyProfileChooserPriv *priv = GET_PRIV (profile_chooser); - GtkTreeIter iter; - McProfile *profile = NULL; - - g_return_val_if_fail (EMPATHY_IS_PROFILE_CHOOSER (profile_chooser), NULL); - - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (profile_chooser), &iter)) - { - gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter, - COL_PROFILE, &profile, - -1); - } - - return profile; -} - -/** - * empathy_profile_chooser_n_profiles: - * @profile_chooser: an #EmpathyProfileChooser - * - * Returns the number of profiles in @profile_chooser. - * - * Return value: the number of profiles in @profile_chooser - */ -gint -empathy_profile_chooser_n_profiles (EmpathyProfileChooser *profile_chooser) -{ - EmpathyProfileChooserPriv *priv = GET_PRIV (profile_chooser); - - g_return_val_if_fail (EMPATHY_IS_PROFILE_CHOOSER (profile_chooser), 0); - - return gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->store), NULL); -} - -/** - * empathy_profile_chooser_new: - * - * Creates a new #EmpathyProfileChooser widget. - * - * Return value: a new #EmpathyProfileChooser widget - */ -GtkWidget * -empathy_profile_chooser_new (void) -{ - return GTK_WIDGET (g_object_new (EMPATHY_TYPE_PROFILE_CHOOSER, NULL)); -} diff --git a/libempathy-gtk/empathy-profile-chooser.h b/libempathy-gtk/empathy-profile-chooser.h deleted file mode 100644 index 37d7241a9..000000000 --- a/libempathy-gtk/empathy-profile-chooser.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ -/* - * Copyright (C) 2007-2009 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> - * Jonny Lamb <jonny.lamb@collabora.co.uk - */ - -#ifndef __EMPATHY_PROFILE_CHOOSER_H__ -#define __EMPATHY_PROFILE_CHOOSER_H__ - -#include <glib-object.h> -#include <gtk/gtk.h> - -#include <libmissioncontrol/mc-profile.h> - -G_BEGIN_DECLS - -#define EMPATHY_TYPE_PROFILE_CHOOSER (empathy_profile_chooser_get_type ()) -#define EMPATHY_PROFILE_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ - EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooser)) -#define EMPATHY_PROFILE_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \ - EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooserClass)) -#define EMPATHY_IS_PROFILE_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ - EMPATHY_TYPE_PROFILE_CHOOSER)) -#define EMPATHY_IS_PROFILE_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \ - EMPATHY_TYPE_PROFILE_CHOOSER)) -#define EMPATHY_PROFILE_CHOOSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), \ - EMPATHY_TYPE_PROFILE_CHOOSER, EmpathyProfileChooserClass)) - -typedef struct _EmpathyProfileChooser EmpathyProfileChooser; -typedef struct _EmpathyProfileChooserClass EmpathyProfileChooserClass; - -struct _EmpathyProfileChooser -{ - GtkComboBox parent; - - /*<private>*/ - gpointer priv; -}; - -struct _EmpathyProfileChooserClass -{ - GtkComboBoxClass parent_class; -}; - -GType empathy_profile_chooser_get_type (void) G_GNUC_CONST; -GtkWidget * empathy_profile_chooser_new (void); -McProfile * empathy_profile_chooser_dup_selected ( - EmpathyProfileChooser *profile_chooser); -gint empathy_profile_chooser_n_profiles ( - EmpathyProfileChooser *profile_chooser); - -G_END_DECLS -#endif /* __EMPATHY_PROFILE_CHOOSER_H__ */ diff --git a/libempathy-gtk/empathy-protocol-chooser.c b/libempathy-gtk/empathy-protocol-chooser.c new file mode 100644 index 000000000..f148edb99 --- /dev/null +++ b/libempathy-gtk/empathy-protocol-chooser.c @@ -0,0 +1,425 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* + * Copyright (C) 2007-2009 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> + * Jonny Lamb <jonny.lamb@collabora.co.uk> + */ + +#include <config.h> + +#include <string.h> + +#include <telepathy-glib/util.h> + +#include <gtk/gtk.h> + +#include <libempathy/empathy-utils.h> +#include <libempathy/empathy-connection-managers.h> + +#include "empathy-protocol-chooser.h" +#include "empathy-ui-utils.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT +#include <libempathy/empathy-debug.h> + +/** + * SECTION:empathy-protocol-chooser + * @title: EmpathyProtocolChooser + * @short_description: A widget used to choose from a list of protocols + * @include: libempathy-gtk/empathy-protocol-chooser.h + * + * #EmpathyProtocolChooser is a widget which extends #GtkComboBox to provides a + * chooser of available protocols. + */ + +/** + * EmpathyProtocolChooser: + * @parent: parent object + * + * Widget which extends #GtkComboBox to provide a chooser of available + * protocols. + */ + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyProtocolChooser) +typedef struct +{ + GtkListStore *store; + + gboolean dispose_run; + EmpathyConnectionManagers *cms; + + EmpathyProtocolChooserFilterFunc filter_func; + gpointer filter_user_data; +} EmpathyProtocolChooserPriv; + +enum +{ + COL_ICON, + COL_LABEL, + COL_CM, + COL_PROTOCOL, + COL_COUNT +}; + +G_DEFINE_TYPE (EmpathyProtocolChooser, empathy_protocol_chooser, + GTK_TYPE_COMBO_BOX); + +static gint +protocol_chooser_sort_protocol_value (TpConnectionManagerProtocol *protocol) +{ + guint i; + const gchar *names[] = { + "jabber", + "salut", + "gtalk", + NULL + }; + + for (i = 0 ; names[i]; i++) + { + if (strcmp (protocol->name, names[i]) == 0) + return i; + } + + return i; +} + +static gint +protocol_chooser_sort_func (GtkTreeModel *model, + GtkTreeIter *iter_a, + GtkTreeIter *iter_b, + gpointer user_data) +{ + TpConnectionManagerProtocol *protocol_a; + TpConnectionManagerProtocol *protocol_b; + gint cmp; + + gtk_tree_model_get (model, iter_a, + COL_PROTOCOL, &protocol_a, + -1); + gtk_tree_model_get (model, iter_b, + COL_PROTOCOL, &protocol_b, + -1); + + cmp = protocol_chooser_sort_protocol_value (protocol_a); + cmp -= protocol_chooser_sort_protocol_value (protocol_b); + if (cmp == 0) + { + cmp = strcmp (protocol_a->name, protocol_b->name); + } + + return cmp; +} + +static const char * +protocol_chooser_proto_name_to_display_name (const gchar *proto_name) +{ + int i; + static struct { + const gchar *proto; + const gchar *display; + } names[] = { + { "jabber", "XMPP" }, + { "msn", "MSN" }, + { "local-xmpp", "Salut" }, + { "irc", "IRC" }, + { "icq", "ICQ" }, + { "aim", "AIM" }, + { "yahoo", "Yahoo" }, + { "groupwise", "GroupWise" }, + { "sip", "SIP" }, + { NULL, NULL } + }; + + for (i = 0; names[i].proto != NULL; i++) + { + if (!tp_strdiff (proto_name, names[i].proto)) + return names[i].display; + } + + return NULL; +} + +static void +protocol_choosers_add_cm (EmpathyProtocolChooser *chooser, + TpConnectionManager *cm) +{ + EmpathyProtocolChooserPriv *priv = GET_PRIV (chooser); + const TpConnectionManagerProtocol * const *iter; + + for (iter = cm->protocols; iter != NULL && *iter != NULL; iter++) + { + const TpConnectionManagerProtocol *proto = *iter; + gchar *icon_name; + const gchar *display_name; + gchar *display_name_set; + + icon_name = empathy_protocol_icon_name (proto->name); + display_name = protocol_chooser_proto_name_to_display_name (proto->name); + + if (display_name == NULL) + display_name = proto->name; + + if (!tp_strdiff (cm->name, "haze")) + display_name_set = g_strdup_printf ("%s (Haze)", display_name); + else + display_name_set = g_strdup (display_name); + + gtk_list_store_insert_with_values (priv->store, + NULL, 0, + COL_ICON, icon_name, + COL_LABEL, display_name_set, + COL_CM, cm, + COL_PROTOCOL, proto, + -1); + + g_free (display_name_set); + g_free (icon_name); + } +} + +static void +protocol_chooser_add_cms_list (EmpathyProtocolChooser *protocol_chooser, + GList *cms) +{ + GList *l; + + for (l = cms; l != NULL; l = l->next) + protocol_choosers_add_cm (protocol_chooser, l->data); + + gtk_combo_box_set_active (GTK_COMBO_BOX (protocol_chooser), 0); +} + +static void +protocol_chooser_cms_ready_cb (EmpathyConnectionManagers *cms, + GParamSpec *pspec, + EmpathyProtocolChooser *protocol_chooser) +{ + if (empathy_connection_managers_is_ready (cms)) + protocol_chooser_add_cms_list + (protocol_chooser, empathy_connection_managers_get_cms (cms)); +} + +static void +protocol_chooser_constructed (GObject *object) +{ + EmpathyProtocolChooser *protocol_chooser; + EmpathyProtocolChooserPriv *priv; + GtkCellRenderer *renderer; + + priv = GET_PRIV (object); + protocol_chooser = EMPATHY_PROTOCOL_CHOOSER (object); + + /* set up combo box with new store */ + priv->store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* Icon name */ + G_TYPE_STRING, /* Label */ + G_TYPE_OBJECT, /* CM */ + G_TYPE_POINTER); /* protocol */ + + /* Set the protocol sort function */ + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->store), + COL_PROTOCOL, + protocol_chooser_sort_func, + NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store), + COL_PROTOCOL, + GTK_SORT_ASCENDING); + + gtk_combo_box_set_model (GTK_COMBO_BOX (object), + GTK_TREE_MODEL (priv->store)); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, FALSE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer, + "icon-name", COL_ICON, + NULL); + g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (object), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (object), renderer, + "text", COL_LABEL, + NULL); + + if (empathy_connection_managers_is_ready (priv->cms)) + protocol_chooser_add_cms_list (protocol_chooser, + empathy_connection_managers_get_cms (priv->cms)); + else + g_signal_connect (priv->cms, "notify::ready", + G_CALLBACK (protocol_chooser_cms_ready_cb), protocol_chooser); + + if (G_OBJECT_CLASS (empathy_protocol_chooser_parent_class)->constructed) + G_OBJECT_CLASS (empathy_protocol_chooser_parent_class)->constructed (object); +} + +static void +empathy_protocol_chooser_init (EmpathyProtocolChooser *protocol_chooser) +{ + EmpathyProtocolChooserPriv *priv = + G_TYPE_INSTANCE_GET_PRIVATE (protocol_chooser, + EMPATHY_TYPE_PROTOCOL_CHOOSER, EmpathyProtocolChooserPriv); + + priv->dispose_run = FALSE; + priv->cms = empathy_connection_managers_dup_singleton (); + + protocol_chooser->priv = priv; +} + +static void +protocol_chooser_dispose (GObject *object) +{ + EmpathyProtocolChooser *protocol_chooser = EMPATHY_PROTOCOL_CHOOSER (object); + EmpathyProtocolChooserPriv *priv = GET_PRIV (protocol_chooser); + + if (priv->dispose_run) + return; + + priv->dispose_run = TRUE; + + if (priv->store) + { + g_object_unref (priv->store); + priv->store = NULL; + } + + if (priv->cms) + { + g_object_unref (priv->cms); + priv->cms = NULL; + } + + (G_OBJECT_CLASS (empathy_protocol_chooser_parent_class)->dispose) (object); +} + +static void +empathy_protocol_chooser_class_init (EmpathyProtocolChooserClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = protocol_chooser_constructed; + object_class->dispose = protocol_chooser_dispose; + + g_type_class_add_private (object_class, sizeof (EmpathyProtocolChooserPriv)); +} + +static gboolean +protocol_chooser_filter_visible_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + EmpathyProtocolChooser *protocol_chooser = user_data; + EmpathyProtocolChooserPriv *priv = GET_PRIV (protocol_chooser); + TpConnectionManager *cm = NULL; + TpConnectionManagerProtocol *protocol = NULL; + gboolean visible = FALSE; + + gtk_tree_model_get (model, iter, COL_CM, &cm, COL_PROTOCOL, &protocol, -1); + + if (cm != NULL && protocol != NULL) + { + visible = priv->filter_func (cm, protocol, priv->filter_user_data); + g_object_unref (cm); + } + + return visible; +} + +/* public methods */ + +/** + * empathy_protocol_chooser_get_selected_protocol: + * @protocol_chooser: an #EmpathyProtocolChooser + * + * Returns a pointer to the selected #TpConnectionManagerProtocol in + * @protocol_chooser. + * + * Return value: a pointer to the selected #TpConnectionManagerProtocol + */ +TpConnectionManager * +empathy_protocol_chooser_dup_selected ( + EmpathyProtocolChooser *protocol_chooser, + TpConnectionManagerProtocol **protocol) +{ + GtkTreeIter iter; + TpConnectionManager *cm = NULL; + GtkTreeModel *cur_model; + + g_return_val_if_fail (EMPATHY_IS_PROTOCOL_CHOOSER (protocol_chooser), NULL); + + /* get the current model from the chooser, as we could either be filtering + * or not. + */ + cur_model = gtk_combo_box_get_model (GTK_COMBO_BOX (protocol_chooser)); + + if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (protocol_chooser), &iter)) + { + gtk_tree_model_get (GTK_TREE_MODEL (cur_model), &iter, + COL_CM, &cm, + -1); + + if (protocol != NULL) + gtk_tree_model_get (GTK_TREE_MODEL (cur_model), &iter, + COL_PROTOCOL, protocol, + -1); + } + + return cm; +} + +/** + * empathy_protocol_chooser_new: + * + * Triggers the creation of a new #EmpathyProtocolChooser. + * + * Return value: a new #EmpathyProtocolChooser widget + */ + +GtkWidget * +empathy_protocol_chooser_new (void) +{ + return GTK_WIDGET (g_object_new (EMPATHY_TYPE_PROTOCOL_CHOOSER, NULL)); +} + +void +empathy_protocol_chooser_set_visible (EmpathyProtocolChooser *protocol_chooser, + EmpathyProtocolChooserFilterFunc func, + gpointer user_data) +{ + EmpathyProtocolChooserPriv *priv; + GtkTreeModel *filter_model; + + g_return_if_fail (EMPATHY_IS_PROTOCOL_CHOOSER (protocol_chooser)); + + priv = GET_PRIV (protocol_chooser); + priv->filter_func = func; + priv->filter_user_data = user_data; + + filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (priv->store), + NULL); + gtk_combo_box_set_model (GTK_COMBO_BOX (protocol_chooser), filter_model); + g_object_unref (filter_model); + + gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER + (filter_model), protocol_chooser_filter_visible_func, + protocol_chooser, NULL); + + gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model)); + + gtk_combo_box_set_active (GTK_COMBO_BOX (protocol_chooser), 0); +} diff --git a/libempathy-gtk/empathy-protocol-chooser.h b/libempathy-gtk/empathy-protocol-chooser.h new file mode 100644 index 000000000..55e8e355e --- /dev/null +++ b/libempathy-gtk/empathy-protocol-chooser.h @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* + * Copyright (C) 2007-2009 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> + * Jonny Lamb <jonny.lamb@collabora.co.uk + */ + +#ifndef __EMPATHY_PROTOCOL_CHOOSER_H__ +#define __EMPATHY_PROTOCOL_CHOOSER_H__ + +#include <glib-object.h> +#include <gtk/gtk.h> + +#include <telepathy-glib/connection-manager.h> + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_PROTOCOL_CHOOSER (empathy_protocol_chooser_get_type ()) +#define EMPATHY_PROTOCOL_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + EMPATHY_TYPE_PROTOCOL_CHOOSER, EmpathyProtocolChooser)) +#define EMPATHY_PROTOCOL_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \ + EMPATHY_TYPE_PROTOCOL_CHOOSER, EmpathyProtocolChooserClass)) +#define EMPATHY_IS_PROTOCOL_CHOOSER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + EMPATHY_TYPE_PROTOCOL_CHOOSER)) +#define EMPATHY_IS_PROTOCOL_CHOOSER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \ + EMPATHY_TYPE_PROTOCOL_CHOOSER)) +#define EMPATHY_PROTOCOL_CHOOSER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),\ + EMPATHY_TYPE_PROTOCOL_CHOOSER, EmpathyProtocolChooserClass)) + +typedef struct _EmpathyProtocolChooser EmpathyProtocolChooser; +typedef struct _EmpathyProtocolChooserClass EmpathyProtocolChooserClass; + +struct _EmpathyProtocolChooser +{ + GtkComboBox parent; + + /*<private>*/ + gpointer priv; +}; + +struct _EmpathyProtocolChooserClass +{ + GtkComboBoxClass parent_class; +}; + +typedef gboolean (*EmpathyProtocolChooserFilterFunc) (TpConnectionManager *cm, + TpConnectionManagerProtocol *protocol, gpointer user_data); + +GType empathy_protocol_chooser_get_type (void) G_GNUC_CONST; +GtkWidget * empathy_protocol_chooser_new (void); +TpConnectionManager *empathy_protocol_chooser_dup_selected ( + EmpathyProtocolChooser *protocol_chooser, + TpConnectionManagerProtocol **protocol); + +void empathy_protocol_chooser_set_visible ( + EmpathyProtocolChooser *protocol_chooser, + EmpathyProtocolChooserFilterFunc func, + gpointer user_data); + + +G_END_DECLS +#endif /* __EMPATHY_PROTOCOL_CHOOSER_H__ */ diff --git a/libempathy-gtk/empathy-share-my-desktop.c b/libempathy-gtk/empathy-share-my-desktop.c index b981d5ade..01c2e183f 100644 --- a/libempathy-gtk/empathy-share-my-desktop.c +++ b/libempathy-gtk/empathy-share-my-desktop.c @@ -23,6 +23,8 @@ #include <dbus/dbus-glib.h> #include <telepathy-glib/util.h> #include <telepathy-glib/contact.h> +#include <telepathy-glib/channel.h> +#include <telepathy-glib/interfaces.h> #define DEBUG_FLAG EMPATHY_DEBUG_SHARE_DESKTOP #include <libempathy/empathy-debug.h> diff --git a/libempathy-gtk/empathy-theme-adium.c b/libempathy-gtk/empathy-theme-adium.c index b286464d2..e1094f1be 100644 --- a/libempathy-gtk/empathy-theme-adium.c +++ b/libempathy-gtk/empathy-theme-adium.c @@ -31,7 +31,6 @@ #include <libempathy/empathy-time.h> #include <libempathy/empathy-utils.h> -#include <libmissioncontrol/mc-profile.h> #include "empathy-theme-adium.h" #include "empathy-smiley-manager.h" @@ -479,7 +478,6 @@ theme_adium_append_html (EmpathyThemeAdium *theme, } else if (theme_adium_match (&cur, "%time")) { gchar *format = NULL; gchar *end; - /* Time can be in 2 formats: * %time% or %time{strftime format}% * Extract the time format if provided. */ @@ -524,7 +522,6 @@ theme_adium_append_message (EmpathyChatView *view, EmpathyThemeAdiumPriv *priv = GET_PRIV (theme); EmpathyContact *sender; EmpathyAccount *account; - McProfile *account_profile; gchar *dup_body = NULL; const gchar *body; const gchar *name; @@ -548,8 +545,7 @@ theme_adium_append_message (EmpathyChatView *view, /* Get information */ sender = empathy_message_get_sender (msg); account = empathy_contact_get_account (sender); - account_profile = empathy_account_get_profile (account); - service_name = mc_profile_get_display_name (account_profile); + service_name = empathy_account_get_protocol (account); timestamp = empathy_message_get_timestamp (msg); body = empathy_message_get_body (msg); dup_body = theme_adium_parse_body (theme, body); diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c index 32abc5884..c12cbd1c9 100644 --- a/libempathy-gtk/empathy-ui-utils.c +++ b/libempathy-gtk/empathy-ui-utils.c @@ -38,8 +38,6 @@ #include <gtk/gtk.h> #include <gio/gio.h> -#include <libmissioncontrol/mc-profile.h> - #include "empathy-ui-utils.h" #include "empathy-images.h" #include "empathy-conf.h" @@ -183,16 +181,6 @@ empathy_builder_unref_and_keep_widget (GtkBuilder *gui, } const gchar * -empathy_icon_name_from_account (EmpathyAccount *account) -{ - McProfile *profile; - - profile = empathy_account_get_profile (account); - - return mc_profile_get_icon_name (profile); -} - -const gchar * empathy_icon_name_for_presence (TpConnectionPresenceType presence) { switch (presence) { diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h index 3299a44e0..afb409af4 100644 --- a/libempathy-gtk/empathy-ui-utils.h +++ b/libempathy-gtk/empathy-ui-utils.h @@ -34,8 +34,6 @@ #include <gtk/gtk.h> -#include <libmissioncontrol/mc-profile.h> - #include <libempathy/empathy-contact.h> #include <libempathy/empathy-account.h> #include <libempathy/empathy-ft-handler.h> @@ -59,7 +57,6 @@ GtkWidget *empathy_builder_unref_and_keep_widget (GtkBuilder *gui, GtkWidget *root); /* Pixbufs */ -const gchar * empathy_icon_name_from_account (EmpathyAccount *account); const gchar * empathy_icon_name_for_presence (TpConnectionPresenceType presence); const gchar * empathy_icon_name_for_contact (EmpathyContact *contact); GdkPixbuf * empathy_pixbuf_from_data (gchar *data, diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 0250a63d8..5fe4a9df7 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -26,7 +26,7 @@ lib_LTLIBRARIES = libempathy.la libempathy_la_SOURCES = \ empathy-account.c \ - empathy-account-priv.h \ + empathy-account-settings.c \ empathy-account-manager.c \ empathy-chatroom.c \ empathy-chatroom-manager.c \ @@ -38,6 +38,7 @@ libempathy_la_SOURCES = \ empathy-contact-list.c \ empathy-contact-manager.c \ empathy-contact-monitor.c \ + empathy-connection-managers.c \ empathy-debug.c \ empathy-debugger.c \ empathy-dispatcher.c \ @@ -79,6 +80,7 @@ libempathy_la_LDFLAGS = \ -export-symbols-regex ^empathy_ libempathy_headers = \ + empathy-account-settings.h \ empathy-account.h \ empathy-account-manager.h \ empathy-chatroom.h \ @@ -91,6 +93,7 @@ libempathy_headers = \ empathy-contact-list.h \ empathy-contact-manager.h \ empathy-contact-monitor.h \ + empathy-connection-managers.h \ empathy-debug.h \ empathy-debugger.h \ empathy-dispatcher.h \ diff --git a/libempathy/empathy-account-manager.c b/libempathy/empathy-account-manager.c index fd8a21b1d..75de6f193 100644 --- a/libempathy/empathy-account-manager.c +++ b/libempathy/empathy-account-manager.c @@ -21,10 +21,14 @@ #include "config.h" -#include <libmissioncontrol/mc-account-monitor.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/account-manager.h> +#include <telepathy-glib/enums.h> +#include <telepathy-glib/defs.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> #include "empathy-account-manager.h" -#include "empathy-account-priv.h" #include "empathy-marshal.h" #include "empathy-utils.h" @@ -33,15 +37,33 @@ #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountManager) -typedef struct { - McAccountMonitor *monitor; - MissionControl *mc; +#define MC5_BUS_NAME "org.freedesktop.Telepathy.MissionControl5" +typedef struct { /* (owned) unique name -> (reffed) EmpathyAccount */ GHashTable *accounts; int connected; int connecting; gboolean dispose_run; + gboolean ready; + TpAccountManager *tp_manager; + TpDBusDaemon *dbus; + + /* global presence */ + EmpathyAccount *global_account; + + TpConnectionPresenceType global_presence; + gchar *global_status; + gchar *global_status_message; + + /* requested global presence, could be different + * from the actual global one. + */ + TpConnectionPresenceType requested_presence; + gchar *requested_status; + gchar *requested_status_message; + + GHashTable *create_results; } EmpathyAccountManagerPriv; enum { @@ -51,38 +73,20 @@ enum { ACCOUNT_DISABLED, ACCOUNT_CHANGED, ACCOUNT_CONNECTION_CHANGED, - ACCOUNT_PRESENCE_CHANGED, + GLOBAL_PRESENCE_CHANGED, NEW_CONNECTION, LAST_SIGNAL }; +enum { + PROP_READY = 1, +}; + static guint signals[LAST_SIGNAL]; static EmpathyAccountManager *manager_singleton = NULL; G_DEFINE_TYPE (EmpathyAccountManager, empathy_account_manager, G_TYPE_OBJECT); -static TpConnectionPresenceType -mc_presence_to_tp_presence (McPresence presence) -{ - switch (presence) - { - case MC_PRESENCE_OFFLINE: - return TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - case MC_PRESENCE_AVAILABLE: - return TP_CONNECTION_PRESENCE_TYPE_AVAILABLE; - case MC_PRESENCE_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_AWAY; - case MC_PRESENCE_EXTENDED_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY; - case MC_PRESENCE_HIDDEN: - return TP_CONNECTION_PRESENCE_TYPE_HIDDEN; - case MC_PRESENCE_DO_NOT_DISTURB: - return TP_CONNECTION_PRESENCE_TYPE_BUSY; - default: - return TP_CONNECTION_PRESENCE_TYPE_UNSET; - } -} - static void emp_account_connection_cb (EmpathyAccount *account, GParamSpec *spec, @@ -98,6 +102,17 @@ emp_account_connection_cb (EmpathyAccount *account, } static void +emp_account_enabled_cb (EmpathyAccount *account, + GParamSpec *spec, + gpointer manager) +{ + if (empathy_account_is_enabled (account)) + g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account); + else + g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account); +} + +static void emp_account_status_changed_cb (EmpathyAccount *account, TpConnectionStatus old, TpConnectionStatus new, @@ -136,270 +151,333 @@ emp_account_status_changed_cb (EmpathyAccount *account, } static void -emp_account_presence_changed_cb (EmpathyAccount *account, - TpConnectionPresenceType old, - TpConnectionPresenceType new, - gpointer user_data) -{ - EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); - g_signal_emit (manager, signals[ACCOUNT_PRESENCE_CHANGED], 0, - account, new, old); -} - -static EmpathyAccount * -create_account (EmpathyAccountManager *manager, - const gchar *account_name, - McAccount *mc_account) +emp_account_manager_update_global_presence (EmpathyAccountManager *manager) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; - TpConnectionStatus status; - TpConnectionPresenceType presence; - McPresence mc_presence; - TpConnection *connection; - GError *error = NULL; - - if ((account = g_hash_table_lookup (priv->accounts, account_name)) != NULL) - return account; - - account = _empathy_account_new (mc_account); - g_hash_table_insert (priv->accounts, g_strdup (account_name), - account); + TpConnectionPresenceType presence = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; + EmpathyAccount *account = NULL; + GHashTableIter iter; + gpointer value; - _empathy_account_set_enabled (account, - mc_account_is_enabled (mc_account)); + /* Make the global presence is equal to the presence of the account with the + * highest availability */ - g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account); + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + EmpathyAccount *a = EMPATHY_ACCOUNT (value); + TpConnectionPresenceType p; - g_signal_connect (account, "notify::connection", - G_CALLBACK (emp_account_connection_cb), manager); + g_object_get (a, "presence", &p, NULL); - connection = mission_control_get_tpconnection (priv->mc, - mc_account, NULL); - _empathy_account_set_connection (account, connection); + if (tp_connection_presence_type_cmp_availability (p, presence) > 0) + { + account = a; + presence = p; + } + } - status = mission_control_get_connection_status (priv->mc, - mc_account, &error); + priv->global_account = account; + g_free (priv->global_status); + g_free (priv->global_status_message); - if (error != NULL) + if (account == NULL) { - status = TP_CONNECTION_STATUS_DISCONNECTED; - g_clear_error (&error); + priv->global_presence = presence; + priv->global_status = NULL; + priv->global_status_message = NULL; + return; } - mc_presence = mission_control_get_presence_actual (priv->mc, &error); - if (error != NULL) - { - presence = TP_CONNECTION_PRESENCE_TYPE_UNSET; - g_clear_error (&error); - } - else + g_object_get (account, + "presence", &priv->global_presence, + "status", &priv->global_status, + "status-message", &priv->global_status_message, + NULL); + + DEBUG ("Updated global presence to: %s (%d) \"%s\"", + priv->global_status, priv->global_presence, priv->global_status_message); +} + +static void +emp_account_presence_changed_cb (EmpathyAccount *account, + TpConnectionPresenceType presence, + const gchar *status, + const gchar *status_message, + gpointer user_data) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + if (tp_connection_presence_type_cmp_availability (presence, + priv->global_presence) > 0) { - presence = mc_presence_to_tp_presence (mc_presence); - } + priv->global_account = account; - g_signal_connect (account, "status-changed", - G_CALLBACK (emp_account_status_changed_cb), manager); + priv->global_presence = presence; - g_signal_connect (account, "presence-changed", - G_CALLBACK (emp_account_presence_changed_cb), manager); + g_free (priv->global_status); + priv->global_status = g_strdup (status); - _empathy_account_set_status (account, status, - TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, - presence); + g_free (priv->global_status_message); + priv->global_status_message = g_strdup (status_message); - return account; + goto signal; + } + else if (priv->global_account == account) + { + emp_account_manager_update_global_presence (manager); + goto signal; + } + + return; +signal: + g_signal_emit (manager, signals[GLOBAL_PRESENCE_CHANGED], 0, + priv->global_presence, priv->global_status, priv->global_status_message); } static void -account_created_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +emp_account_removed_cb (EmpathyAccount *account, gpointer user_data) { - McAccount *mc_account = mc_account_lookup (account_name); + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - if (mc_account != NULL) - create_account (manager, account_name, mc_account); + g_object_ref (account); + g_hash_table_remove (priv->accounts, + empathy_account_get_unique_name (account)); + + g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account); + g_object_unref (account); } static void -account_deleted_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +empathy_account_manager_check_ready (EmpathyAccountManager *manager) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; + GHashTableIter iter; + gpointer value; - account = g_hash_table_lookup (priv->accounts, account_name); + if (priv->ready) + return; - if (account) + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &value)) { - g_signal_emit (manager, signals[ACCOUNT_DELETED], 0, account); - g_hash_table_remove (priv->accounts, account_name); + EmpathyAccount *account = EMPATHY_ACCOUNT (value); + gboolean ready; + + g_object_get (account, "ready", &ready, NULL); + + if (!ready) + return; } + + /* Rerequest global presence on the initial set of accounts for cases where a + * global presence was requested before the manager was ready */ + if (priv->requested_presence != TP_CONNECTION_PRESENCE_TYPE_UNSET) + empathy_account_manager_request_global_presence (manager, + priv->requested_presence, + priv->requested_status, + priv->requested_status_message); + + priv->ready = TRUE; + g_object_notify (G_OBJECT (manager), "ready"); } static void -account_changed_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +account_manager_account_ready_cb (GObject *obj, + GParamSpec *spec, + gpointer user_data) { + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; + EmpathyAccount *account = EMPATHY_ACCOUNT (obj); + GSimpleAsyncResult *result; + gboolean ready; - account = g_hash_table_lookup (priv->accounts, account_name); + g_object_get (account, "ready", &ready, NULL); - if (account != NULL) - g_signal_emit (manager, signals[ACCOUNT_CHANGED], 0, account); + if (!ready) + return; + + /* see if there's any pending callbacks for this account */ + result = g_hash_table_lookup (priv->create_results, account); + if (result != NULL) + { + g_simple_async_result_set_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (result), account, NULL); + + g_simple_async_result_complete (result); + + g_hash_table_remove (priv->create_results, account); + g_object_unref (result); + } + + g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account); + + g_signal_connect (account, "notify::connection", + G_CALLBACK (emp_account_connection_cb), manager); + + g_signal_connect (account, "notify::enabled", + G_CALLBACK (emp_account_enabled_cb), manager); + + g_signal_connect (account, "status-changed", + G_CALLBACK (emp_account_status_changed_cb), manager); + + g_signal_connect (account, "presence-changed", + G_CALLBACK (emp_account_presence_changed_cb), manager); + + g_signal_connect (account, "removed", + G_CALLBACK (emp_account_removed_cb), manager); + + empathy_account_manager_check_ready (manager); } -static void -account_disabled_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +EmpathyAccount * +empathy_account_manager_get_account (EmpathyAccountManager *manager, + const gchar *path) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; - account = g_hash_table_lookup (priv->accounts, account_name); - - if (account) - { - _empathy_account_set_enabled (account, FALSE); - g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account); - } + return g_hash_table_lookup (priv->accounts, path); } -static void -account_enabled_cb (McAccountMonitor *mon, - gchar *account_name, - EmpathyAccountManager *manager) +EmpathyAccount * +empathy_account_manager_ensure_account (EmpathyAccountManager *manager, + const gchar *path) { EmpathyAccountManagerPriv *priv = GET_PRIV (manager); EmpathyAccount *account; - account = g_hash_table_lookup (priv->accounts, account_name); + account = g_hash_table_lookup (priv->accounts, path); + if (account != NULL) + return account; + + account = empathy_account_new (priv->dbus, path); + g_hash_table_insert (priv->accounts, g_strdup (path), account); - if (account) - { - _empathy_account_set_enabled (account, TRUE); - g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account); - } + g_signal_connect (account, "notify::ready", + G_CALLBACK (account_manager_account_ready_cb), manager); + + return account; } -typedef struct { - TpConnectionStatus status; - TpConnectionPresenceType presence; - TpConnectionStatusReason reason; - gchar *unique_name; - EmpathyAccountManager *manager; - McAccount *mc_account; -} ChangedSignalData; -static gboolean -account_status_changed_idle_cb (ChangedSignalData *signal_data) +static void +account_manager_got_all_cb (TpProxy *proxy, + GHashTable *properties, + const GError *error, + gpointer user_data, + GObject *weak_object) { - EmpathyAccount *account; - EmpathyAccountManager *manager = signal_data->manager; - EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object); + GPtrArray *accounts; + int i; - account = g_hash_table_lookup (priv->accounts, - signal_data->unique_name); + if (error != NULL) + { + DEBUG ("Failed to get account manager properties: %s", error->message); + return; + } - if (account) + accounts = tp_asv_get_boxed (properties, "ValidAccounts", + EMPATHY_ARRAY_TYPE_OBJECT); + + if (accounts != NULL) { - if (empathy_account_get_connection (account) == NULL) + for (i = 0; i < accounts->len; i++) { - TpConnection *connection; - - connection = mission_control_get_tpconnection (priv->mc, - signal_data->mc_account, NULL); + gchar *name = g_ptr_array_index (accounts, i); - if (connection != NULL) - { - _empathy_account_set_connection (account, connection); - g_object_unref (connection); - } + empathy_account_manager_ensure_account (manager, name); } - - _empathy_account_set_status (account, signal_data->status, - signal_data->reason, - signal_data->presence); } - g_object_unref (signal_data->manager); - g_object_unref (signal_data->mc_account); - g_free (signal_data->unique_name); - g_slice_free (ChangedSignalData, signal_data); - - return FALSE; + empathy_account_manager_check_ready (manager); } static void -account_status_changed_cb (MissionControl *mc, - TpConnectionStatus status, - McPresence presence, - TpConnectionStatusReason reason, - const gchar *unique_name, - EmpathyAccountManager *manager) +account_validity_changed_cb (TpAccountManager *proxy, + const gchar *path, + gboolean valid, + gpointer user_data, + GObject *weak_object) { - ChangedSignalData *data; + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object); + + if (!valid) + return; - DEBUG ("Status of account %s became " - "status: %d presence: %d reason: %d", unique_name, status, - presence, reason); + empathy_account_manager_ensure_account (manager, path); +} - data = g_slice_new0 (ChangedSignalData); - data->status = status; - data->presence = mc_presence_to_tp_presence (presence); - data->reason = reason; - data->unique_name = g_strdup (unique_name); - data->manager = g_object_ref (manager); - data->mc_account = mc_account_lookup (unique_name); +static void +account_manager_name_owner_cb (TpDBusDaemon *proxy, + const gchar *name, + const gchar *new_owner, + gpointer user_data) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - g_idle_add ((GSourceFunc) account_status_changed_idle_cb, data); + tp_dbus_daemon_cancel_name_owner_watch (proxy, name, + account_manager_name_owner_cb, user_data); + + priv->tp_manager = tp_account_manager_new (priv->dbus); + + tp_cli_account_manager_connect_to_account_validity_changed ( + priv->tp_manager, + account_validity_changed_cb, + NULL, + NULL, + G_OBJECT (manager), + NULL); + + tp_cli_dbus_properties_call_get_all (priv->tp_manager, -1, + TP_IFACE_ACCOUNT_MANAGER, + account_manager_got_all_cb, + NULL, + NULL, + G_OBJECT (manager)); } static void empathy_account_manager_init (EmpathyAccountManager *manager) { EmpathyAccountManagerPriv *priv; - GList *mc_accounts, *l; + TpProxy *mc5_proxy; priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerPriv); manager->priv = priv; - priv->monitor = mc_account_monitor_new (); - priv->mc = empathy_mission_control_dup_singleton (); priv->connected = priv->connecting = 0; - priv->dispose_run = FALSE; + priv->global_presence = TP_CONNECTION_PRESENCE_TYPE_UNSET; priv->accounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); - mc_accounts = mc_accounts_list (); + priv->create_results = g_hash_table_new (g_direct_hash, g_direct_equal); + + priv->dbus = tp_dbus_daemon_dup (NULL); - for (l = mc_accounts; l; l = l->next) - account_created_cb (priv->monitor, - (char *) mc_account_get_unique_name (l->data), manager); + tp_dbus_daemon_watch_name_owner (priv->dbus, + TP_ACCOUNT_MANAGER_BUS_NAME, + account_manager_name_owner_cb, + manager, + NULL); - g_signal_connect (priv->monitor, "account-created", - G_CALLBACK (account_created_cb), manager); - g_signal_connect (priv->monitor, "account-deleted", - G_CALLBACK (account_deleted_cb), manager); - g_signal_connect (priv->monitor, "account-disabled", - G_CALLBACK (account_disabled_cb), manager); - g_signal_connect (priv->monitor, "account-enabled", - G_CALLBACK (account_enabled_cb), manager); - g_signal_connect (priv->monitor, "account-changed", - G_CALLBACK (account_changed_cb), manager); + /* trigger MC5 starting */ + mc5_proxy = g_object_new (TP_TYPE_PROXY, + "dbus-daemon", priv->dbus, + "dbus-connection", tp_proxy_get_dbus_connection (TP_PROXY (priv->dbus)), + "bus-name", MC5_BUS_NAME, + "object-path", "/", + NULL); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), "AccountStatusChanged", - G_CALLBACK (account_status_changed_cb), - manager, NULL); + tp_cli_dbus_peer_call_ping (mc5_proxy, -1, NULL, NULL, NULL, NULL); - mc_accounts_list_free (mc_accounts); + g_object_unref (mc5_proxy); } static void @@ -408,8 +486,15 @@ do_finalize (GObject *obj) EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj); EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + g_hash_table_destroy (priv->create_results); g_hash_table_destroy (priv->accounts); + g_free (priv->global_status); + g_free (priv->global_status_message); + + g_free (priv->requested_status); + g_free (priv->requested_status_message); + G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj); } @@ -418,37 +503,37 @@ do_dispose (GObject *obj) { EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj); EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GHashTableIter iter; + GSimpleAsyncResult *result; if (priv->dispose_run) return; priv->dispose_run = TRUE; - dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc), - "AccountStatusChanged", - G_CALLBACK (account_status_changed_cb), - obj); - - if (priv->monitor) + /* the manager is being destroyed while there are account creation + * processes pending; this should not happen, but emit the callbacks + * with an error anyway. + */ + g_hash_table_iter_init (&iter, priv->create_results); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &result)) { - g_signal_handlers_disconnect_by_func (priv->monitor, - account_created_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_deleted_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_disabled_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_enabled_cb, obj); - g_signal_handlers_disconnect_by_func (priv->monitor, - account_changed_cb, obj); - g_object_unref (priv->monitor); - priv->monitor = NULL; + g_simple_async_result_set_error (result, G_IO_ERROR, + G_IO_ERROR_CANCELLED, "The account manager was disposed while " + "creating the account"); + g_simple_async_result_complete (result); + g_object_unref (result); } + g_hash_table_remove_all (priv->create_results); - if (priv->mc) - g_object_unref (priv->mc); + if (priv->dbus != NULL) + { + tp_dbus_daemon_cancel_name_owner_watch (priv->dbus, + TP_ACCOUNT_MANAGER_BUS_NAME, account_manager_name_owner_cb, manager); - g_hash_table_remove_all (priv->accounts); + g_object_unref (priv->dbus); + priv->dbus = NULL; + } G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj); } @@ -477,6 +562,26 @@ do_constructor (GType type, } static void +do_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (object); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + switch (prop_id) + { + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void empathy_account_manager_class_init (EmpathyAccountManagerClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); @@ -484,6 +589,14 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass) oclass->finalize = do_finalize; oclass->dispose = do_dispose; oclass->constructor = do_constructor; + oclass->get_property = do_get_property; + + g_object_class_install_property (oclass, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether the initial state dump from the account manager is finished", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); signals[ACCOUNT_CREATED] = g_signal_new ("account-created", @@ -548,17 +661,17 @@ empathy_account_manager_class_init (EmpathyAccountManagerClass *klass) G_TYPE_UINT, /* actual connection */ G_TYPE_UINT); /* previous connection */ - signals[ACCOUNT_PRESENCE_CHANGED] = - g_signal_new ("account-presence-changed", + signals[GLOBAL_PRESENCE_CHANGED] = + g_signal_new ("global-presence-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _empathy_marshal_VOID__OBJECT_INT_INT, + _empathy_marshal_VOID__UINT_STRING_STRING, G_TYPE_NONE, - 3, EMPATHY_TYPE_ACCOUNT, - G_TYPE_INT, /* actual presence */ - G_TYPE_INT); /* previous presence */ + 3, G_TYPE_UINT, /* Presence type */ + G_TYPE_STRING, /* status */ + G_TYPE_STRING); /* stauts message*/ signals[NEW_CONNECTION] = g_signal_new ("new-connection", @@ -581,14 +694,12 @@ empathy_account_manager_dup_singleton (void) return g_object_new (EMPATHY_TYPE_ACCOUNT_MANAGER, NULL); } -EmpathyAccount * -empathy_account_manager_create (EmpathyAccountManager *manager, - McProfile *profile) +gboolean +empathy_account_manager_is_ready (EmpathyAccountManager *manager) { - McAccount *mc_account = mc_account_create (profile); - return g_object_ref (create_account (manager, - mc_account_get_unique_name (mc_account), - mc_account)); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + return priv->ready; } int @@ -636,8 +747,9 @@ empathy_account_manager_get_count (EmpathyAccountManager *manager) } EmpathyAccount * -empathy_account_manager_get_account (EmpathyAccountManager *manager, - TpConnection *connection) +empathy_account_manager_get_account_for_connection ( + EmpathyAccountManager *manager, + TpConnection *connection) { EmpathyAccountManagerPriv *priv; GHashTableIter iter; @@ -659,21 +771,6 @@ empathy_account_manager_get_account (EmpathyAccountManager *manager, return NULL; } -EmpathyAccount * -empathy_account_manager_lookup (EmpathyAccountManager *manager, - const gchar *unique_name) -{ - EmpathyAccountManagerPriv *priv = GET_PRIV (manager); - EmpathyAccount *account; - - account = g_hash_table_lookup (priv->accounts, unique_name); - - if (account != NULL) - g_object_ref (account); - - return account; -} - GList * empathy_account_manager_dup_accounts (EmpathyAccountManager *manager) { @@ -726,8 +823,154 @@ empathy_account_manager_dup_connections (EmpathyAccountManager *manager) } void -empathy_account_manager_remove (EmpathyAccountManager *manager, - EmpathyAccount *account) +empathy_account_manager_request_global_presence ( + EmpathyAccountManager *manager, + TpConnectionPresenceType type, + const gchar *status, + const gchar *message) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GHashTableIter iter; + gpointer value; + + DEBUG ("request global presence, type: %d, status: %s, message: %s", + type, status, message); + + g_hash_table_iter_init (&iter, priv->accounts); + while (g_hash_table_iter_next (&iter, NULL, &value)) + { + EmpathyAccount *account = EMPATHY_ACCOUNT (value); + gboolean ready; + + g_object_get (account, "ready", &ready, NULL); + + if (ready) + empathy_account_request_presence (account, type, status, message); + } + + /* save the requested global presence, to use it in case we create + * new accounts or some accounts become ready. + */ + priv->requested_presence = type; + + if (tp_strdiff (priv->requested_status, status)) + { + g_free (priv->requested_status); + priv->requested_status = g_strdup (status); + } + + if (tp_strdiff (priv->requested_status_message, message)) + { + g_free (priv->requested_status_message); + priv->requested_status_message = g_strdup (message); + } +} + +TpConnectionPresenceType +empathy_account_manager_get_requested_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + if (status != NULL) + *status = g_strdup (priv->requested_status); + if (message != NULL) + *message = g_strdup (priv->requested_status_message); + + return priv->requested_presence; +} + +TpConnectionPresenceType +empathy_account_manager_get_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + + if (status != NULL) + *status = g_strdup (priv->global_status); + if (message != NULL) + *message = g_strdup (priv->global_status_message); + + return priv->global_presence; +} + +static void +empathy_account_manager_created_cb (TpAccountManager *proxy, + const gchar *account_path, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object); + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GSimpleAsyncResult *my_res = user_data; + EmpathyAccount *account; + + if (error != NULL) + { + g_simple_async_result_set_from_error (my_res, + (GError *) error); + g_simple_async_result_complete (my_res); + g_object_unref (my_res); + + return; + } + + account = empathy_account_manager_ensure_account (manager, account_path); + + g_hash_table_insert (priv->create_results, account, my_res); +} + +void +empathy_account_manager_create_account_async (EmpathyAccountManager *manager, + const gchar *connection_manager, + const gchar *protocol, + const gchar *display_name, + GHashTable *parameters, + GHashTable *properties, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyAccountManagerPriv *priv = GET_PRIV (manager); + GSimpleAsyncResult *res; + + res = g_simple_async_result_new + (G_OBJECT (manager), callback, user_data, + empathy_account_manager_create_account_finish); + + tp_cli_account_manager_call_create_account (priv->tp_manager, + -1, + connection_manager, + protocol, + display_name, + parameters, + properties, + empathy_account_manager_created_cb, + res, + NULL, + G_OBJECT (manager)); +} + +EmpathyAccount * +empathy_account_manager_create_account_finish ( + EmpathyAccountManager *manager, GAsyncResult *result, GError **error) { - mc_account_delete (_empathy_account_get_mc_account (account)); + EmpathyAccount *retval; + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return NULL; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (manager), empathy_account_manager_create_account_finish), NULL); + + retval = EMPATHY_ACCOUNT (g_simple_async_result_get_op_res_gpointer ( + G_SIMPLE_ASYNC_RESULT (result))); + + return retval; } + diff --git a/libempathy/empathy-account-manager.h b/libempathy/empathy-account-manager.h index b04571ff8..25adfdbeb 100644 --- a/libempathy/empathy-account-manager.h +++ b/libempathy/empathy-account-manager.h @@ -28,12 +28,17 @@ G_BEGIN_DECLS -#define EMPATHY_TYPE_ACCOUNT_MANAGER (empathy_account_manager_get_type ()) -#define EMPATHY_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManager)) -#define EMPATHY_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) -#define EMPATHY_IS_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EMPATHY_TYPE_ACCOUNT_MANAGER)) -#define EMPATHY_IS_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EMPATHY_TYPE_ACCOUNT_MANAGER)) -#define EMPATHY_ACCOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) +#define EMPATHY_TYPE_ACCOUNT_MANAGER (empathy_account_manager_get_type ()) +#define EMPATHY_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \ + EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManager)) +#define EMPATHY_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \ + EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) +#define EMPATHY_IS_ACCOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ + EMPATHY_TYPE_ACCOUNT_MANAGER)) +#define EMPATHY_IS_ACCOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \ + EMPATHY_TYPE_ACCOUNT_MANAGER)) +#define EMPATHY_ACCOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), \ + EMPATHY_TYPE_ACCOUNT_MANAGER, EmpathyAccountManagerClass)) typedef struct _EmpathyAccountManager EmpathyAccountManager; typedef struct _EmpathyAccountManagerClass EmpathyAccountManagerClass; @@ -52,19 +57,22 @@ GType empathy_account_manager_get_type (void); /* public methods */ EmpathyAccountManager * empathy_account_manager_dup_singleton (void); -EmpathyAccount * empathy_account_manager_create - (EmpathyAccountManager *manager, - McProfile *profile); + +gboolean empathy_account_manager_is_ready (EmpathyAccountManager *manager); + int empathy_account_manager_get_connected_accounts (EmpathyAccountManager *manager); int empathy_account_manager_get_connecting_accounts (EmpathyAccountManager *manager); int empathy_account_manager_get_count (EmpathyAccountManager *manager); -EmpathyAccount * empathy_account_manager_get_account +EmpathyAccount * empathy_account_manager_get_account_for_connection (EmpathyAccountManager *manager, TpConnection *connection); -EmpathyAccount * empathy_account_manager_lookup +EmpathyAccount * empathy_account_manager_ensure_account + (EmpathyAccountManager *manager, + const gchar *unique_name); +EmpathyAccount * empathy_account_manager_get_account (EmpathyAccountManager *manager, const gchar *unique_name); GList * empathy_account_manager_dup_accounts @@ -75,6 +83,31 @@ void empathy_account_manager_remove ( EmpathyAccountManager *manager, EmpathyAccount *account); +void empathy_account_manager_request_global_presence ( + EmpathyAccountManager *manager, + TpConnectionPresenceType type, + const gchar *status, + const gchar *message); + +TpConnectionPresenceType empathy_account_manager_get_requested_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message); + +TpConnectionPresenceType empathy_account_manager_get_global_presence ( + EmpathyAccountManager *manager, + gchar **status, + gchar **message); + +void empathy_account_manager_create_account_async ( + EmpathyAccountManager *manager, const gchar *connection_manager, + const gchar *protocol, const gchar *display_name, + GHashTable *parameters, GHashTable *properties, + GAsyncReadyCallback callback, gpointer user_data); + +EmpathyAccount * empathy_account_manager_create_account_finish ( + EmpathyAccountManager *settings, GAsyncResult *result, GError **error); + G_END_DECLS #endif /* __EMPATHY_ACCOUNT_MANAGER_H__ */ diff --git a/libempathy/empathy-account-priv.h b/libempathy/empathy-account-priv.h deleted file mode 100644 index 8b656b4d8..000000000 --- a/libempathy/empathy-account-priv.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * empathy-account-priv.h - Private Header for EmpathyAccount - * Copyright (C) 2009 Collabora Ltd. - * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> - * - * 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 - */ - -#ifndef __EMPATHY_ACCOUNT_PRIV_H__ -#define __EMPATHY_ACCOUNT_PRIV_H__ - -#include <glib.h> - -#include <libmissioncontrol/mc-account.h> -#include "empathy-account.h" - -G_BEGIN_DECLS - -EmpathyAccount *_empathy_account_new (McAccount *account); -void _empathy_account_set_status (EmpathyAccount *account, - TpConnectionStatus status, - TpConnectionStatusReason reason, - TpConnectionPresenceType presence); -void _empathy_account_set_connection (EmpathyAccount *account, - TpConnection *connection); -void _empathy_account_set_enabled (EmpathyAccount *account, - gboolean enabled); -McAccount *_empathy_account_get_mc_account (EmpathyAccount *account); - -G_END_DECLS - -#endif /* #ifndef __EMPATHY_ACCOUNT_PRIV_H__*/ diff --git a/libempathy/empathy-account-settings.c b/libempathy/empathy-account-settings.c new file mode 100644 index 000000000..81a7a948e --- /dev/null +++ b/libempathy/empathy-account-settings.c @@ -0,0 +1,1179 @@ +/* + * empathy-account-settings.c - Source for EmpathyAccountSettings + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * + * 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 + */ + + +#include <stdio.h> +#include <stdlib.h> + +#include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> +#include <telepathy-glib/gtypes.h> + +#include "empathy-account-settings.h" +#include "empathy-account-manager.h" +#include "empathy-connection-managers.h" +#include "empathy-utils.h" + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountSettings) + +G_DEFINE_TYPE(EmpathyAccountSettings, empathy_account_settings, G_TYPE_OBJECT) + +enum { + PROP_ACCOUNT = 1, + PROP_CM_NAME, + PROP_PROTOCOL, + PROP_DISPLAY_NAME, + PROP_DISPLAY_NAME_OVERRIDDEN, + PROP_READY +}; + +/* private structure */ +typedef struct _EmpathyAccountSettingsPriv EmpathyAccountSettingsPriv; + +struct _EmpathyAccountSettingsPriv +{ + gboolean dispose_has_run; + EmpathyConnectionManagers *managers; + EmpathyAccountManager *account_manager; + gulong account_manager_ready_id; + + TpConnectionManager *manager; + const TpConnectionManagerProtocol *tp_protocol; + + EmpathyAccount *account; + gchar *cm_name; + gchar *protocol; + gchar *display_name; + gchar *icon_name; + gboolean display_name_overridden; + gboolean ready; + + GHashTable *parameters; + GArray *unset_parameters; + GArray *required_params; + + gulong managers_ready_id; + gulong account_ready_id; + + GSimpleAsyncResult *apply_result; +}; + +static void +empathy_account_settings_init (EmpathyAccountSettings *obj) +{ + EmpathyAccountSettingsPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE ((obj), + EMPATHY_TYPE_ACCOUNT_SETTINGS, EmpathyAccountSettingsPriv); + + obj->priv = priv; + + /* allocate any data required by the object here */ + priv->managers = empathy_connection_managers_dup_singleton (); + priv->account_manager = empathy_account_manager_dup_singleton (); + + priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) tp_g_value_slice_free); + + priv->unset_parameters = g_array_new (TRUE, FALSE, sizeof (gchar *)); +} + +static void empathy_account_settings_dispose (GObject *object); +static void empathy_account_settings_finalize (GObject *object); +static void empathy_account_settings_ready_cb (GObject *obj, + GParamSpec *spec, gpointer user_data); +static void empathy_account_settings_check_readyness ( + EmpathyAccountSettings *self); + +static void +empathy_account_settings_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + switch (prop_id) + { + case PROP_ACCOUNT: + priv->account = g_value_dup_object (value); + break; + case PROP_CM_NAME: + priv->cm_name = g_value_dup_string (value); + break; + case PROP_PROTOCOL: + priv->protocol = g_value_dup_string (value); + break; + case PROP_DISPLAY_NAME: + priv->display_name = g_value_dup_string (value); + break; + case PROP_DISPLAY_NAME_OVERRIDDEN: + priv->display_name_overridden = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_account_settings_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + switch (prop_id) + { + case PROP_ACCOUNT: + g_value_set_object (value, priv->account); + break; + case PROP_CM_NAME: + g_value_set_string (value, priv->cm_name); + break; + case PROP_PROTOCOL: + g_value_set_string (value, priv->protocol); + break; + case PROP_DISPLAY_NAME: + g_value_set_string (value, priv->display_name); + break; + case PROP_DISPLAY_NAME_OVERRIDDEN: + g_value_set_boolean (value, priv->display_name_overridden); + break; + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_account_settings_constructed (GObject *object) +{ + EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + if (priv->account != NULL) + { + g_free (priv->cm_name); + g_free (priv->protocol); + + priv->cm_name = + g_strdup (empathy_account_get_connection_manager (priv->account)); + priv->protocol = + g_strdup (empathy_account_get_protocol (priv->account)); + } + + priv->icon_name = g_strdup_printf ("im-%s", priv->protocol); + + g_assert (priv->cm_name != NULL && priv->protocol != NULL); + + empathy_account_settings_check_readyness (self); + + if (!priv->ready) + { + g_signal_connect (priv->account, "notify::ready", + G_CALLBACK (empathy_account_settings_ready_cb), self); + g_signal_connect (priv->managers, "notify::ready", + G_CALLBACK (empathy_account_settings_ready_cb), self); + } + + if (G_OBJECT_CLASS ( + empathy_account_settings_parent_class)->constructed != NULL) + G_OBJECT_CLASS ( + empathy_account_settings_parent_class)->constructed (object); +} + + +static void +empathy_account_settings_class_init ( + EmpathyAccountSettingsClass *empathy_account_settings_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_account_settings_class); + + g_type_class_add_private (empathy_account_settings_class, sizeof + (EmpathyAccountSettingsPriv)); + + object_class->dispose = empathy_account_settings_dispose; + object_class->finalize = empathy_account_settings_finalize; + object_class->set_property = empathy_account_settings_set_property; + object_class->get_property = empathy_account_settings_get_property; + object_class->constructed = empathy_account_settings_constructed; + + g_object_class_install_property (object_class, PROP_ACCOUNT, + g_param_spec_object ("account", + "Account", + "The EmpathyAccount backing these settings", + EMPATHY_TYPE_ACCOUNT, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_CM_NAME, + g_param_spec_string ("connection-manager", + "connection-manager", + "The name of the connection manager this account uses", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_PROTOCOL, + g_param_spec_string ("protocol", + "Protocol", + "The name of the protocol this account uses", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DISPLAY_NAME, + g_param_spec_string ("display-name", + "display-name", + "The display name account these settings belong to", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DISPLAY_NAME_OVERRIDDEN, + g_param_spec_boolean ("display-name-overridden", + "display-name-overridden", + "Whether the display name for this account has been manually overridden", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether this account is ready to be used", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); +} + +static void +empathy_account_settings_dispose (GObject *object) +{ + EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->managers_ready_id != 0) + g_signal_handler_disconnect (priv->managers, priv->managers_ready_id); + priv->managers_ready_id = 0; + + if (priv->managers != NULL) + g_object_unref (priv->managers); + priv->managers = NULL; + + if (priv->manager != NULL) + g_object_unref (priv->manager); + priv->manager = NULL; + + if (priv->account_manager_ready_id != 0) + g_signal_handler_disconnect (priv->account_manager, + priv->account_manager_ready_id); + priv->account_manager_ready_id = 0; + + if (priv->account_manager != NULL) + g_object_unref (priv->account_manager); + priv->account_manager = NULL; + + if (priv->account_ready_id != 0) + g_signal_handler_disconnect (priv->account, priv->account_ready_id); + priv->account_ready_id = 0; + + if (priv->account != NULL) + g_object_unref (priv->account); + priv->account = NULL; + + /* release any references held by the object here */ + if (G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose) + G_OBJECT_CLASS (empathy_account_settings_parent_class)->dispose (object); +} + +static void +empathy_account_settings_free_unset_parameters ( + EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + int i; + + for (i = 0 ; i < priv->unset_parameters->len; i++) + g_free (g_array_index (priv->unset_parameters, gchar *, i)); + + g_array_set_size (priv->unset_parameters, 0); +} + +static void +empathy_account_settings_finalize (GObject *object) +{ + EmpathyAccountSettings *self = EMPATHY_ACCOUNT_SETTINGS (object); + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + /* free any data held directly by the object here */ + g_free (priv->cm_name); + g_free (priv->protocol); + g_free (priv->display_name); + g_free (priv->icon_name); + + g_hash_table_destroy (priv->parameters); + + empathy_account_settings_free_unset_parameters (self); + g_array_free (priv->unset_parameters, TRUE); + + G_OBJECT_CLASS (empathy_account_settings_parent_class)->finalize (object); +} + +static void +empathy_account_settings_check_readyness (EmpathyAccountSettings *self) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (self); + + if (priv->ready) + return; + + if (priv->account != NULL && !empathy_account_is_ready (priv->account)) + return; + + if (!empathy_connection_managers_is_ready (priv->managers)) + return; + + priv->manager = empathy_connection_managers_get_cm ( + priv->managers, priv->cm_name); + + if (priv->manager == NULL) + return; + + if (priv->account != NULL) + { + g_free (priv->display_name); + priv->display_name = + g_strdup (empathy_account_get_display_name (priv->account)); + + g_free (priv->icon_name); + priv->icon_name = + g_strdup (empathy_account_get_icon_name (priv->account)); + } + + priv->tp_protocol = tp_connection_manager_get_protocol (priv->manager, + priv->protocol); + + if (priv->tp_protocol == NULL) + { + priv->manager = NULL; + return; + } + + if (priv->required_params == NULL) + { + TpConnectionManagerParam *cur; + char *val; + + priv->required_params = g_array_new (TRUE, FALSE, sizeof (gchar *)); + + for (cur = priv->tp_protocol->params; cur->name != NULL; cur++) + { + if (tp_connection_manager_param_is_required (cur)) + { + val = g_strdup (cur->name); + g_array_append_val (priv->required_params, val); + } + } + } + + g_object_ref (priv->manager); + + priv->ready = TRUE; + g_object_notify (G_OBJECT (self), "ready"); +} + +static void +empathy_account_settings_ready_cb (GObject *obj, + GParamSpec *spec, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + + empathy_account_settings_check_readyness (settings); +} + +EmpathyAccountSettings * +empathy_account_settings_new (const gchar *connection_manager, + const gchar *protocol, + const char *display_name) +{ + return g_object_new (EMPATHY_TYPE_ACCOUNT_SETTINGS, + "connection-manager", connection_manager, + "protocol", protocol, + "display-name", display_name, + NULL); +} + +EmpathyAccountSettings * +empathy_account_settings_new_for_account (EmpathyAccount *account) +{ + return g_object_new (EMPATHY_TYPE_ACCOUNT_SETTINGS, + "account", account, + NULL); +} + +TpConnectionManagerParam * +empathy_account_settings_get_tp_params (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + g_return_val_if_fail (priv->tp_protocol != NULL, NULL); + + return priv->tp_protocol->params; +} + +gboolean +empathy_account_settings_is_ready (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->ready; +} + +const gchar * +empathy_account_settings_get_cm (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->cm_name; +} + +const gchar * +empathy_account_settings_get_protocol (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->protocol; +} + +gchar * +empathy_account_settings_get_icon_name (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->icon_name; +} + +const gchar * +empathy_account_settings_get_display_name (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->display_name; +} + +EmpathyAccount * +empathy_account_settings_get_account (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + return priv->account; +} + +static gboolean +empathy_account_settings_is_unset (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GArray *a; + int i; + + a = priv->unset_parameters; + + for (i = 0; i < a->len; i++) + { + if (!tp_strdiff (g_array_index (a, gchar *, i), param)) + return TRUE; + } + + return FALSE; +} + +static TpConnectionManagerParam * +empathy_account_settings_get_tp_param (EmpathyAccountSettings *settings, + const gchar *param) +{ + TpConnectionManagerParam *tp_params = + empathy_account_settings_get_tp_params (settings); + TpConnectionManagerParam *p; + + for (p = tp_params; p != NULL && p->name != NULL; p++) + { + if (tp_strdiff (p->name, param)) + continue; + + return p; + } + + return NULL; +} + +static void +account_settings_remove_from_unset (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + int idx; + gchar *val; + + for (idx = 0; idx < priv->unset_parameters->len; idx++) + { + val = g_array_index (priv->unset_parameters, gchar *, idx); + + if (!tp_strdiff (val, param)) + { + priv->unset_parameters = + g_array_remove_index (priv->unset_parameters, idx); + g_free (val); + + break; + } + } +} + +const GValue * +empathy_account_settings_get_default (EmpathyAccountSettings *settings, + const gchar *param) +{ + TpConnectionManagerParam *p; + + p = empathy_account_settings_get_tp_param (settings, param); + + if (p == NULL || !(p->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT)) + return NULL; + + return &(p->default_value); +} + +const gchar * +empathy_account_settings_get_dbus_signature (EmpathyAccountSettings *settings, + const gchar *param) +{ + TpConnectionManagerParam *p; + + p = empathy_account_settings_get_tp_param (settings, param); + + if (p == NULL) + return NULL; + + return p->dbus_signature; +} + +const GValue * +empathy_account_settings_get (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + const GValue *result = NULL; + + /* Lookup the update parameters we set */ + result = tp_asv_lookup (priv->parameters, param); + if (result != NULL) + return result; + + /* If the parameters isn't unset use the accounts setting if any */ + if (priv->account != NULL + && !empathy_account_settings_is_unset (settings, param)) + { + const GHashTable *parameters; + + parameters = empathy_account_get_parameters (priv->account); + result = tp_asv_lookup (parameters, param); + + if (result != NULL) + return result; + } + + /* fallback to the default */ + return empathy_account_settings_get_default (settings, param); +} + +void +empathy_account_settings_unset (EmpathyAccountSettings *settings, + const gchar *param) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + gchar *v; + if (empathy_account_settings_is_unset (settings, param)) + return; + + v = g_strdup (param); + + g_array_append_val (priv->unset_parameters, v); + g_hash_table_remove (priv->parameters, param); +} + +void +empathy_account_settings_discard_changes (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + g_hash_table_remove_all (priv->parameters); + empathy_account_settings_free_unset_parameters (settings); +} + +const gchar * +empathy_account_settings_get_string (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL || !G_VALUE_HOLDS_STRING (v)) + return NULL; + + return g_value_get_string (v); +} + +gint32 +empathy_account_settings_get_int32 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + gint32 ret = 0; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL) + return 0; + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = g_value_get_int (v); + break; + case G_TYPE_UINT: + ret = CLAMP (G_MININT32, g_value_get_uint (v), G_MAXINT32); + break; + case G_TYPE_INT64: + ret = CLAMP (G_MININT32, g_value_get_int64 (v), G_MAXINT32); + break; + case G_TYPE_UINT64: + ret = CLAMP (G_MININT32, g_value_get_uint64 (v), G_MAXINT32); + break; + default: + ret = 0; + break; + } + + return ret; +} + +gint64 +empathy_account_settings_get_int64 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + gint64 ret = 0; + + v = empathy_account_settings_get (settings, param); + if (v == NULL) + return 0; + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = g_value_get_int (v); + break; + case G_TYPE_UINT: + ret = g_value_get_uint (v); + break; + case G_TYPE_INT64: + ret = g_value_get_int64 (v); + break; + case G_TYPE_UINT64: + ret = CLAMP (G_MININT64, g_value_get_uint64 (v), G_MAXINT64); + break; + default: + ret = 0; + break; + } + + return ret; +} + +guint32 +empathy_account_settings_get_uint32 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + guint32 ret; + + v = empathy_account_settings_get (settings, param); + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = MAX (0, g_value_get_int (v)); + break; + case G_TYPE_UINT: + ret = g_value_get_uint (v); + break; + case G_TYPE_INT64: + ret = CLAMP (0, g_value_get_int64 (v), G_MAXUINT32); + break; + case G_TYPE_UINT64: + ret = CLAMP (0, g_value_get_uint64 (v), G_MAXUINT32); + break; + default: + ret = 0; + break; + } + + return ret; +} + +guint64 +empathy_account_settings_get_uint64 (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + guint64 ret = 0; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL || !G_VALUE_HOLDS_INT (v)) + return 0; + + switch G_VALUE_TYPE (v) + { + case G_TYPE_UCHAR: + ret = g_value_get_uchar (v); + break; + case G_TYPE_INT: + ret = MAX (0, g_value_get_int (v)); + break; + case G_TYPE_UINT: + ret = g_value_get_uint (v); + break; + case G_TYPE_INT64: + ret = MAX (0, g_value_get_int64 (v)); + break; + case G_TYPE_UINT64: + ret = CLAMP (0, g_value_get_uint64 (v), G_MAXUINT64); + break; + default: + ret = 0; + break; + } + + return ret; +} + +gboolean +empathy_account_settings_get_boolean (EmpathyAccountSettings *settings, + const gchar *param) +{ + const GValue *v; + + v = empathy_account_settings_get (settings, param); + + if (v == NULL || !G_VALUE_HOLDS_BOOLEAN (v)) + return FALSE; + + return g_value_get_boolean (v); +} + +void +empathy_account_settings_set_string (EmpathyAccountSettings *settings, + const gchar *param, + const gchar *value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_string (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_int32 (EmpathyAccountSettings *settings, + const gchar *param, + gint32 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_int32 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_int64 (EmpathyAccountSettings *settings, + const gchar *param, + gint64 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_int64 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_uint32 (EmpathyAccountSettings *settings, + const gchar *param, + guint32 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_uint32 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_uint64 (EmpathyAccountSettings *settings, + const gchar *param, + guint64 value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_uint64 (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +void +empathy_account_settings_set_boolean (EmpathyAccountSettings *settings, + const gchar *param, + gboolean value) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + tp_asv_set_boolean (priv->parameters, g_strdup (param), value); + + account_settings_remove_from_unset (settings, param); +} + +static void +account_settings_display_name_set_cb (GObject *src, + GAsyncResult *res, + gpointer user_data) +{ + GError *error = NULL; + EmpathyAccount *account = EMPATHY_ACCOUNT (src); + GSimpleAsyncResult *set_result = user_data; + + empathy_account_set_display_name_finish (account, res, &error); + + if (error != NULL) + { + g_simple_async_result_set_from_error (set_result, error); + g_error_free (error); + } + + g_simple_async_result_complete (set_result); + g_object_unref (set_result); +} + +void +empathy_account_settings_set_display_name_async ( + EmpathyAccountSettings *settings, + const gchar *name, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GSimpleAsyncResult *result; + + result = g_simple_async_result_new (G_OBJECT (settings), + callback, user_data, empathy_account_settings_set_display_name_finish); + + if (priv->account == NULL) + { + if (priv->display_name != NULL) + g_free (priv->display_name); + + priv->display_name = g_strdup (name); + + g_simple_async_result_complete_in_idle (result); + + return; + } + + empathy_account_set_display_name_async (priv->account, name, + account_settings_display_name_set_cb, result); +} + +gboolean +empathy_account_settings_set_display_name_finish ( + EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (settings), empathy_account_settings_set_display_name_finish), + FALSE); + + return TRUE; +} + +static void +empathy_account_settings_account_updated (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GSimpleAsyncResult *r; + GError *error = NULL; + + if (!empathy_account_update_settings_finish (EMPATHY_ACCOUNT (source), + result, &error)) + { + g_simple_async_result_set_from_error (priv->apply_result, error); + g_error_free (error); + } + else + { + empathy_account_settings_discard_changes (settings); + } + + r = priv->apply_result; + priv->apply_result = NULL; + + g_simple_async_result_complete (r); + g_object_unref (r); +} + +static void +empathy_account_settings_created_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + EmpathyAccount *account; + GError *error = NULL; + GSimpleAsyncResult *r; + + account = empathy_account_manager_create_account_finish ( + EMPATHY_ACCOUNT_MANAGER (source), result, &error); + + if (account == NULL) + { + g_simple_async_result_set_from_error (priv->apply_result, error); + } + else + { + priv->account = g_object_ref (account); + empathy_account_settings_discard_changes (settings); + } + + r = priv->apply_result; + priv->apply_result = NULL; + + g_simple_async_result_complete (r); + g_object_unref (r); +} + + +static void +empathy_account_settings_do_create_account (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + GHashTable *properties; + TpConnectionPresenceType type; + gchar *status; + gchar *message; + + properties = tp_asv_new (NULL, NULL); + + type = empathy_account_manager_get_requested_global_presence + (priv->account_manager, &status, &message); + + if (type != TP_CONNECTION_PRESENCE_TYPE_UNSET) + { + /* Create the account with the requested presence the same as the current + * global requested presence, but don't enable it */ + GValueArray *presence; + GValue vtype = { 0, }; + GValue vstatus = { 0, }; + GValue vmessage = { 0, }; + + presence = g_value_array_new (3); + + g_value_init (&vtype, G_TYPE_UINT); + g_value_set_uint (&vtype, type); + g_value_array_append (presence, &vtype); + + g_value_init (&vstatus, G_TYPE_STRING); + g_value_take_string (&vstatus, status); + g_value_array_append (presence, &vstatus); + + g_value_init (&vmessage, G_TYPE_STRING); + g_value_take_string (&vmessage, message); + g_value_array_append (presence, &vmessage); + + tp_asv_take_boxed (properties, TP_IFACE_ACCOUNT ".RequestedPresence", + TP_STRUCT_TYPE_SIMPLE_PRESENCE, presence); + } + + empathy_account_manager_create_account_async (priv->account_manager, + priv->cm_name, priv->protocol, priv->display_name, + priv->parameters, properties, + empathy_account_settings_created_cb, + settings); + + g_hash_table_unref (properties); +} + +static void +empathy_account_settings_manager_ready_cb (EmpathyAccountManager *manager, + GParamSpec *spec, + gpointer user_data) +{ + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (user_data); + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + if (empathy_account_manager_is_ready (manager)) + { + g_assert (priv->apply_result != NULL && priv->account == NULL); + g_signal_handler_disconnect (priv->account_manager, + priv->account_manager_ready_id); + priv->account_manager_ready_id = 0; + + empathy_account_settings_do_create_account (settings); + } +} + +void +empathy_account_settings_apply_async (EmpathyAccountSettings *settings, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EmpathyAccountSettingsPriv *priv = GET_PRIV (settings); + + if (priv->apply_result != NULL) + { + g_simple_async_report_error_in_idle (G_OBJECT (settings), + callback, user_data, + G_IO_ERROR, G_IO_ERROR_PENDING, "Applying already in progress"); + return; + } + + priv->apply_result = g_simple_async_result_new (G_OBJECT (settings), + callback, user_data, empathy_account_settings_apply_finish); + + if (priv->account == NULL) + { + if (empathy_account_manager_is_ready (priv->account_manager)) + empathy_account_settings_do_create_account (settings); + else + priv->account_manager_ready_id = g_signal_connect ( + priv->account_manager, + "notify::ready", + G_CALLBACK (empathy_account_settings_manager_ready_cb), + settings); + } + else + { + empathy_account_update_settings_async (priv->account, + priv->parameters, (const gchar **)priv->unset_parameters->data, + empathy_account_settings_account_updated, settings); + } +} + +gboolean +empathy_account_settings_apply_finish (EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (settings), empathy_account_settings_apply_finish), FALSE); + + return TRUE; +} + +gboolean +empathy_account_settings_has_account (EmpathyAccountSettings *settings, + EmpathyAccount *account) +{ + EmpathyAccountSettingsPriv *priv; + + g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE); + g_return_val_if_fail (EMPATHY_IS_ACCOUNT (account), FALSE); + + priv = GET_PRIV (settings); + + return (account == priv->account); +} + +gboolean +empathy_account_settings_is_valid (EmpathyAccountSettings *settings) +{ + EmpathyAccountSettingsPriv *priv; + int idx; + gchar *current; + gboolean missed = FALSE; + + g_return_val_if_fail (EMPATHY_IS_ACCOUNT_SETTINGS (settings), FALSE); + + priv = GET_PRIV (settings); + + for (idx = 0; idx < priv->required_params->len; idx++) + { + current = g_array_index (priv->required_params, gchar *, idx); + + /* first, look if it's set in our own parameters */ + if (tp_asv_lookup (priv->parameters, current)) + continue; + + /* if we did not unset the parameter, look if it's in the account */ + if (priv->account != NULL && + !empathy_account_settings_is_unset (settings, current)) + { + const GHashTable *account_params; + + account_params = empathy_account_get_parameters (priv->account); + if (tp_asv_lookup (account_params, current)) + continue; + } + + missed = TRUE; + break; + } + + return !missed; +} diff --git a/libempathy/empathy-account-settings.h b/libempathy/empathy-account-settings.h new file mode 100644 index 000000000..476bfb397 --- /dev/null +++ b/libempathy/empathy-account-settings.h @@ -0,0 +1,163 @@ +/* + * empathy-account-settings.h - Header for EmpathyAccountSettings + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * + * 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 + */ + +#ifndef __EMPATHY_ACCOUNT_SETTINGS_H__ +#define __EMPATHY_ACCOUNT_SETTINGS_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +#include <libempathy/empathy-account.h> +#include <telepathy-glib/connection-manager.h> + +G_BEGIN_DECLS + +typedef struct _EmpathyAccountSettings EmpathyAccountSettings; +typedef struct _EmpathyAccountSettingsClass EmpathyAccountSettingsClass; + +struct _EmpathyAccountSettingsClass { + GObjectClass parent_class; +}; + +struct _EmpathyAccountSettings { + GObject parent; + gpointer priv; +}; + +GType empathy_account_settings_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_ACCOUNT_SETTINGS \ + (empathy_account_settings_get_type ()) +#define EMPATHY_ACCOUNT_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + EMPATHY_TYPE_ACCOUNT_SETTINGS, EmpathyAccountSettings)) +#define EMPATHY_ACCOUNT_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_ACCOUNT_SETTINGS, \ + EmpathyAccountSettingsClass)) +#define EMPATHY_IS_ACCOUNT_SETTINGS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_ACCOUNT_SETTINGS)) +#define EMPATHY_IS_ACCOUNT_SETTINGS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_ACCOUNT_SETTINGS)) +#define EMPATHY_ACCOUNT_SETTINGS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT_SETTINGS, \ + EmpathyAccountSettingsClass)) + +EmpathyAccountSettings * empathy_account_settings_new ( + const gchar *connection_manager, + const gchar *protocol, + const char *display_name); + +EmpathyAccountSettings * empathy_account_settings_new_for_account ( + EmpathyAccount *account); + +gboolean empathy_account_settings_is_ready (EmpathyAccountSettings *settings); + +const gchar *empathy_account_settings_get_cm (EmpathyAccountSettings *settings); +const gchar *empathy_account_settings_get_protocol ( + EmpathyAccountSettings *settings); + +EmpathyAccount *empathy_account_settings_get_account ( + EmpathyAccountSettings *settings); + +gboolean empathy_account_settings_has_account ( + EmpathyAccountSettings *settings, EmpathyAccount *account); + +TpConnectionManagerParam *empathy_account_settings_get_tp_params ( + EmpathyAccountSettings *settings); + +void empathy_account_settings_unset (EmpathyAccountSettings *settings, + const gchar *param); + +void empathy_account_settings_discard_changes ( + EmpathyAccountSettings *settings); + +const GValue *empathy_account_settings_get (EmpathyAccountSettings *settings, + const gchar *param); + +const gchar * +empathy_account_settings_get_dbus_signature (EmpathyAccountSettings *setting, + const gchar *param); + +const GValue * +empathy_account_settings_get_default (EmpathyAccountSettings *settings, + const gchar *param); + +const gchar *empathy_account_settings_get_string ( + EmpathyAccountSettings *settings, + const gchar *param); + +gint32 empathy_account_settings_get_int32 (EmpathyAccountSettings *settings, + const gchar *param); +gint64 empathy_account_settings_get_int64 (EmpathyAccountSettings *settings, + const gchar *param); +guint32 empathy_account_settings_get_uint32 (EmpathyAccountSettings *settings, + const gchar *param); +guint64 empathy_account_settings_get_uint64 (EmpathyAccountSettings *settings, + const gchar *param); +gboolean empathy_account_settings_get_boolean (EmpathyAccountSettings *settings, + const gchar *param); + +void empathy_account_settings_set_string (EmpathyAccountSettings *settings, + const gchar *param, const gchar *value); + +void empathy_account_settings_set_int32 (EmpathyAccountSettings *settings, + const gchar *param, gint32 value); +void empathy_account_settings_set_int64 (EmpathyAccountSettings *settings, + const gchar *param, gint64 value); +void empathy_account_settings_set_uint32 (EmpathyAccountSettings *settings, + const gchar *param, guint32 value); +void empathy_account_settings_set_uint64 (EmpathyAccountSettings *settings, + const gchar *param, guint64 value); + +void empathy_account_settings_set_boolean (EmpathyAccountSettings *settings, + const gchar *param, gboolean value); + +gchar *empathy_account_settings_get_icon_name ( + EmpathyAccountSettings *settings); + +const gchar *empathy_account_settings_get_display_name ( + EmpathyAccountSettings *settings); + +void empathy_account_settings_set_display_name_async ( + EmpathyAccountSettings *settings, + const gchar *name, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean empathy_account_settings_set_display_name_finish ( + EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error); + +void empathy_account_settings_apply_async (EmpathyAccountSettings *settings, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean empathy_account_settings_apply_finish ( + EmpathyAccountSettings *settings, + GAsyncResult *result, + GError **error); + +gboolean empathy_account_settings_is_valid (EmpathyAccountSettings *settings); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_ACCOUNT_SETTINGS_H__*/ diff --git a/libempathy/empathy-account.c b/libempathy/empathy-account.c index e0a8e756b..091950880 100644 --- a/libempathy/empathy-account.c +++ b/libempathy/empathy-account.c @@ -18,17 +18,24 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <telepathy-glib/enums.h> +#include <telepathy-glib/dbus.h> +#include <telepathy-glib/account.h> +#include <telepathy-glib/gtypes.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> +#include <telepathy-glib/defs.h> #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> +#include <glib/gi18n-lib.h> + #include "empathy-account.h" -#include "empathy-account-priv.h" #include "empathy-utils.h" #include "empathy-marshal.h" @@ -36,6 +43,7 @@ enum { STATUS_CHANGED, PRESENCE_CHANGED, + REMOVED, LAST_SIGNAL }; @@ -45,10 +53,14 @@ static guint signals[LAST_SIGNAL]; enum { PROP_ENABLED = 1, PROP_PRESENCE, + PROP_STATUS, + PROP_STATUS_MESSAGE, + PROP_READY, PROP_CONNECTION_STATUS, PROP_CONNECTION_STATUS_REASON, PROP_CONNECTION, PROP_UNIQUE_NAME, + PROP_DBUS_DAEMON, PROP_DISPLAY_NAME }; @@ -64,19 +76,37 @@ struct _EmpathyAccountPriv TpConnection *connection; guint connection_invalidated_id; - TpConnectionStatus status; + TpConnectionStatus connection_status; TpConnectionStatusReason reason; + TpConnectionPresenceType presence; + gchar *status; + gchar *message; gboolean enabled; + gboolean valid; + gboolean ready; + gboolean removed; /* Timestamp when the connection got connected in seconds since the epoch */ glong connect_time; - McAccount *mc_account; + gchar *cm_name; + gchar *proto_name; + gchar *icon_name; + + gchar *unique_name; + gchar *display_name; + TpDBusDaemon *dbus; + + TpAccount *account; + GHashTable *parameters; }; #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccount) +static void _empathy_account_set_connection (EmpathyAccount *account, + const gchar *path); + static void empathy_account_init (EmpathyAccount *obj) { @@ -87,7 +117,34 @@ empathy_account_init (EmpathyAccount *obj) obj->priv = priv; - priv->status = TP_CONNECTION_STATUS_DISCONNECTED; + priv->connection_status = TP_CONNECTION_STATUS_DISCONNECTED; +} + +static void +empathy_account_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + switch (prop_id) + { + case PROP_ENABLED: + empathy_account_set_enabled_async (account, + g_value_get_boolean (value), NULL, NULL); + break; + case PROP_UNIQUE_NAME: + priv->unique_name = g_value_dup_string (value); + break; + case PROP_DBUS_DAEMON: + priv->dbus = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void @@ -104,11 +161,20 @@ empathy_account_get_property (GObject *object, case PROP_ENABLED: g_value_set_boolean (value, priv->enabled); break; + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; case PROP_PRESENCE: g_value_set_uint (value, priv->presence); break; + case PROP_STATUS: + g_value_set_string (value, priv->status); + break; + case PROP_STATUS_MESSAGE: + g_value_set_string (value, priv->message); + break; case PROP_CONNECTION_STATUS: - g_value_set_uint (value, priv->status); + g_value_set_uint (value, priv->connection_status); break; case PROP_CONNECTION_STATUS_REASON: g_value_set_uint (value, priv->reason); @@ -125,12 +191,297 @@ empathy_account_get_property (GObject *object, g_value_set_string (value, empathy_account_get_display_name (account)); break; + case PROP_DBUS_DAEMON: + g_value_set_object (value, priv->dbus); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } +static void +empathy_account_update (EmpathyAccount *account, + GHashTable *properties) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + GValueArray *arr; + TpConnectionStatus old_s = priv->connection_status; + gboolean presence_changed = FALSE; + + if (g_hash_table_lookup (properties, "ConnectionStatus") != NULL) + priv->connection_status = + tp_asv_get_int32 (properties, "ConnectionStatus", NULL); + + if (g_hash_table_lookup (properties, "ConnectionStatusReason") != NULL) + priv->reason = tp_asv_get_int32 (properties, + "ConnectionStatusReason", NULL); + + if (g_hash_table_lookup (properties, "CurrentPresence") != NULL) + { + presence_changed = TRUE; + arr = tp_asv_get_boxed (properties, "CurrentPresence", + TP_STRUCT_TYPE_SIMPLE_PRESENCE); + priv->presence = g_value_get_uint (g_value_array_get_nth (arr, 0)); + + g_free (priv->status); + priv->status = g_value_dup_string (g_value_array_get_nth (arr, 1)); + + g_free (priv->message); + priv->message = g_value_dup_string (g_value_array_get_nth (arr, 2)); + } + + if (g_hash_table_lookup (properties, "DisplayName") != NULL) + { + g_free (priv->display_name); + priv->display_name = + g_strdup (tp_asv_get_string (properties, "DisplayName")); + g_object_notify (G_OBJECT (account), "display-name"); + } + + if (g_hash_table_lookup (properties, "Enabled") != NULL) + { + gboolean enabled = tp_asv_get_boolean (properties, "Enabled", NULL); + if (priv->enabled != enabled) + { + priv->enabled = enabled; + g_object_notify (G_OBJECT (account), "enabled"); + } + } + + if (g_hash_table_lookup (properties, "Valid") != NULL) + priv->valid = tp_asv_get_boolean (properties, "Valid", NULL); + + if (g_hash_table_lookup (properties, "Parameters") != NULL) + { + GHashTable *parameters; + + parameters = tp_asv_get_boxed (properties, "Parameters", + TP_HASH_TYPE_STRING_VARIANT_MAP); + + if (priv->parameters != NULL) + g_hash_table_unref (priv->parameters); + + priv->parameters = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP, + parameters); + } + + if (!priv->ready) + { + priv->ready = TRUE; + g_object_notify (G_OBJECT (account), "ready"); + } + + if (priv->connection_status != old_s) + { + if (priv->connection_status == TP_CONNECTION_STATUS_CONNECTED) + { + GTimeVal val; + g_get_current_time (&val); + + priv->connect_time = val.tv_sec; + } + + g_signal_emit (account, signals[STATUS_CHANGED], 0, + old_s, priv->connection_status, priv->reason); + + g_object_notify (G_OBJECT (account), "connection-status"); + g_object_notify (G_OBJECT (account), "connection-status-reason"); + } + + if (presence_changed) + { + g_signal_emit (account, signals[PRESENCE_CHANGED], 0, + priv->presence, priv->status, priv->message); + g_object_notify (G_OBJECT (account), "presence"); + g_object_notify (G_OBJECT (account), "status"); + g_object_notify (G_OBJECT (account), "status-message"); + } + + if (g_hash_table_lookup (properties, "Connection") != NULL) + { + const gchar *conn_path = + tp_asv_get_object_path (properties, "Connection"); + + _empathy_account_set_connection (account, conn_path); + } +} + +static void +empathy_account_properties_changed (TpAccount *proxy, + GHashTable *properties, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (weak_object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (!priv->ready) + return; + + empathy_account_update (account, properties); +} + +static void +empathy_account_removed_cb (TpAccount *proxy, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (weak_object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (priv->removed) + return; + + priv->removed = TRUE; + + g_signal_emit (account, signals[REMOVED], 0); +} + +static void +empathy_account_got_all_cb (TpProxy *proxy, + GHashTable *properties, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (weak_object); + + DEBUG ("Got initial set of properties for %s", + empathy_account_get_unique_name (account)); + + if (error != NULL) + { + DEBUG ("Failed to get the initial set of account properties: %s", + error->message); + return; + } + + empathy_account_update (account, properties); +} + +static gchar * +empathy_account_unescape_protocol (const gchar *protocol, gssize len) +{ + gchar *result, *escape; + /* Bad implementation might accidentally use tp_escape_as_identifier, + * which escapes - in the wrong way... */ + if ((escape = g_strstr_len (protocol, len, "_2d")) != NULL) + { + GString *str; + const gchar *input; + + str = g_string_new (""); + input = protocol; + do { + g_string_append_len (str, input, escape - input); + g_string_append_c (str, '-'); + + len -= escape - input + 3; + input = escape + 3; + } while ((escape = g_strstr_len (input, len, "_2d")) != NULL); + + g_string_append_len (str, input, len); + + result = g_string_free (str, FALSE); + } + else + { + result = g_strndup (protocol, len); + } + + g_strdelimit (result, "_", '-'); + + return result; +} + +static gboolean +empathy_account_parse_unique_name (const gchar *bus_name, + gchar **protocol, gchar **manager) +{ + const gchar *proto, *proto_end; + const gchar *cm, *cm_end; + + g_return_val_if_fail ( + g_str_has_prefix (bus_name, TP_ACCOUNT_OBJECT_PATH_BASE), FALSE); + + cm = bus_name + strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + for (cm_end = cm; *cm_end != '/' && *cm_end != '\0'; cm_end++) + /* pass */; + + if (*cm_end == '\0') + return FALSE; + + if (cm_end == '\0') + return FALSE; + + proto = cm_end + 1; + + for (proto_end = proto; *proto_end != '/' && *proto_end != '\0'; proto_end++) + /* pass */; + + if (*proto_end == '\0') + return FALSE; + + if (protocol != NULL) + { + *protocol = empathy_account_unescape_protocol (proto, proto_end - proto); + } + + if (manager != NULL) + *manager = g_strndup (cm, cm_end - cm); + + return TRUE; +} + +static void +account_invalidated_cb (TpProxy *proxy, guint domain, gint code, + gchar *message, gpointer user_data) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (user_data); + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (priv->removed) + return; + + priv->removed = TRUE; + + g_signal_emit (account, signals[REMOVED], 0); +} + +static void +empathy_account_constructed (GObject *object) +{ + EmpathyAccount *account = EMPATHY_ACCOUNT (object); + EmpathyAccountPriv *priv = GET_PRIV (account); + + priv->account = tp_account_new (priv->dbus, priv->unique_name, NULL); + + g_signal_connect (priv->account, "invalidated", + G_CALLBACK (account_invalidated_cb), object); + + empathy_account_parse_unique_name (priv->unique_name, + &(priv->proto_name), &(priv->cm_name)); + + priv->icon_name = empathy_protocol_icon_name (priv->proto_name); + + tp_cli_account_connect_to_account_property_changed (priv->account, + empathy_account_properties_changed, + NULL, NULL, object, NULL); + + tp_cli_account_connect_to_removed (priv->account, + empathy_account_removed_cb, + NULL, NULL, object, NULL); + + tp_cli_dbus_properties_call_get_all (priv->account, -1, + TP_IFACE_ACCOUNT, + empathy_account_got_all_cb, + NULL, + NULL, + G_OBJECT (account)); +} + static void empathy_account_dispose (GObject *object); static void empathy_account_finalize (GObject *object); @@ -142,15 +493,24 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) g_type_class_add_private (empathy_account_class, sizeof (EmpathyAccountPriv)); + object_class->set_property = empathy_account_set_property; object_class->get_property = empathy_account_get_property; object_class->dispose = empathy_account_dispose; object_class->finalize = empathy_account_finalize; + object_class->constructed = empathy_account_constructed; g_object_class_install_property (object_class, PROP_ENABLED, g_param_spec_boolean ("enabled", "Enabled", "Whether this account is enabled or not", FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether this account is ready to be used", + FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_PRESENCE, @@ -162,8 +522,22 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) TP_CONNECTION_PRESENCE_TYPE_UNSET, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_STATUS, + g_param_spec_string ("status", + "Status", + "The Status string of the account", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_STATUS_MESSAGE, + g_param_spec_string ("status-message", + "status-message", + "The Status message string of the account", + NULL, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_CONNECTION_STATUS, - g_param_spec_uint ("status", + g_param_spec_uint ("connection-status", "ConnectionStatus", "The accounts connections status type", 0, @@ -172,7 +546,7 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); g_object_class_install_property (object_class, PROP_CONNECTION_STATUS_REASON, - g_param_spec_uint ("status-reason", + g_param_spec_uint ("connection-status-reason", "ConnectionStatusReason", "The account connections status reason", 0, @@ -192,7 +566,14 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) "UniqueName", "The accounts unique name", NULL, - G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_DBUS_DAEMON, + g_param_spec_object ("dbus-daemon", + "dbus-daemon", + "The Tp Dbus daemon on which this account exists", + TP_TYPE_DBUS_DAEMON, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_DISPLAY_NAME, g_param_spec_string ("display-name", @@ -212,8 +593,30 @@ empathy_account_class_init (EmpathyAccountClass *empathy_account_class) G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _empathy_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + _empathy_marshal_VOID__UINT_STRING_STRING, + G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); + + signals[REMOVED] = g_signal_new ("removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +empathy_account_free_connection (EmpathyAccount *account) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (priv->connection_invalidated_id != 0) + g_signal_handler_disconnect (priv->connection, + priv->connection_invalidated_id); + priv->connection_invalidated_id = 0; + + if (priv->connection != NULL) + g_object_unref (priv->connection); + priv->connection = NULL; } void @@ -227,14 +630,7 @@ empathy_account_dispose (GObject *object) priv->dispose_has_run = TRUE; - if (priv->connection_invalidated_id != 0) - g_signal_handler_disconnect (priv->connection, - priv->connection_invalidated_id); - priv->connection_invalidated_id = 0; - - if (priv->connection != NULL) - g_object_unref (priv->connection); - priv->connection = NULL; + empathy_account_free_connection (self); /* release any references held by the object here */ if (G_OBJECT_CLASS (empathy_account_parent_class)->dispose != NULL) @@ -244,6 +640,16 @@ empathy_account_dispose (GObject *object) void empathy_account_finalize (GObject *object) { + EmpathyAccountPriv *priv = GET_PRIV (object); + + g_free (priv->status); + g_free (priv->message); + + g_free (priv->cm_name); + g_free (priv->proto_name); + g_free (priv->icon_name); + g_free (priv->display_name); + /* free any data held directly by the object here */ if (G_OBJECT_CLASS (empathy_account_parent_class)->finalize != NULL) G_OBJECT_CLASS (empathy_account_parent_class)->finalize (object); @@ -255,7 +661,7 @@ empathy_account_is_just_connected (EmpathyAccount *account) EmpathyAccountPriv *priv = GET_PRIV (account); GTimeVal val; - if (priv->status != TP_CONNECTION_STATUS_CONNECTED) + if (priv->connection_status != TP_CONNECTION_STATUS_CONNECTED) return FALSE; g_get_current_time (&val); @@ -285,6 +691,35 @@ empathy_account_get_connection (EmpathyAccount *account) } /** + * empathy_account_get_connection_for_path: + * @account: a #EmpathyAccount + * @patch: the path to connection object for #EmpathyAccount + * + * Get the connection of the account on path. This function does not return a + * new ref. It is not guaranteed that the returned connection object is ready + * + * Returns: the connection of the account. + **/ +TpConnection * +empathy_account_get_connection_for_path (EmpathyAccount *account, + const gchar *path) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + + /* double-check that the object path is valid */ + if (!tp_dbus_check_valid_object_path (path, NULL)) + return NULL; + + /* Should be a full object path, not the special "/" value */ + if (strlen (path) == 1) + return NULL; + + _empathy_account_set_connection (account, path); + + return priv->connection; +} + +/** * empathy_account_get_unique_name: * @account: a #EmpathyAccount * @@ -295,7 +730,7 @@ empathy_account_get_unique_name (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_get_unique_name (priv->mc_account); + return priv->unique_name; } /** @@ -309,7 +744,7 @@ empathy_account_get_display_name (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_get_display_name (priv->mc_account); + return priv->display_name; } gboolean @@ -317,154 +752,66 @@ empathy_account_is_valid (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_is_complete (priv->mc_account); -} - -void -empathy_account_set_enabled (EmpathyAccount *account, gboolean enabled) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - - mc_account_set_enabled (priv->mc_account, enabled); + return priv->valid; } -gboolean -empathy_account_is_enabled (EmpathyAccount *account) +const gchar * +empathy_account_get_connection_manager (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - return priv->enabled; + return priv->cm_name; } -void -empathy_account_unset_param (EmpathyAccount *account, const gchar *param) +const gchar * +empathy_account_get_protocol (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_unset_param (priv->mc_account, param); + return priv->proto_name; } -gchar * -empathy_account_get_param_string (EmpathyAccount *account, const gchar *param) +const gchar * +empathy_account_get_icon_name (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - gchar *value = NULL; - mc_account_get_param_string (priv->mc_account, param, &value); - return value; + return priv->icon_name; } -gint -empathy_account_get_param_int (EmpathyAccount *account, const gchar *param) +const GHashTable * +empathy_account_get_parameters (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - int value; - mc_account_get_param_int (priv->mc_account, param, &value); - return value; + return priv->parameters; } gboolean -empathy_account_get_param_boolean (EmpathyAccount *account, const gchar *param) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - gboolean value; - - mc_account_get_param_boolean (priv->mc_account, param, &value); - return value; -} - -void -empathy_account_set_param_string (EmpathyAccount *account, - const gchar *param, - const gchar *value) +empathy_account_is_enabled (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_param_string (priv->mc_account, param, value); -} -void -empathy_account_set_param_int (EmpathyAccount *account, - const gchar *param, - gint value) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_param_int (priv->mc_account, param, value); + return priv->enabled; } -void -empathy_account_set_param_boolean (EmpathyAccount *account, - const gchar *param, - gboolean value) +gboolean +empathy_account_is_ready (EmpathyAccount *account) { EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_param_boolean (priv->mc_account, param, value); -} -void -empathy_account_set_display_name (EmpathyAccount *account, - const gchar *display_name) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - mc_account_set_display_name (priv->mc_account, display_name); + return priv->ready; } -McProfile * -empathy_account_get_profile (EmpathyAccount *account) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - return mc_account_get_profile (priv->mc_account); -} EmpathyAccount * -_empathy_account_new (McAccount *mc_account) +empathy_account_new (TpDBusDaemon *dbus, + const gchar *unique_name) { - EmpathyAccount *account; - EmpathyAccountPriv *priv; - - account = g_object_new (EMPATHY_TYPE_ACCOUNT, NULL); - priv = GET_PRIV (account); - priv->mc_account = mc_account; - - return account; -} - -void -_empathy_account_set_status (EmpathyAccount *account, - TpConnectionStatus status, - TpConnectionStatusReason reason, - TpConnectionPresenceType presence) -{ - EmpathyAccountPriv *priv = GET_PRIV (account); - TpConnectionStatus old_s = priv->status; - TpConnectionPresenceType old_p = priv->presence; - - priv->status = status; - priv->presence = presence; - - if (priv->status != old_s) - { - if (priv->status == TP_CONNECTION_STATUS_CONNECTED) - { - GTimeVal val; - g_get_current_time (&val); - - priv->connect_time = val.tv_sec; - } - - priv->reason = reason; - g_signal_emit (account, signals[STATUS_CHANGED], 0, - old_s, priv->status, reason); - - g_object_notify (G_OBJECT (account), "status"); - } - - if (priv->presence != old_p) - { - g_signal_emit (account, signals[PRESENCE_CHANGED], 0, - old_p, priv->presence); - g_object_notify (G_OBJECT (account), "presence"); - } + return EMPATHY_ACCOUNT (g_object_new (EMPATHY_TYPE_ACCOUNT, + "dbus-daemon", dbus, + "unique-name", unique_name, + NULL)); } static void @@ -473,13 +820,12 @@ empathy_account_connection_ready_cb (TpConnection *connection, gpointer user_data) { EmpathyAccount *account = EMPATHY_ACCOUNT (user_data); - EmpathyAccountPriv *priv = GET_PRIV (account); if (error != NULL) { DEBUG ("(%s) Connection failed to become ready: %s", empathy_account_get_unique_name (account), error->message); - priv->connection = NULL; + empathy_account_free_connection (account); } else { @@ -517,20 +863,22 @@ _empathy_account_connection_invalidated_cb (TpProxy *self, g_object_notify (G_OBJECT (account), "connection"); } -void +static void _empathy_account_set_connection (EmpathyAccount *account, - TpConnection *connection) + const gchar *path) { EmpathyAccountPriv *priv = GET_PRIV (account); - if (priv->connection == connection) - return; + if (priv->connection != NULL) + { + const gchar *current; - /* Connection already set, don't set the new one */ - if (connection != NULL && priv->connection != NULL) - return; + current = tp_proxy_get_object_path (priv->connection); + if (!tp_strdiff (current, path)) + return; + } - if (connection == NULL) + if (priv->connection != NULL) { g_signal_handler_disconnect (priv->connection, priv->connection_invalidated_id); @@ -538,38 +886,284 @@ _empathy_account_set_connection (EmpathyAccount *account, g_object_unref (priv->connection); priv->connection = NULL; - g_object_notify (G_OBJECT (account), "connection"); } - else + + if (tp_strdiff ("/", path)) { - priv->connection = g_object_ref (connection); - priv->connection_invalidated_id = g_signal_connect (priv->connection, - "invalidated", - G_CALLBACK (_empathy_account_connection_invalidated_cb), - account); - - /* notify a change in the connection property when it's ready */ - tp_connection_call_when_ready (priv->connection, - empathy_account_connection_ready_cb, account); + GError *error = NULL; + priv->connection = tp_connection_new (priv->dbus, NULL, path, &error); + + if (priv->connection == NULL) + { + DEBUG ("Failed to create a new TpConnection: %s", + error->message); + g_error_free (error); + } + else + { + priv->connection_invalidated_id = g_signal_connect (priv->connection, + "invalidated", + G_CALLBACK (_empathy_account_connection_invalidated_cb), account); + + DEBUG ("Readying connection for %s", priv->unique_name); + /* notify a change in the connection property when it's ready */ + tp_connection_call_when_ready (priv->connection, + empathy_account_connection_ready_cb, account); + } } + + g_object_notify (G_OBJECT (account), "connection"); +} + +static void +account_enabled_set_cb (TpProxy *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = user_data; + + if (error != NULL) + g_simple_async_result_set_from_error (result, (GError *) error); + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +gboolean +empathy_account_set_enabled_finish (EmpathyAccount *account, + GAsyncResult *result, + GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error) || + !g_simple_async_result_is_valid (result, G_OBJECT (account), + empathy_account_set_enabled_finish)) + return FALSE; + + return TRUE; } void -_empathy_account_set_enabled (EmpathyAccount *account, - gboolean enabled) +empathy_account_set_enabled_async (EmpathyAccount *account, + gboolean enabled, + GAsyncReadyCallback callback, + gpointer user_data) { EmpathyAccountPriv *priv = GET_PRIV (account); + GValue value = {0, }; + GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account), + callback, user_data, empathy_account_set_enabled_finish); if (priv->enabled == enabled) - return; + { + g_simple_async_result_complete_in_idle (result); + return; + } + + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, enabled); + + tp_cli_dbus_properties_call_set (TP_PROXY (priv->account), + -1, TP_IFACE_ACCOUNT, "Enabled", &value, + account_enabled_set_cb, result, NULL, G_OBJECT (account)); +} + +static void +empathy_account_requested_presence_cb (TpProxy *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + if (error) + DEBUG ("Failed to set the requested presence: %s", error->message); +} + + +void +empathy_account_request_presence (EmpathyAccount *account, + TpConnectionPresenceType type, + const gchar *status, + const gchar *message) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + GValue value = {0, }; + GValueArray *arr; + + g_value_init (&value, TP_STRUCT_TYPE_SIMPLE_PRESENCE); + g_value_take_boxed (&value, dbus_g_type_specialized_construct + (TP_STRUCT_TYPE_SIMPLE_PRESENCE)); + arr = (GValueArray *) g_value_get_boxed (&value); + + g_value_set_uint (arr->values, type); + g_value_set_static_string (arr->values + 1, status); + g_value_set_static_string (arr->values + 2, message); + + tp_cli_dbus_properties_call_set (TP_PROXY (priv->account), + -1, + TP_IFACE_ACCOUNT, + "RequestedPresence", + &value, + empathy_account_requested_presence_cb, + NULL, + NULL, + G_OBJECT (account)); + + g_value_unset (&value); +} + +static void +empathy_account_updated_cb (TpAccount *proxy, + const gchar **reconnect_required, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + + if (error != NULL) + { + g_simple_async_result_set_from_error (result, (GError *) error); + } + + g_simple_async_result_complete (result); + g_object_unref (G_OBJECT (result)); +} + +void +empathy_account_update_settings_async (EmpathyAccount *account, + GHashTable *parameters, const gchar **unset_parameters, + GAsyncReadyCallback callback, gpointer user_data) +{ + EmpathyAccountPriv *priv = GET_PRIV (account); + GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account), + callback, user_data, empathy_account_update_settings_finish); + + tp_cli_account_call_update_parameters (priv->account, + -1, + parameters, + unset_parameters, + empathy_account_updated_cb, + result, + NULL, + G_OBJECT (account)); +} + +gboolean +empathy_account_update_settings_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (account), empathy_account_update_settings_finish), FALSE); + + return TRUE; +} + +static void +account_display_name_set_cb (TpProxy *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = user_data; + + if (error != NULL) + g_simple_async_result_set_from_error (result, (GError *) error); + + g_simple_async_result_complete (result); + g_object_unref (result); +} + +void +empathy_account_set_display_name_async (EmpathyAccount *account, + const char *display_name, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *result; + GValue value = {0, }; + EmpathyAccountPriv *priv = GET_PRIV (account); + + if (display_name == NULL) + { + g_simple_async_report_error_in_idle (G_OBJECT (account), + callback, user_data, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Can't set an empty display name")); + return; + } + + result = g_simple_async_result_new (G_OBJECT (account), callback, + user_data, empathy_account_set_display_name_finish); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_string (&value, display_name); + + tp_cli_dbus_properties_call_set (priv->account, -1, TP_IFACE_ACCOUNT, + "DisplayName", &value, account_display_name_set_cb, result, NULL, + G_OBJECT (account)); +} - priv->enabled = enabled; - g_object_notify (G_OBJECT (account), "enabled"); +gboolean +empathy_account_set_display_name_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error) || + !g_simple_async_result_is_valid (result, G_OBJECT (account), + empathy_account_set_display_name_finish)) + return FALSE; + + return TRUE; } -McAccount * -_empathy_account_get_mc_account (EmpathyAccount *account) +static void +empathy_account_remove_cb (TpAccount *proxy, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); + + if (error != NULL) + { + g_simple_async_result_set_from_error (result, (GError *) error); + } + + g_simple_async_result_complete (result); + g_object_unref (G_OBJECT (result)); +} + +void +empathy_account_remove_async (EmpathyAccount *account, + GAsyncReadyCallback callback, gpointer user_data) { EmpathyAccountPriv *priv = GET_PRIV (account); - return priv->mc_account; + GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account), + callback, user_data, empathy_account_remove_finish); + + tp_cli_account_call_remove (priv->account, + -1, + empathy_account_remove_cb, + result, + NULL, + G_OBJECT (account)); +} + +gboolean +empathy_account_remove_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error) +{ + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, + G_OBJECT (account), empathy_account_update_settings_finish), FALSE); + + return TRUE; } + diff --git a/libempathy/empathy-account.h b/libempathy/empathy-account.h index 75babd826..f88ac43e4 100644 --- a/libempathy/empathy-account.h +++ b/libempathy/empathy-account.h @@ -22,9 +22,9 @@ #define __EMPATHY_ACCOUNT_H__ #include <glib-object.h> +#include <gio/gio.h> #include <telepathy-glib/connection.h> -#include <libmissioncontrol/mc-profile.h> G_BEGIN_DECLS @@ -58,36 +58,51 @@ GType empathy_account_get_type (void); gboolean empathy_account_is_just_connected (EmpathyAccount *account); TpConnection *empathy_account_get_connection (EmpathyAccount *account); +TpConnection *empathy_account_get_connection_for_path (EmpathyAccount *account, + const gchar *path); const gchar *empathy_account_get_unique_name (EmpathyAccount *account); const gchar *empathy_account_get_display_name (EmpathyAccount *account); -void empathy_account_set_enabled (EmpathyAccount *account, - gboolean enabled); -gboolean empathy_account_is_enabled (EmpathyAccount *account); +const gchar *empathy_account_get_connection_manager (EmpathyAccount *account); +const gchar *empathy_account_get_protocol (EmpathyAccount *account); +const gchar *empathy_account_get_icon_name (EmpathyAccount *account); + +void empathy_account_set_enabled_async (EmpathyAccount *account, + gboolean enabled, GAsyncReadyCallback callback, gpointer user_data); +gboolean empathy_account_set_enabled_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); -void empathy_account_unset_param (EmpathyAccount *account, const gchar *param); -gchar *empathy_account_get_param_string (EmpathyAccount *account, - const gchar *param); -gint empathy_account_get_param_int (EmpathyAccount *account, - const gchar *param); -gboolean empathy_account_get_param_boolean (EmpathyAccount *account, - const gchar *param); - -void empathy_account_set_param_string (EmpathyAccount *account, - const gchar *param, const gchar *value); -void empathy_account_set_param_int (EmpathyAccount *account, - const gchar *param, gint value); -void empathy_account_set_param_boolean (EmpathyAccount *account, - const gchar *param, gboolean value); +gboolean empathy_account_is_enabled (EmpathyAccount *account); gboolean empathy_account_is_valid (EmpathyAccount *account); +gboolean empathy_account_is_ready (EmpathyAccount *account); + +void empathy_account_update_settings_async (EmpathyAccount *account, + GHashTable *parameters, const gchar **unset_parameters, + GAsyncReadyCallback callback, gpointer user_data); + +gboolean empathy_account_update_settings_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); + +void empathy_account_remove_async (EmpathyAccount *account, + GAsyncReadyCallback callback, gpointer user_data); +gboolean empathy_account_remove_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); + +void empathy_account_set_display_name_async (EmpathyAccount *account, + const gchar *display_name, GAsyncReadyCallback callback, + gpointer user_data); +gboolean empathy_account_set_display_name_finish (EmpathyAccount *account, + GAsyncResult *result, GError **error); + +EmpathyAccount *empathy_account_new (TpDBusDaemon *bus_daemon, + const gchar *unique_name); -void empathy_account_set_display_name (EmpathyAccount *account, - const gchar *display_name); +void empathy_account_request_presence (EmpathyAccount *account, + TpConnectionPresenceType type, const gchar *status, const gchar *message); +const GHashTable *empathy_account_get_parameters (EmpathyAccount *account); -/* TODO remove McProfile */ -McProfile *empathy_account_get_profile (EmpathyAccount *account); G_END_DECLS diff --git a/libempathy/empathy-call-handler.c b/libempathy/empathy-call-handler.c index 72c317b7f..1c6e53c6c 100644 --- a/libempathy/empathy-call-handler.c +++ b/libempathy/empathy-call-handler.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include <telepathy-farsight/channel.h> #include <telepathy-farsight/stream.h> diff --git a/libempathy/empathy-chatroom-manager.c b/libempathy/empathy-chatroom-manager.c index 940b56220..7c3559e2f 100644 --- a/libempathy/empathy-chatroom-manager.c +++ b/libempathy/empathy-chatroom-manager.c @@ -30,6 +30,8 @@ #include <libxml/parser.h> #include <libxml/tree.h> +#include <telepathy-glib/interfaces.h> + #include "empathy-tp-chat.h" #include "empathy-chatroom-manager.h" #include "empathy-account-manager.h" @@ -221,7 +223,8 @@ chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager, xmlFree (str); } - account = empathy_account_manager_lookup (priv->account_manager, account_id); + account = empathy_account_manager_get_account (priv->account_manager, + account_id); if (!account) { g_free (name); g_free (room); @@ -234,7 +237,6 @@ chatroom_manager_parse_chatroom (EmpathyChatroomManager *manager, add_chatroom (manager, chatroom); g_signal_emit (manager, signals[CHATROOM_ADDED], 0, chatroom); - g_object_unref (account); g_free (name); g_free (room); g_free (account_id); @@ -578,9 +580,8 @@ empathy_chatroom_manager_find (EmpathyChatroomManager *manager, this_account = empathy_chatroom_get_account (chatroom); this_room = empathy_chatroom_get_room (chatroom); - if (this_account && this_room && - empathy_account_equal (account, this_account) && - strcmp (this_room, room) == 0) { + if (this_account && this_room && account == this_account + && strcmp (this_room, room) == 0) { return chatroom; } } @@ -609,8 +610,7 @@ empathy_chatroom_manager_get_chatrooms (EmpathyChatroomManager *manager, chatroom = l->data; - if (empathy_account_equal (account, - empathy_chatroom_get_account (chatroom))) { + if (account == empathy_chatroom_get_account (chatroom)) { chatrooms = g_list_append (chatrooms, chatroom); } } @@ -639,8 +639,7 @@ empathy_chatroom_manager_get_count (EmpathyChatroomManager *manager, chatroom = l->data; - if (empathy_account_equal (account, - empathy_chatroom_get_account (chatroom))) { + if (account == empathy_chatroom_get_account (chatroom)) { count++; } } @@ -705,8 +704,8 @@ chatroom_manager_observe_channel_cb (EmpathyDispatcher *dispatcher, chat = EMPATHY_TP_CHAT ( empathy_dispatch_operation_get_channel_wrapper (operation)); connection = empathy_tp_chat_get_connection (chat); - account = empathy_account_manager_get_account (priv->account_manager, - connection); + account = empathy_account_manager_get_account_for_connection ( + priv->account_manager, connection); roomname = empathy_tp_chat_get_id (chat); diff --git a/libempathy/empathy-chatroom.c b/libempathy/empathy-chatroom.c index b62d6ad77..33df9a3d6 100644 --- a/libempathy/empathy-chatroom.c +++ b/libempathy/empathy-chatroom.c @@ -480,8 +480,7 @@ empathy_chatroom_equal (gconstpointer v1, room_a = empathy_chatroom_get_room (EMPATHY_CHATROOM (v1)); room_b = empathy_chatroom_get_room (EMPATHY_CHATROOM (v2)); - return empathy_account_equal (account_a, account_b) && - !tp_strdiff (room_a, room_b); + return account_a == account_b && !tp_strdiff (room_a, room_b); } EmpathyTpChat * diff --git a/libempathy/empathy-connection-managers.c b/libempathy/empathy-connection-managers.c new file mode 100644 index 000000000..bd6f315e2 --- /dev/null +++ b/libempathy/empathy-connection-managers.c @@ -0,0 +1,293 @@ +/* + * empathy-connection-managers.c - Source for EmpathyConnectionManagers + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * + * 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 + */ + + +#include <stdio.h> +#include <stdlib.h> + +#include <telepathy-glib/connection-manager.h> +#include <telepathy-glib/util.h> + +#include "empathy-connection-managers.h" +#include "empathy-utils.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_OTHER +#include <libempathy/empathy-debug.h> + +static GObject *managers = NULL; + +G_DEFINE_TYPE(EmpathyConnectionManagers, empathy_connection_managers, + G_TYPE_OBJECT) + +/* signal enum */ +enum +{ + UPDATED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +/* properties */ +enum { + PROP_READY = 1 +}; + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyConnectionManagers) + + +/* private structure */ +typedef struct _EmpathyConnectionManagersPriv + EmpathyConnectionManagersPriv; + +struct _EmpathyConnectionManagersPriv +{ + gboolean dispose_has_run; + gboolean ready; + + GList *cms; + + TpDBusDaemon *dbus; +}; + +static void +empathy_connection_managers_init (EmpathyConnectionManagers *obj) +{ + EmpathyConnectionManagersPriv *priv = + G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + EMPATHY_TYPE_CONNECTION_MANAGERS, EmpathyConnectionManagersPriv); + + obj->priv = priv; + + priv->dbus = tp_dbus_daemon_dup (NULL); + g_assert (priv->dbus != NULL); + + empathy_connection_managers_update (obj); + + /* allocate any data required by the object here */ +} + +static void empathy_connection_managers_dispose (GObject *object); + +static GObject * +empathy_connection_managers_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + if (managers != NULL) + return g_object_ref (managers); + + managers = + G_OBJECT_CLASS (empathy_connection_managers_parent_class)->constructor + (type, n_construct_params, construct_params); + + g_object_add_weak_pointer (managers, (gpointer) &managers); + + return managers; +} + + + +static void +empathy_connection_managers_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyConnectionManagers *managers = EMPATHY_CONNECTION_MANAGERS (object); + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + + switch (prop_id) + { + case PROP_READY: + g_value_set_boolean (value, priv->ready); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +empathy_connection_managers_class_init ( + EmpathyConnectionManagersClass *empathy_connection_managers_class) +{ + GObjectClass *object_class = + G_OBJECT_CLASS (empathy_connection_managers_class); + + g_type_class_add_private (empathy_connection_managers_class, sizeof + (EmpathyConnectionManagersPriv)); + + object_class->constructor = empathy_connection_managers_constructor; + object_class->dispose = empathy_connection_managers_dispose; + object_class->get_property = empathy_connection_managers_get_property; + + g_object_class_install_property (object_class, PROP_READY, + g_param_spec_boolean ("ready", + "Ready", + "Whether the connection manager information is ready to be used", + FALSE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + + signals[UPDATED] = g_signal_new ("updated", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +empathy_connection_managers_free_cm_list (EmpathyConnectionManagers *self) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (self); + GList *l; + + for (l = priv->cms ; l != NULL ; l = g_list_next (l)) + { + g_object_unref (l->data); + } + g_list_free (priv->cms); + + priv->cms = NULL; +} + +static void +empathy_connection_managers_dispose (GObject *object) +{ + EmpathyConnectionManagers *self = EMPATHY_CONNECTION_MANAGERS (object); + EmpathyConnectionManagersPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->dbus != NULL) + g_object_unref (priv->dbus); + priv->dbus = NULL; + + empathy_connection_managers_free_cm_list (self); + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (empathy_connection_managers_parent_class)->dispose) + G_OBJECT_CLASS (empathy_connection_managers_parent_class)->dispose (object); +} + +EmpathyConnectionManagers * +empathy_connection_managers_dup_singleton (void) +{ + return EMPATHY_CONNECTION_MANAGERS ( + g_object_new (EMPATHY_TYPE_CONNECTION_MANAGERS, NULL)); +} + +gboolean +empathy_connection_managers_is_ready (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + return priv->ready; +} + +static void +empathy_connection_managers_listed_cb (TpConnectionManager * const *cms, + gsize n_cms, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyConnectionManagers *self = + EMPATHY_CONNECTION_MANAGERS (weak_object); + EmpathyConnectionManagersPriv *priv = GET_PRIV (self); + TpConnectionManager * const *iter; + + empathy_connection_managers_free_cm_list (self); + + if (error != NULL) + { + DEBUG ("Failed to get connection managers: %s", error->message); + goto out; + } + + for (iter = cms ; iter != NULL && *iter != NULL; iter++) + { + /* only list cms that didn't hit errors */ + if (tp_connection_manager_is_ready (*iter)) + priv->cms = g_list_prepend (priv->cms, g_object_ref (*iter)); + } + +out: + g_object_ref (weak_object); + if (!priv->ready) + { + priv->ready = TRUE; + g_object_notify (weak_object, "ready"); + } + g_signal_emit (weak_object, signals[UPDATED], 0); + g_object_unref (weak_object); +} + +void +empathy_connection_managers_update (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + + tp_list_connection_managers (priv->dbus, + empathy_connection_managers_listed_cb, + NULL, NULL, G_OBJECT (managers)); +} + +GList * +empathy_connection_managers_get_cms (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + + return priv->cms; +} + +TpConnectionManager * +empathy_connection_managers_get_cm (EmpathyConnectionManagers *managers, + const gchar *cm) +{ + EmpathyConnectionManagersPriv *priv = GET_PRIV (managers); + GList *l; + + for (l = priv->cms ; l != NULL; l = g_list_next (l)) + { + TpConnectionManager *c = TP_CONNECTION_MANAGER (l->data); + + if (!tp_strdiff (c->name, cm)) + return c; + } + + return NULL; +} + +guint +empathy_connection_managers_get_cms_num (EmpathyConnectionManagers *managers) +{ + EmpathyConnectionManagersPriv *priv; + + g_return_val_if_fail (EMPATHY_IS_CONNECTION_MANAGERS (managers), 0); + + priv = GET_PRIV (managers); + + return g_list_length (priv->cms); +} diff --git a/libempathy/empathy-connection-managers.h b/libempathy/empathy-connection-managers.h new file mode 100644 index 000000000..17289d36d --- /dev/null +++ b/libempathy/empathy-connection-managers.h @@ -0,0 +1,77 @@ +/* + * empathy-connection-managers.h - Header for EmpathyConnectionManagers + * Copyright (C) 2009 Collabora Ltd. + * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> + * + * 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 + */ + +#ifndef __EMPATHY_CONNECTION_MANAGERS_H__ +#define __EMPATHY_CONNECTION_MANAGERS_H__ + +#include <glib-object.h> + +#include <telepathy-glib/connection-manager.h> + +G_BEGIN_DECLS + +typedef struct _EmpathyConnectionManagers EmpathyConnectionManagers; +typedef struct _EmpathyConnectionManagersClass EmpathyConnectionManagersClass; + +struct _EmpathyConnectionManagersClass { + GObjectClass parent_class; +}; + +struct _EmpathyConnectionManagers { + GObject parent; + gpointer priv; +}; + +GType empathy_connection_managers_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_CONNECTION_MANAGERS \ + (empathy_connection_managers_get_type ()) +#define EMPATHY_CONNECTION_MANAGERS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_CONNECTION_MANAGERS, \ + EmpathyConnectionManagers)) +#define EMPATHY_CONNECTION_MANAGERS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_CONNECTION_MANAGERS, \ + EmpathyConnectionManagersClass)) +#define EMPATHY_IS_CONNECTION_MANAGERS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_CONNECTION_MANAGERS)) +#define EMPATHY_IS_CONNECTION_MANAGERS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_CONNECTION_MANAGERS)) +#define EMPATHY_CONNECTION_MANAGERS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_CONNECTION_MANAGERS, \ + EmpathyConnectionManagersClass)) + +EmpathyConnectionManagers *empathy_connection_managers_dup_singleton (void); +gboolean empathy_connection_managers_is_ready ( + EmpathyConnectionManagers *managers); + +void empathy_connection_managers_update (EmpathyConnectionManagers *managers); + +GList * empathy_connection_managers_get_cms ( + EmpathyConnectionManagers *managers); +guint empathy_connection_managers_get_cms_num + (EmpathyConnectionManagers *managers); + +TpConnectionManager *empathy_connection_managers_get_cm ( + EmpathyConnectionManagers *managers, const gchar *cm); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_CONNECTION_MANAGERS_H__*/ diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c index c82ecd467..44d9dbeed 100644 --- a/libempathy/empathy-contact.c +++ b/libempathy/empathy-contact.c @@ -570,7 +570,8 @@ empathy_contact_get_account (EmpathyContact *contact) /* FIXME: This assume the account manager already exists */ manager = empathy_account_manager_dup_singleton (); connection = tp_contact_get_connection (priv->tp_contact); - priv->account = empathy_account_manager_get_account (manager, connection); + priv->account = empathy_account_manager_get_account_for_connection ( + manager, connection); g_object_ref (priv->account); g_object_unref (manager); } @@ -857,27 +858,23 @@ contact_get_avatar_filename (EmpathyContact *contact, gchar *avatar_path; gchar *avatar_file; gchar *token_escaped; - gchar *contact_escaped; if (EMP_STR_EMPTY (empathy_contact_get_id (contact))) return NULL; - contact_escaped = tp_escape_as_identifier (empathy_contact_get_id (contact)); token_escaped = tp_escape_as_identifier (token); account = empathy_contact_get_account (contact); - /* FIXME: Do not use the account, but proto/cm instead */ avatar_path = g_build_filename (g_get_user_cache_dir (), - PACKAGE_NAME, + "telepathy", "avatars", - empathy_account_get_unique_name (account), - contact_escaped, + empathy_account_get_connection_manager (account), + empathy_account_get_protocol (account), NULL); g_mkdir_with_parents (avatar_path, 0700); avatar_file = g_build_filename (avatar_path, token_escaped, NULL); - g_free (contact_escaped); g_free (token_escaped); g_free (avatar_path); diff --git a/libempathy/empathy-debug.c b/libempathy/empathy-debug.c index 9d69b801c..141340024 100644 --- a/libempathy/empathy-debug.c +++ b/libempathy/empathy-debug.c @@ -50,6 +50,7 @@ static GDebugKey keys[] = { { "Location", EMPATHY_DEBUG_LOCATION }, { "Other", EMPATHY_DEBUG_OTHER }, { "Connectivity", EMPATHY_DEBUG_CONNECTIVITY }, + { "ImportMc4Accounts", EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS }, { 0, } }; diff --git a/libempathy/empathy-debug.h b/libempathy/empathy-debug.h index edfa05d95..cc8eca0a3 100644 --- a/libempathy/empathy-debug.h +++ b/libempathy/empathy-debug.h @@ -43,6 +43,7 @@ typedef enum EMPATHY_DEBUG_OTHER = 1 << 9, EMPATHY_DEBUG_SHARE_DESKTOP = 1 << 10, EMPATHY_DEBUG_CONNECTIVITY = 1 << 11, + EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS = 1 << 11, } EmpathyDebugFlags; gboolean empathy_debug_flag_is_set (EmpathyDebugFlags flag); diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c index b51df95fa..c1a19f699 100644 --- a/libempathy/empathy-dispatcher.c +++ b/libempathy/empathy-dispatcher.c @@ -19,6 +19,9 @@ * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> */ +#define DISPATCHER_BUS_NAME TP_CLIENT_BUS_NAME_BASE "Empathy" +#define DISPATCHER_OBJECT_PATH TP_CLIENT_OBJECT_PATH_BASE "Empathy" + #include <config.h> #include <string.h> @@ -31,8 +34,10 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/proxy-subclass.h> #include <telepathy-glib/gtypes.h> - -#include <libmissioncontrol/mission-control.h> +#include <telepathy-glib/defs.h> +#include <telepathy-glib/svc-client.h> +#include <telepathy-glib/svc-generic.h> +#include <telepathy-glib/interfaces.h> #include <extensions/extensions.h> @@ -51,7 +56,6 @@ typedef struct { EmpathyAccountManager *account_manager; - MissionControl *mc; /* connection to connection data mapping */ GHashTable *connections; GHashTable *outstanding_classes_requests; @@ -64,7 +68,30 @@ typedef struct GHashTable *request_channel_class_async_ids; } EmpathyDispatcherPriv; -G_DEFINE_TYPE (EmpathyDispatcher, empathy_dispatcher, G_TYPE_OBJECT); +static void empathy_dispatcher_client_handler_iface_init (gpointer g_iface, + gpointer g_iface_data); + +G_DEFINE_TYPE_WITH_CODE (EmpathyDispatcher, + empathy_dispatcher, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, + tp_dbus_properties_mixin_iface_init); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT, NULL); + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CLIENT_HANDLER, + empathy_dispatcher_client_handler_iface_init); + ); + +static const gchar *empathy_dispatcher_interfaces[] = { + TP_IFACE_CLIENT_HANDLER, + NULL +}; + +enum +{ + PROP_INTERFACES = 1, + PROP_CHANNEL_FILTER, + PROP_CHANNELS +}; enum { @@ -77,6 +104,10 @@ enum static guint signals[LAST_SIGNAL]; static EmpathyDispatcher *dispatcher = NULL; +static void dispatcher_init_connection_if_needed ( + EmpathyDispatcher *dispatcher, + TpConnection *connection); + static GList * empathy_dispatcher_find_channel_classes (EmpathyDispatcher *dispatcher, TpConnection *connection, const gchar *channel_type, guint handle_type, GArray *fixed_properties); @@ -563,6 +594,8 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher, NULL }; + dispatcher_init_connection_if_needed (dispatcher, connection); + cd = g_hash_table_lookup (priv->connections, connection); /* Don't bother with channels we have already dispatched or are dispatching @@ -638,30 +671,11 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher, } static void -dispatcher_connection_new_channel_cb (TpConnection *connection, - const gchar *object_path, - const gchar *channel_type, - guint handle_type, - guint handle, - gboolean suppress_handler, - gpointer user_data, - GObject *object) -{ - EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); - - /* Empathy heavily abuses surpress handler (don't try this at home), if - * surpress handler is true then it is an outgoing channel, which is - * requested either by us or some other party (like the megaphone applet). - * Otherwise it's an incoming channel */ - dispatcher_connection_new_channel (dispatcher, connection, - object_path, channel_type, handle_type, handle, NULL, !suppress_handler); -} - -static void -dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher, - TpConnection *connection, - const gchar *object_path, - GHashTable *properties) +dispatcher_connection_new_channel_with_properties ( + EmpathyDispatcher *dispatcher, + TpConnection *connection, + const gchar *object_path, + GHashTable *properties) { const gchar *channel_type; guint handle_type; @@ -701,7 +715,7 @@ dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher if (!valid) { g_message ("%s had an invalid Requested property", object_path); - return; + requested = FALSE; } dispatcher_connection_new_channel (dispatcher, connection, @@ -709,29 +723,6 @@ dispatcher_connection_new_channel_with_properties (EmpathyDispatcher *dispatcher } static void -dispatcher_connection_new_channels_cb (TpConnection *connection, - const GPtrArray *channels, - gpointer user_data, - GObject *object) -{ - EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); - int i; - - for (i = 0; i < channels->len ; i++) - { - GValueArray *arr = g_ptr_array_index (channels, i); - const gchar *object_path; - GHashTable *properties; - - object_path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); - properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); - - dispatcher_connection_new_channel_with_properties (dispatcher, - connection, object_path, properties); - } -} - -static void dispatcher_connection_got_all (TpProxy *proxy, GHashTable *properties, const GError *error, @@ -740,7 +731,6 @@ dispatcher_connection_got_all (TpProxy *proxy, { EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); - GPtrArray *channels; GPtrArray *requestable_channels; if (error) { @@ -748,15 +738,6 @@ dispatcher_connection_got_all (TpProxy *proxy, return; } - channels = tp_asv_get_boxed (properties, "Channels", - TP_ARRAY_TYPE_CHANNEL_DETAILS_LIST); - - if (channels == NULL) - DEBUG ("No Channels property !?! on connection"); - else - dispatcher_connection_new_channels_cb (TP_CONNECTION (proxy), - channels, NULL, object); - requestable_channels = tp_asv_get_boxed (properties, "RequestableChannelClasses", TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST); @@ -798,38 +779,6 @@ dispatcher_connection_got_all (TpProxy *proxy, } static void -dispatcher_connection_list_channels_cb (TpConnection *connection, - const GPtrArray *channels, - const GError *error, - gpointer user_data, - GObject *dispatcher) -{ - int i; - - if (error) - { - DEBUG ("Error: %s", error->message); - return; - } - - for (i = 0; i < channels->len; i++) - { - GValueArray *values; - - values = g_ptr_array_index (channels, i); - /* We don't have any extra info, so assume already existing channels are - * incoming... */ - dispatcher_connection_new_channel (EMPATHY_DISPATCHER (dispatcher), - connection, - g_value_get_boxed (g_value_array_get_nth (values, 0)), - g_value_get_string (g_value_array_get_nth (values, 1)), - g_value_get_uint (g_value_array_get_nth (values, 2)), - g_value_get_uint (g_value_array_get_nth (values, 3)), - NULL, TRUE); - } -} - -static void dispatcher_connection_advertise_capabilities_cb (TpConnection *connection, const GPtrArray *capabilities, const GError *error, @@ -841,9 +790,8 @@ dispatcher_connection_advertise_capabilities_cb (TpConnection *connection, } static void -dispatcher_new_connection_cb (EmpathyAccountManager *manager, - TpConnection *connection, - EmpathyDispatcher *dispatcher) +dispatcher_init_connection_if_needed (EmpathyDispatcher *dispatcher, + TpConnection *connection) { EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); GPtrArray *capabilities; @@ -863,26 +811,11 @@ dispatcher_new_connection_cb (EmpathyAccountManager *manager, if (tp_proxy_has_interface_by_id (TP_PROXY (connection), TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS)) { - tp_cli_connection_interface_requests_connect_to_new_channels (connection, - dispatcher_connection_new_channels_cb, - NULL, NULL, G_OBJECT (dispatcher), NULL); - tp_cli_dbus_properties_call_get_all (connection, -1, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, dispatcher_connection_got_all, NULL, NULL, G_OBJECT (dispatcher)); } - else - { - tp_cli_connection_connect_to_new_channel (connection, - dispatcher_connection_new_channel_cb, - NULL, NULL, G_OBJECT (dispatcher), NULL); - - tp_cli_connection_call_list_channels (connection, -1, - dispatcher_connection_list_channels_cb, NULL, NULL, - G_OBJECT (dispatcher)); - - } /* Advertise VoIP capabilities */ capabilities = g_ptr_array_sized_new (1); @@ -908,6 +841,14 @@ dispatcher_new_connection_cb (EmpathyAccountManager *manager, } static void +dispatcher_new_connection_cb (EmpathyAccountManager *manager, + TpConnection *connection, + EmpathyDispatcher *dispatcher) +{ + dispatcher_init_connection_if_needed (dispatcher, connection); +} + +static void remove_idle_handlers (gpointer key, gpointer value, gpointer user_data) @@ -924,19 +865,25 @@ dispatcher_constructor (GType type, GObjectConstructParam *construct_params) { GObject *retval; + TpDBusDaemon *dbus; - if (dispatcher == NULL) - { - retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor - (type, n_construct_params, construct_params); + if (dispatcher != NULL) + return g_object_ref (dispatcher); - dispatcher = EMPATHY_DISPATCHER (retval); - g_object_add_weak_pointer (retval, (gpointer) &dispatcher); - } - else - { - retval = g_object_ref (dispatcher); - } + retval = G_OBJECT_CLASS (empathy_dispatcher_parent_class)->constructor + (type, n_construct_params, construct_params); + + dispatcher = EMPATHY_DISPATCHER (retval); + g_object_add_weak_pointer (retval, (gpointer) &dispatcher); + + dbus = tp_dbus_daemon_dup (NULL); + + g_assert (tp_dbus_daemon_request_name (dbus, + DISPATCHER_BUS_NAME, TRUE, NULL)); + dbus_g_connection_register_g_object (tp_get_bus (), + DISPATCHER_OBJECT_PATH, retval); + + DEBUG ("Registering at '%s'", DISPATCHER_OBJECT_PATH); return retval; } @@ -983,20 +930,113 @@ dispatcher_finalize (GObject *object) } g_object_unref (priv->account_manager); - g_object_unref (priv->mc); g_hash_table_destroy (priv->connections); g_hash_table_destroy (priv->outstanding_classes_requests); } static void +dispatcher_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (object); + EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); + + switch (property_id) + { + case PROP_INTERFACES: + g_value_set_boxed (value, empathy_dispatcher_interfaces); + break; + case PROP_CHANNEL_FILTER: + { + GPtrArray *filters = g_ptr_array_new (); + GHashTable *filter = g_hash_table_new (NULL, NULL); + + g_ptr_array_add (filters, filter); + + g_value_set_boxed (value, filters); + break; + } + case PROP_CHANNELS: + { + GPtrArray *accounts; + GList *l; + + accounts = g_ptr_array_new (); + + for (l = priv->channels; l != NULL; l = g_list_next (l)) + { + TpProxy *channel = TP_PROXY (l->data); + + g_ptr_array_add (accounts, + g_strdup (tp_proxy_get_object_path (channel))); + } + + g_value_set_boxed (value, accounts); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void empathy_dispatcher_class_init (EmpathyDispatcherClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + static TpDBusPropertiesMixinPropImpl client_props[] = { + { "Interfaces", "interfaces", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinPropImpl client_handler_props[] = { + { "HandlerChannelFilter", "channel-filter", NULL }, + { "HandledChannels", "channels", NULL }, + { NULL } + }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CLIENT, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_props + }, + { TP_IFACE_CLIENT_HANDLER, + tp_dbus_properties_mixin_getter_gobject_properties, + NULL, + client_handler_props + }, + { NULL } + }; object_class->finalize = dispatcher_finalize; object_class->constructor = dispatcher_constructor; + object_class->get_property = dispatcher_get_property; + + param_spec = g_param_spec_boxed ("interfaces", "interfaces", + "Available D-Bus interfaces", + G_TYPE_STRV, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); + + param_spec = g_param_spec_boxed ("channel-filter", "channel-filter", + "Filter for channels this handles", + TP_ARRAY_TYPE_CHANNEL_CLASS_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_CHANNEL_FILTER, param_spec); + + param_spec = g_param_spec_boxed ("channels", "channels", + "List of channels we're handling", + EMPATHY_ARRAY_TYPE_OBJECT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, + PROP_CHANNELS, param_spec); + signals[OBSERVE] = g_signal_new ("observe", G_TYPE_FROM_CLASS (klass), @@ -1027,8 +1067,12 @@ empathy_dispatcher_class_init (EmpathyDispatcherClass *klass) G_TYPE_NONE, 1, EMPATHY_TYPE_DISPATCH_OPERATION); + g_type_class_add_private (object_class, sizeof (EmpathyDispatcherPriv)); + klass->dbus_props_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (EmpathyDispatcherClass, dbus_props_class)); } static void @@ -1039,7 +1083,6 @@ empathy_dispatcher_init (EmpathyDispatcher *dispatcher) EMPATHY_TYPE_DISPATCHER, EmpathyDispatcherPriv); dispatcher->priv = priv; - priv->mc = empathy_mission_control_dup_singleton (); priv->account_manager = empathy_account_manager_dup_singleton (); g_signal_connect (priv->account_manager, "new-connection", @@ -1753,3 +1796,59 @@ empathy_dispatcher_find_requestable_channel_classes_async g_hash_table_insert (priv->request_channel_class_async_ids, request, GUINT_TO_POINTER (source_id)); } + +static void +empathy_dispatcher_handle_channels (TpSvcClientHandler *self, + const gchar *account_path, + const gchar *connection_path, + const GPtrArray *channels, + const GPtrArray *requests_satisfied, + guint64 timestamp, + GHashTable *handler_info, + DBusGMethodInvocation *context) +{ + EmpathyDispatcher *dispatcher = EMPATHY_DISPATCHER (self); + EmpathyDispatcherPriv *priv = GET_PRIV (dispatcher); + int i; + EmpathyAccount *account; + TpConnection *connection; + + account = empathy_account_manager_ensure_account (priv->account_manager, + account_path); + g_assert (account != NULL); + + connection = empathy_account_get_connection_for_path (account, + connection_path); + if (connection == NULL) + { + GError error = { TP_ERRORS, TP_ERROR_INVALID_ARGUMENT, + "Invalid connection argument" }; + dbus_g_method_return_error (context, &error); + return; + } + + for (i = 0; i < channels->len ; i++) + { + GValueArray *arr = g_ptr_array_index (channels, i); + const gchar *object_path; + GHashTable *properties; + + object_path = g_value_get_boxed (g_value_array_get_nth (arr, 0)); + properties = g_value_get_boxed (g_value_array_get_nth (arr, 1)); + + dispatcher_connection_new_channel_with_properties (dispatcher, + connection, object_path, properties); + } + + tp_svc_client_handler_return_from_handle_channels (context); +} + +static void +empathy_dispatcher_client_handler_iface_init (gpointer g_iface, + gpointer g_iface_data) +{ + TpSvcClientHandlerClass *klass = (TpSvcClientHandlerClass *) g_iface; + + tp_svc_client_handler_implement_handle_channels (klass, + empathy_dispatcher_handle_channels); +} diff --git a/libempathy/empathy-dispatcher.h b/libempathy/empathy-dispatcher.h index d6c83f6c1..41a1430fb 100644 --- a/libempathy/empathy-dispatcher.h +++ b/libempathy/empathy-dispatcher.h @@ -26,6 +26,7 @@ #include <gio/gio.h> #include <telepathy-glib/channel.h> +#include <telepathy-glib/dbus-properties-mixin.h> #include "empathy-contact.h" #include "empathy-dispatch-operation.h" @@ -51,6 +52,7 @@ struct _EmpathyDispatcher struct _EmpathyDispatcherClass { GObjectClass parent_class; + TpDBusPropertiesMixinClass dbus_props_class; }; /* Will be called when the channel is ready for dispatching. The requestor diff --git a/libempathy/empathy-ft-handler.c b/libempathy/empathy-ft-handler.c index d24467b24..b05da94aa 100644 --- a/libempathy/empathy-ft-handler.c +++ b/libempathy/empathy-ft-handler.c @@ -25,6 +25,7 @@ #include <glib/gi18n.h> #include <telepathy-glib/util.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> #include "empathy-ft-handler.h" #include "empathy-tp-contact-factory.h" diff --git a/libempathy/empathy-idle.c b/libempathy/empathy-idle.c index ac0ca72f6..c86b997af 100644 --- a/libempathy/empathy-idle.c +++ b/libempathy/empathy-idle.c @@ -28,8 +28,8 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> -#include <libmissioncontrol/mc-enum-types.h> +#include "empathy-account-manager.h" #include "empathy-idle.h" #include "empathy-utils.h" #include "empathy-connectivity.h" @@ -42,7 +42,6 @@ #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIdle) typedef struct { - MissionControl *mc; DBusGProxy *gs_proxy; EmpathyConnectivity *connectivity; gulong state_change_signal_id; @@ -58,6 +57,8 @@ typedef struct { gboolean is_idle; guint ext_away_timeout; + + EmpathyAccountManager *manager; } EmpathyIdlePriv; typedef enum { @@ -81,9 +82,10 @@ G_DEFINE_TYPE (EmpathyIdle, empathy_idle, G_TYPE_OBJECT); static EmpathyIdle * idle_singleton = NULL; static void -idle_presence_changed_cb (MissionControl *mc, +idle_presence_changed_cb (EmpathyAccountManager *manager, TpConnectionPresenceType state, gchar *status, + gchar *status_message, EmpathyIdle *idle) { EmpathyIdlePriv *priv; @@ -94,14 +96,15 @@ idle_presence_changed_cb (MissionControl *mc, /* Assume our presence is offline if MC reports UNSET */ state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - DEBUG ("Presence changed to '%s' (%d)", status, state); + DEBUG ("Presence changed to '%s' (%d) \"%s\"", status, state, + status_message); g_free (priv->status); priv->state = state; - priv->status = NULL; - if (!EMP_STR_EMPTY (status)) { - priv->status = g_strdup (status); - } + if (EMP_STR_EMPTY (status_message)) + priv->status = NULL; + else + priv->status = g_strdup (status_message); g_object_notify (G_OBJECT (idle), "state"); g_object_notify (G_OBJECT (idle), "status"); @@ -265,7 +268,6 @@ idle_finalize (GObject *object) priv = GET_PRIV (object); g_free (priv->status); - g_object_unref (priv->mc); if (priv->gs_proxy) { g_object_unref (priv->gs_proxy); @@ -407,67 +409,22 @@ empathy_idle_class_init (EmpathyIdleClass *klass) g_type_class_add_private (object_class, sizeof (EmpathyIdlePriv)); } -static TpConnectionPresenceType -empathy_idle_get_actual_presence (EmpathyIdle *idle, GError **error) -{ - McPresence presence; - EmpathyIdlePriv *priv = GET_PRIV (idle); - - presence = mission_control_get_presence_actual (priv->mc, error); - - switch (presence) { - case MC_PRESENCE_OFFLINE: - return TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - case MC_PRESENCE_AVAILABLE: - return TP_CONNECTION_PRESENCE_TYPE_AVAILABLE; - case MC_PRESENCE_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_AWAY; - case MC_PRESENCE_EXTENDED_AWAY: - return TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY; - case MC_PRESENCE_HIDDEN: - return TP_CONNECTION_PRESENCE_TYPE_HIDDEN; - case MC_PRESENCE_DO_NOT_DISTURB: - return TP_CONNECTION_PRESENCE_TYPE_BUSY; - default: - return TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - } -} - static void empathy_idle_init (EmpathyIdle *idle) { - GError *error = NULL; EmpathyIdlePriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (idle, EMPATHY_TYPE_IDLE, EmpathyIdlePriv); idle->priv = priv; priv->is_idle = FALSE; - priv->mc = empathy_mission_control_dup_singleton (); - priv->state = empathy_idle_get_actual_presence (idle, &error); - if (error) { - DEBUG ("Error getting actual presence: %s", error->message); - - /* Fallback to OFFLINE as that's what mission_control_get_presence_actual - does. This also ensure to always display the status icon (there is no - unset presence icon). */ - priv->state = TP_CONNECTION_PRESENCE_TYPE_OFFLINE; - g_clear_error (&error); - } - priv->status = mission_control_get_presence_message_actual (priv->mc, &error); - if (error || EMP_STR_EMPTY (priv->status)) { - g_free (priv->status); - priv->status = NULL; - if (error) { - DEBUG ("Error getting actual presence message: %s", error->message); - g_clear_error (&error); - } - } + priv->manager = empathy_account_manager_dup_singleton (); + priv->state = empathy_account_manager_get_global_presence (priv->manager, + NULL, &priv->status); - dbus_g_proxy_connect_signal (DBUS_G_PROXY (priv->mc), - "PresenceChanged", - G_CALLBACK (idle_presence_changed_cb), - idle, NULL); + + g_signal_connect (priv->manager, "global-presence-changed", + G_CALLBACK (idle_presence_changed_cb), idle); priv->gs_proxy = dbus_g_proxy_new_for_name (tp_get_bus (), "org.gnome.SessionManager", @@ -568,36 +525,31 @@ empathy_idle_set_flash_state (EmpathyIdle *idle, static void empathy_idle_do_set_presence (EmpathyIdle *idle, - TpConnectionPresenceType state, - const gchar *status) + TpConnectionPresenceType status_type, + const gchar *status_message) { - McPresence mc_state = MC_PRESENCE_UNSET; EmpathyIdlePriv *priv = GET_PRIV (idle); + const gchar *statuses[NUM_TP_CONNECTION_PRESENCE_TYPES] = { + NULL, + "offline", + "available", + "away", + "xa", + "hidden", + "busy", + NULL, + NULL, + }; + const gchar *status; - switch (state) { - case TP_CONNECTION_PRESENCE_TYPE_OFFLINE: - mc_state = MC_PRESENCE_OFFLINE; - break; - case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE: - mc_state = MC_PRESENCE_AVAILABLE; - break; - case TP_CONNECTION_PRESENCE_TYPE_AWAY: - mc_state = MC_PRESENCE_AWAY; - break; - case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY: - mc_state = MC_PRESENCE_EXTENDED_AWAY; - break; - case TP_CONNECTION_PRESENCE_TYPE_HIDDEN: - mc_state = MC_PRESENCE_HIDDEN; - break; - case TP_CONNECTION_PRESENCE_TYPE_BUSY: - mc_state = MC_PRESENCE_DO_NOT_DISTURB; - break; - default: - g_assert_not_reached (); - } + g_assert (status_type > 0 && status_type < NUM_TP_CONNECTION_PRESENCE_TYPES); + + status = statuses[status_type]; + + g_return_if_fail (status != NULL); - mission_control_set_presence (priv->mc, mc_state, status, NULL, NULL); + empathy_account_manager_request_global_presence (priv->manager, + status_type, status, status_message); } void diff --git a/libempathy/empathy-idle.h b/libempathy/empathy-idle.h index d0b426e59..47dcfee23 100644 --- a/libempathy/empathy-idle.h +++ b/libempathy/empathy-idle.h @@ -24,7 +24,7 @@ #include <glib.h> -#include <libmissioncontrol/mission-control.h> +#include <telepathy-glib/enums.h> G_BEGIN_DECLS diff --git a/libempathy/empathy-log-manager.c b/libempathy/empathy-log-manager.c index c1e20f487..309b3b60f 100644 --- a/libempathy/empathy-log-manager.c +++ b/libempathy/empathy-log-manager.c @@ -29,6 +29,7 @@ #include <glib/gstdio.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-log-manager.h" #include "empathy-log-store-empathy.h" diff --git a/libempathy/empathy-log-manager.h b/libempathy/empathy-log-manager.h index 6907e2ede..a67f6e8dd 100644 --- a/libempathy/empathy-log-manager.h +++ b/libempathy/empathy-log-manager.h @@ -26,8 +26,6 @@ #include <glib-object.h> -#include <libmissioncontrol/mc-account.h> - #include "empathy-message.h" #include "empathy-dispatcher.h" diff --git a/libempathy/empathy-log-store-empathy.c b/libempathy/empathy-log-store-empathy.c index b814defe7..9963bfc44 100644 --- a/libempathy/empathy-log-store-empathy.c +++ b/libempathy/empathy-log-store-empathy.c @@ -36,6 +36,9 @@ #include <glib/gstdio.h> #define G_DISABLE_DEPRECATED +#include <telepathy-glib/util.h> +#include <telepathy-glib/defs.h> + #include "empathy-log-store.h" #include "empathy-log-store-empathy.h" #include "empathy-log-manager.h" @@ -105,33 +108,48 @@ empathy_log_store_empathy_init (EmpathyLogStoreEmpathy *self) self->priv = priv; - priv->basedir = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), - ".gnome2", PACKAGE_NAME, "logs", NULL); + priv->basedir = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), + PACKAGE_NAME, "logs", NULL); priv->name = g_strdup ("Empathy"); priv->account_manager = empathy_account_manager_dup_singleton (); } static gchar * +log_store_account_to_dirname (EmpathyAccount *account) +{ + const gchar *name; + + name = empathy_account_get_unique_name (account); + if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE)) + name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + return g_strdelimit (g_strdup (name), "/", '_'); +} + + +static gchar * log_store_empathy_get_dir (EmpathyLogStore *self, EmpathyAccount *account, const gchar *chat_id, gboolean chatroom) { - const gchar *account_id; gchar *basedir; + gchar *escaped; EmpathyLogStoreEmpathyPriv *priv; priv = GET_PRIV (self); - account_id = empathy_account_get_unique_name (account); + escaped = log_store_account_to_dirname (account); if (chatroom) - basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, account_id, + basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, escaped, LOG_DIR_CHATROOMS, chat_id, NULL); else basedir = g_build_path (G_DIR_SEPARATOR_S, priv->basedir, - account_id, chat_id, NULL); + escaped, chat_id, NULL); + + g_free (escaped); return basedir; } @@ -371,10 +389,11 @@ log_store_empathy_search_hit_new (EmpathyLogStore *self, { EmpathyLogStoreEmpathyPriv *priv = GET_PRIV (self); EmpathyLogSearchHit *hit; - const gchar *account_name; + gchar *account_name; const gchar *end; gchar **strv; guint len; + GList *accounts, *l; if (!g_str_has_suffix (filename, LOG_FILENAME_SUFFIX)) return NULL; @@ -394,8 +413,25 @@ log_store_empathy_search_hit_new (EmpathyLogStore *self, else account_name = strv[len-3]; - hit->account = empathy_account_manager_lookup (priv->account_manager, - account_name); + accounts = empathy_account_manager_dup_accounts (priv->account_manager); + + for (l = accounts; l != NULL; l = g_list_next (l)) + { + EmpathyAccount *account = EMPATHY_ACCOUNT (l->data); + gchar *name; + + name = log_store_account_to_dirname (account); + if (!tp_strdiff (name, account_name)) + { + g_assert (hit->account == NULL); + hit->account = account; + g_object_ref (account); + } + g_object_unref (account); + g_free (name); + } + g_list_free (accounts); + hit->filename = g_strdup (filename); g_strfreev (strv); @@ -428,9 +464,15 @@ log_store_empathy_get_messages_for_file (EmpathyLogStore *self, /* Get the account from the filename */ hit = log_store_empathy_search_hit_new (self, filename); - account = g_object_ref (hit->account); + + if (hit->account != NULL) + account = g_object_ref (hit->account); + empathy_log_manager_search_hit_free (hit); + if (hit->account == NULL) + return NULL; + /* Create parser. */ ctxt = xmlNewParserCtxt (); @@ -708,8 +750,7 @@ log_store_empathy_get_chats (EmpathyLogStore *self, priv = GET_PRIV (self); - dir = g_build_filename (priv->basedir, - empathy_account_get_unique_name (account), NULL); + dir = log_store_empathy_get_dir (self, account, NULL, FALSE); hits = log_store_empathy_get_chats_for_dir (self, dir, FALSE); diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 9300364d5..69057a878 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -26,6 +26,7 @@ #include <telepathy-glib/channel.h> #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-tp-chat.h" #include "empathy-tp-contact-factory.h" diff --git a/libempathy/empathy-tp-contact-factory.c b/libempathy/empathy-tp-contact-factory.c index f62c7f12f..6b4c20b53 100644 --- a/libempathy/empathy-tp-contact-factory.c +++ b/libempathy/empathy-tp-contact-factory.c @@ -26,6 +26,8 @@ #include <telepathy-glib/util.h> #include <telepathy-glib/gtypes.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> + #if HAVE_GEOCLUE #include <geoclue/geoclue-geocode.h> #endif diff --git a/libempathy/empathy-tp-contact-list.c b/libempathy/empathy-tp-contact-list.c index 71d8efa67..2bf2ec416 100644 --- a/libempathy/empathy-tp-contact-list.c +++ b/libempathy/empathy-tp-contact-list.c @@ -29,6 +29,7 @@ #include <telepathy-glib/connection.h> #include <telepathy-glib/util.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/interfaces.h> #include "empathy-tp-contact-list.h" #include "empathy-tp-contact-factory.h" diff --git a/libempathy/empathy-tp-file.c b/libempathy/empathy-tp-file.c index e60b2999d..c43fa0be7 100644 --- a/libempathy/empathy-tp-file.c +++ b/libempathy/empathy-tp-file.c @@ -40,6 +40,7 @@ #include <telepathy-glib/gtypes.h> #include <telepathy-glib/proxy-subclass.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-tp-file.h" #include "empathy-marshal.h" diff --git a/libempathy/empathy-tp-roomlist.c b/libempathy/empathy-tp-roomlist.c index b3d955ee4..54d232339 100644 --- a/libempathy/empathy-tp-roomlist.c +++ b/libempathy/empathy-tp-roomlist.c @@ -26,6 +26,7 @@ #include <telepathy-glib/channel.h> #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include "empathy-account.h" @@ -517,6 +518,10 @@ empathy_tp_roomlist_stop (EmpathyTpRoomlist *list) EmpathyTpRoomlistPriv *priv = GET_PRIV (list); g_return_if_fail (EMPATHY_IS_TP_ROOMLIST (list)); + + if (priv->channel == NULL) + return; + g_return_if_fail (TP_IS_CHANNEL (priv->channel)); tp_cli_channel_type_room_list_call_stop_listing (priv->channel, -1, diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c index fd54c9a98..db35e94dd 100644 --- a/libempathy/empathy-utils.c +++ b/libempathy/empathy-utils.c @@ -227,36 +227,6 @@ empathy_xml_node_find_child_prop_value (xmlNodePtr node, return found; } -guint -empathy_account_hash (gconstpointer key) -{ - g_return_val_if_fail (EMPATHY_IS_ACCOUNT (key), 0); - - return g_str_hash (empathy_account_get_unique_name (EMPATHY_ACCOUNT (key))); -} - -gboolean -empathy_account_equal (gconstpointer a, - gconstpointer b) -{ - return a == b; -} - -MissionControl * -empathy_mission_control_dup_singleton (void) -{ - static MissionControl *mc = NULL; - - if (!mc) { - mc = mission_control_new (tp_get_bus ()); - g_object_add_weak_pointer (G_OBJECT (mc), (gpointer) &mc); - } else { - g_object_ref (mc); - } - - return mc; -} - const gchar * empathy_presence_get_default_message (TpConnectionPresenceType presence) { @@ -378,3 +348,19 @@ empathy_uint_compare (gconstpointer a, return *(guint *) a - *(guint *) b; } +gchar * +empathy_protocol_icon_name (const gchar *protocol) +{ + return g_strdup_printf ("im-%s", protocol); +} + +GType +empathy_type_dbus_ao (void) +{ + static GType t = 0; + + if (G_UNLIKELY (t == 0)) + t = dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH); + + return t; +} diff --git a/libempathy/empathy-utils.h b/libempathy/empathy-utils.h index 42acbc8e3..c6aebb4f2 100644 --- a/libempathy/empathy-utils.h +++ b/libempathy/empathy-utils.h @@ -32,8 +32,6 @@ #include <libxml/parser.h> #include <libxml/tree.h> -#include <libmissioncontrol/mission-control.h> - #include "empathy-contact.h" #define EMPATHY_GET_PRIV(obj,type) ((type##Priv *) ((type *) obj)->priv) @@ -64,10 +62,6 @@ xmlNodePtr empathy_xml_node_find_child_prop_value (xmlNodePtr node, const gchar *prop_value); /* Others */ -guint empathy_account_hash (gconstpointer key); -gboolean empathy_account_equal (gconstpointer a, - gconstpointer b); -MissionControl *empathy_mission_control_dup_singleton (void); const gchar * empathy_presence_get_default_message (TpConnectionPresenceType presence); const gchar * empathy_presence_to_str (TpConnectionPresenceType presence); TpConnectionPresenceType empathy_presence_from_str (const gchar *str); @@ -80,6 +74,11 @@ gboolean empathy_check_available_state (void); gint empathy_uint_compare (gconstpointer a, gconstpointer b); +gchar *empathy_protocol_icon_name (const gchar *protocol); + +#define EMPATHY_ARRAY_TYPE_OBJECT (empathy_type_dbus_ao ()) +GType empathy_type_dbus_ao (void); + G_END_DECLS #endif /* __EMPATHY_UTILS_H__ */ diff --git a/megaphone/src/megaphone-applet.c b/megaphone/src/megaphone-applet.c index 132e8b74f..c269c7c7d 100644 --- a/megaphone/src/megaphone-applet.c +++ b/megaphone/src/megaphone-applet.c @@ -31,8 +31,6 @@ #include <panel-2.0/panel-applet-gconf.h> #include <gconf/gconf-client.h> -#include <libmissioncontrol/mission-control.h> - #include <libempathy/empathy-tp-contact-factory.h> #include <libempathy/empathy-account-manager.h> #include <libempathy/empathy-dispatcher.h> @@ -199,7 +197,7 @@ megaphone_applet_new_connection_cb (EmpathyAccountManager *manager, { MegaphoneAppletPriv *priv = GET_PRIV (applet); - if (priv->contact || !empathy_account_equal (account, priv->account)) { + if (priv->contact || account != priv->account) { return; } @@ -445,7 +443,7 @@ megaphone_applet_set_contact (MegaphoneApplet *applet, /* Lookup the new contact */ if (str) { strv = g_strsplit (str, "/", 2); - priv->account = empathy_account_manager_lookup (priv->account_manager, + priv->account = empathy_account_manager_get_account (priv->account_manager, strv[0]); priv->id = strv[1]; g_free (strv[0]); @@ -453,6 +451,7 @@ megaphone_applet_set_contact (MegaphoneApplet *applet, } if (priv->account) { + g_object_ref (priv->account); connection = empathy_account_get_connection (priv->account); if (connection) { megaphone_applet_new_connection_cb (priv->account_manager, diff --git a/nothere/src/nothere-applet.c b/nothere/src/nothere-applet.c index 243272e67..8cdde3e97 100644 --- a/nothere/src/nothere-applet.c +++ b/nothere/src/nothere-applet.c @@ -27,7 +27,6 @@ #include <gtk/gtk.h> #include <bonobo/bonobo-ui-component.h> -#include <libmissioncontrol/mission-control.h> #include <libempathy-gtk/empathy-presence-chooser.h> #include <libempathy-gtk/empathy-ui-utils.h> diff --git a/po/POTFILES.in b/po/POTFILES.in index 9d36f245b..b7dcd7828 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -4,6 +4,7 @@ data/empathy.desktop.in.in data/empathy.schemas.in +libempathy/empathy-account.c libempathy/empathy-ft-handler.c libempathy/empathy-tp-contact-list.c libempathy/empathy-tp-file.c @@ -20,7 +21,7 @@ libempathy-gtk/empathy-account-widget-irc.c [type: gettext/glade]libempathy-gtk/empathy-account-widget-irc.ui [type: gettext/glade]libempathy-gtk/empathy-account-widget-jabber.ui [type: gettext/glade]libempathy-gtk/empathy-account-widget-msn.ui -[type: gettext/glade]libempathy-gtk/empathy-account-widget-salut.ui +[type: gettext/glade]libempathy-gtk/empathy-account-widget-local-xmpp.ui [type: gettext/glade]libempathy-gtk/empathy-account-widget-sip.ui [type: gettext/glade]libempathy-gtk/empathy-account-widget-yahoo.ui libempathy-gtk/empathy-avatar-chooser.c @@ -61,6 +62,7 @@ nothere/src/nothere-applet.c src/empathy.c src/empathy-about-dialog.c +src/empathy-account-assistant.c src/empathy-accounts-dialog.c [type: gettext/glade]src/empathy-accounts-dialog.ui src/empathy-call-window.c @@ -73,7 +75,10 @@ src/empathy-event-manager.c src/empathy-ft-manager.c [type: gettext/glade]src/empathy-ft-manager.ui src/empathy-import-dialog.c +src/empathy-import-widget.c [type: gettext/glade]src/empathy-import-dialog.ui +src/empathy-import-widget.c +src/empathy-import-mc4-accounts.c src/empathy-main-window.c [type: gettext/glade]src/empathy-main-window.ui src/empathy-new-chatroom-dialog.c @@ -9,6 +9,7 @@ msgstr "" "PO-Revision-Date: 2007-08-25 20:40+CET\n" "Last-Translator: Senko Rasic <senko.rasic@collabora.co.uk>\n" "MIME-Version: 1.0\n" +"Language-Team: Croatian\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" @@ -535,7 +536,7 @@ msgstr "Soba za razgovor" #, c-format msgid "Conversation" msgid_plural "Conversations (%d)" -msgstr[0] "Razgovor" +msgstr[0] "Razgovor (%d)" msgstr[1] "Razgovora (%d)" msgstr[2] "Razgovora (%d)" diff --git a/python/pyempathy/pyempathy.defs b/python/pyempathy/pyempathy.defs index 488f5b3ac..ee8aab8d0 100644 --- a/python/pyempathy/pyempathy.defs +++ b/python/pyempathy/pyempathy.defs @@ -291,13 +291,10 @@ (return-type "EmpathyAccountManager*") ) -(define-method create +(define-method is_ready (of-object "EmpathyAccountManager") - (c-name "empathy_account_manager_create") - (return-type "EmpathyAccount*") - (parameters - '("McProfile*" "profile") - ) + (c-name "empathy_account_manager_is_ready") + (return-type "gboolean") ) (define-method get_connected_accounts @@ -318,18 +315,18 @@ (return-type "int") ) -(define-method get_account +(define-method get_account_for_connection (of-object "EmpathyAccountManager") - (c-name "empathy_account_manager_get_account") + (c-name "empathy_account_manager_get_account_for_connection") (return-type "EmpathyAccount*") (parameters '("TpConnection*" "connection") ) ) -(define-method lookup +(define-method get_account (of-object "EmpathyAccountManager") - (c-name "empathy_account_manager_lookup") + (c-name "empathy_account_manager_get_account") (return-type "EmpathyAccount*") (parameters '("const-gchar*" "unique_name") @@ -357,6 +354,62 @@ ) ) +(define-method request_global_presence + (of-object "EmpathyAccountManager") + (c-name "empathy_account_manager_request_global_presence") + (return-type "none") + (parameters + '("TpConnectionPresenceType" "type") + '("const-gchar*" "status") + '("const-gchar*" "message") + ) +) + +(define-method get_requested_global_presence + (of-object "EmpathyAccountManager") + (c-name "empathy_account_manager_get_requested_global_presence") + (return-type "TpConnectionPresenceType") + (parameters + '("gchar**" "status") + '("gchar**" "message") + ) +) + +(define-method get_global_presence + (of-object "EmpathyAccountManager") + (c-name "empathy_account_manager_get_global_presence") + (return-type "TpConnectionPresenceType") + (parameters + '("gchar**" "status") + '("gchar**" "message") + ) +) + +(define-method create_account_async + (of-object "EmpathyAccountManager") + (c-name "empathy_account_manager_create_account_async") + (return-type "none") + (parameters + '("const-gchar*" "connection_manager") + '("const-gchar*" "protocol") + '("const-gchar*" "display_name") + '("GHashTable*" "parameters") + '("GHashTable*" "properties") + '("GAsyncReadyCallback" "callback") + '("gpointer" "user_data") + ) +) + +(define-method create_account_finish + (of-object "EmpathyAccountManager") + (c-name "empathy_account_manager_create_account_finish") + (return-type "EmpathyAccount*") + (parameters + '("GAsyncResult*" "result") + '("GError**" "error") + ) +) + ;; From empathy-chatroom.h @@ -2893,28 +2946,6 @@ ) ) -(define-function account_hash - (c-name "empathy_account_hash") - (return-type "guint") - (parameters - '("gconstpointer" "key") - ) -) - -(define-function account_equal - (c-name "empathy_account_equal") - (return-type "gboolean") - (parameters - '("gconstpointer" "a") - '("gconstpointer" "b") - ) -) - -(define-function mission_control_dup_singleton - (c-name "empathy_mission_control_dup_singleton") - (return-type "MissionControl*") -) - (define-function presence_get_default_message (c-name "empathy_presence_get_default_message") (return-type "const-gchar*") @@ -2979,4 +3010,17 @@ ) ) +(define-function protocol_icon_name + (c-name "empathy_protocol_icon_name") + (return-type "gchar*") + (parameters + '("const-gchar*" "protocol") + ) +) + +(define-function type_dbus_ao + (c-name "empathy_type_dbus_ao") + (return-type "GType") +) + diff --git a/python/pyempathygtk/pyempathygtk.defs b/python/pyempathygtk/pyempathygtk.defs index d4601b211..82fe5daca 100644 --- a/python/pyempathygtk/pyempathygtk.defs +++ b/python/pyempathygtk/pyempathygtk.defs @@ -7,6 +7,13 @@ (gtype-id "EMPATHY_TYPE_ACCOUNT_CHOOSER") ) +(define-object AccountWidget + (in-module "Empathy") + (parent "GObject") + (c-name "EmpathyAccountWidget") + (gtype-id "EMPATHY_TYPE_ACCOUNT_WIDGET") +) + (define-object AvatarChooser (in-module "Empathy") (parent "GtkButton") @@ -118,11 +125,11 @@ (gtype-id "EMPATHY_TYPE_PRESENCE_CHOOSER") ) -(define-object ProfileChooser +(define-object ProtocolChooser (in-module "Empathy") (parent "GtkComboBox") - (c-name "EmpathyProfileChooser") - (gtype-id "EMPATHY_TYPE_PROFILE_CHOOSER") + (c-name "EmpathyProtocolChooser") + (gtype-id "EMPATHY_TYPE_PROTOCOL_CHOOSER") ) (define-object SmileyManager @@ -328,103 +335,53 @@ ;; From empathy-account-widget.h -(define-method widget_handle_params - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_handle_params") - (return-type "none") - (parameters - '("GtkBuilder*" "gui") - '("const-gchar*" "first_widget") - ) - (varargs #t) +(define-function account_widget_get_type + (c-name "empathy_account_widget_get_type") + (return-type "GType") ) -(define-method widget_add_forget_button - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_add_forget_button") - (return-type "none") - (parameters - '("GtkBuilder*" "gui") - '("const-gchar*" "button") - '("const-gchar*" "entry") - ) +(define-method get_widget + (of-object "EmpathyAccountWidget") + (c-name "empathy_account_widget_get_widget") + (return-type "GtkWidget*") ) -(define-function account_widget_set_default_focus - (c-name "empathy_account_widget_set_default_focus") - (return-type "none") +(define-function account_widget_new_for_protocol + (c-name "empathy_account_widget_new_for_protocol") + (return-type "EmpathyAccountWidget*") (parameters - '("GtkBuilder*" "gui") - '("const-gchar*" "entry") + '("const-char*" "protocol") + '("EmpathyAccountSettings*" "settings") + '("gboolean" "simple") ) ) -(define-method widget_generic_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_generic_new") - (return-type "GtkWidget*") -) - -(define-method widget_salut_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_salut_new") - (return-type "GtkWidget*") -) - -(define-method widget_msn_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_msn_new") - (return-type "GtkWidget*") -) - -(define-method widget_jabber_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_jabber_new") - (return-type "GtkWidget*") -) - -(define-method widget_icq_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_icq_new") - (return-type "GtkWidget*") -) - -(define-method widget_aim_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_aim_new") - (return-type "GtkWidget*") -) - -(define-method widget_yahoo_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_yahoo_new") - (return-type "GtkWidget*") -) - -(define-method widget_groupwise_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_groupwise_new") - (return-type "GtkWidget*") -) - ;; From empathy-account-widget-irc.h -(define-method widget_irc_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_irc_new") - (return-type "GtkWidget*") +(define-method irc_build + (of-object "EmpathyAccountWidget") + (c-name "empathy_account_widget_irc_build") + (return-type "none") + (parameters + '("const-char*" "filename") + '("GtkWidget**" "table_common_settings") + ) ) ;; From empathy-account-widget-sip.h -(define-method widget_sip_new - (of-object "EmpathyAccount") - (c-name "empathy_account_widget_sip_new") - (return-type "GtkWidget*") +(define-method sip_build + (of-object "EmpathyAccountWidget") + (c-name "empathy_account_widget_sip_build") + (return-type "none") + (parameters + '("const-char*" "filename") + '("GtkWidget**" "table_common_settings") + ) ) @@ -1550,29 +1507,36 @@ -;; From empathy-profile-chooser.h +;; From empathy-protocol-chooser.h -(define-function profile_chooser_get_type - (c-name "empathy_profile_chooser_get_type") +(define-function protocol_chooser_get_type + (c-name "empathy_protocol_chooser_get_type") (return-type "GType") ) -(define-function profile_chooser_new - (c-name "empathy_profile_chooser_new") - (is-constructor-of "EmpathyProfileChooser") +(define-function protocol_chooser_new + (c-name "empathy_protocol_chooser_new") + (is-constructor-of "EmpathyProtocolChooser") (return-type "GtkWidget*") ) (define-method dup_selected - (of-object "EmpathyProfileChooser") - (c-name "empathy_profile_chooser_dup_selected") - (return-type "McProfile*") + (of-object "EmpathyProtocolChooser") + (c-name "empathy_protocol_chooser_dup_selected") + (return-type "TpConnectionManager*") + (parameters + '("TpConnectionManagerProtocol**" "protocol") + ) ) -(define-method n_profiles - (of-object "EmpathyProfileChooser") - (c-name "empathy_profile_chooser_n_profiles") - (return-type "gint") +(define-method set_visible + (of-object "EmpathyProtocolChooser") + (c-name "empathy_protocol_chooser_set_visible") + (return-type "none") + (parameters + '("EmpathyProtocolChooserFilterFunc" "func") + '("gpointer" "user_data") + ) ) @@ -1796,14 +1760,6 @@ ) ) -(define-function icon_name_from_account - (c-name "empathy_icon_name_from_account") - (return-type "const-gchar*") - (parameters - '("EmpathyAccount*" "account") - ) -) - (define-function icon_name_for_presence (c-name "empathy_icon_name_for_presence") (return-type "const-gchar*") diff --git a/python/pyempathygtk/pyempathygtk.override b/python/pyempathygtk/pyempathygtk.override index 3229cbac2..d758afbf8 100644 --- a/python/pyempathygtk/pyempathygtk.override +++ b/python/pyempathygtk/pyempathygtk.override @@ -2,6 +2,7 @@ headers #include <Python.h> #include <pygobject.h> +#include <libempathy/empathy-enum-types.h> #include "empathy-account-chooser.h" #include "empathy-account-widget.h" #include "empathy-account-widget-irc.h" @@ -27,7 +28,7 @@ headers #include "empathy-log-window.h" #include "empathy-new-message-dialog.h" #include "empathy-presence-chooser.h" -#include "empathy-profile-chooser.h" +#include "empathy-protocol-chooser.h" #include "empathy-smiley-manager.h" #include "empathy-spell.h" #include "empathy-theme-boxes.h" diff --git a/python/update-binding.sh b/python/update-binding.sh index 854c33159..3636b6341 100755 --- a/python/update-binding.sh +++ b/python/update-binding.sh @@ -74,7 +74,7 @@ python /usr/share/pygobject/2.0/codegen/h2def.py \ empathy-log-window.h \ empathy-new-message-dialog.h \ empathy-presence-chooser.h \ - empathy-profile-chooser.h \ + empathy-protocol-chooser.h \ empathy-smiley-manager.h \ empathy-spell.h \ empathy-theme-boxes.h \ diff --git a/src/Makefile.am b/src/Makefile.am index 42485b7d1..6896c03f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,7 @@ BUILT_SOURCES= \ empathy_handwritten_source = \ empathy.c \ empathy-about-dialog.c empathy-about-dialog.h \ + empathy-account-assistant.c empathy-account-assistant.h \ empathy-accounts-dialog.c empathy-accounts-dialog.h \ empathy-call-window.c empathy-call-window.h \ empathy-call-window-fullscreen.c empathy-call-window-fullscreen.h \ @@ -38,9 +39,12 @@ empathy_handwritten_source = \ empathy-debug-dialog.c empathy-debug-dialog.h \ empathy-chat-window.c empathy-chat-window.h \ empathy-event-manager.c empathy-event-manager.h \ + empathy-import-mc4-accounts.c empathy-import-mc4-accounts.h \ empathy-ft-manager.c empathy-ft-manager.h \ empathy-import-dialog.c empathy-import-dialog.h \ + empathy-import-widget.c empathy-import-widget.h \ empathy-import-pidgin.c empathy-import-pidgin.h \ + empathy-import-utils.c empathy-import-utils.h \ empathy-main-window.c empathy-main-window.h \ empathy-misc.c empathy-misc.h \ empathy-new-chatroom-dialog.c empathy-new-chatroom-dialog.h \ @@ -51,7 +55,6 @@ empathy_handwritten_source = \ empathy_SOURCES = \ $(empathy_handwritten_source) \ - bacon-message-connection.c bacon-message-connection.h \ ephy-spinner.c ephy-spinner.h nodist_empathy_SOURCES = $(BUILT_SOURCES) diff --git a/src/bacon-message-connection.c b/src/bacon-message-connection.c deleted file mode 100644 index c9fda4aeb..000000000 --- a/src/bacon-message-connection.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net> - * - * 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. - * - * The Totem project hereby grant permission for non-gpl compatible GStreamer - * plugins to be used and distributed together with GStreamer and Totem. This - * permission are above and beyond the permissions granted by the GPL license - * Totem is covered by. - * - * Monday 7th February 2005: Christian Schaller: Add excemption clause. - * See license_change file for details. - * - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <errno.h> - -#include "bacon-message-connection.h" - -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 -#endif - -struct BaconMessageConnection { - /* A server accepts connections */ - gboolean is_server; - - /* The socket path itself */ - char *path; - - /* File descriptor of the socket */ - int fd; - /* Channel to watch */ - GIOChannel *chan; - /* Event id returned by g_io_add_watch() */ - int conn_id; - - /* Connections accepted by this connection */ - GSList *accepted_connections; - - /* callback */ - void (*func) (const char *message, gpointer user_data); - gpointer data; -}; - -static gboolean -test_is_socket (const char *path) -{ - struct stat s; - - if (stat (path, &s) == -1) - return FALSE; - - if (S_ISSOCK (s.st_mode)) - return TRUE; - - return FALSE; -} - -static gboolean -is_owned_by_user_and_socket (const char *path) -{ - struct stat s; - - if (stat (path, &s) == -1) - return FALSE; - - if (s.st_uid != geteuid ()) - return FALSE; - - if ((s.st_mode & S_IFSOCK) != S_IFSOCK) - return FALSE; - - return TRUE; -} - -static gboolean server_cb (GIOChannel *source, - GIOCondition condition, gpointer data); - -static gboolean -setup_connection (BaconMessageConnection *conn) -{ - int fdflags; - - g_return_val_if_fail (conn->chan == NULL, FALSE); - - /* Add CLOEXEC flag on the fd to make sure the socket get closed - * if exec is called. */ - fdflags = fcntl (conn->fd, F_GETFD, 0); - if (fdflags >= 0) { - fdflags |= FD_CLOEXEC; - fcntl (conn->fd, F_SETFD, fdflags); - } - - conn->chan = g_io_channel_unix_new (conn->fd); - if (!conn->chan) { - return FALSE; - } - g_io_channel_set_line_term (conn->chan, "\n", 1); - conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn); - - return TRUE; -} - -static void -accept_new_connection (BaconMessageConnection *server_conn) -{ - BaconMessageConnection *conn; - int alen; - - g_return_if_fail (server_conn->is_server); - - conn = g_new0 (BaconMessageConnection, 1); - conn->is_server = FALSE; - conn->func = server_conn->func; - conn->data = server_conn->data; - - conn->fd = accept (server_conn->fd, NULL, (guint *)&alen); - - server_conn->accepted_connections = - g_slist_prepend (server_conn->accepted_connections, conn); - - setup_connection (conn); -} - -static gboolean -server_cb (GIOChannel *source, GIOCondition condition, gpointer data) -{ - BaconMessageConnection *conn = (BaconMessageConnection *)data; - char *message, *subs, buf; - int cd, rc, offset; - gboolean finished; - - offset = 0; - if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) { - accept_new_connection (conn); - return TRUE; - } - message = g_malloc (1); - cd = conn->fd; - rc = read (cd, &buf, 1); - while (rc > 0 && buf != '\n') - { - message = g_realloc (message, rc + offset + 1); - message[offset] = buf; - offset = offset + rc; - rc = read (cd, &buf, 1); - } - if (rc <= 0) { - g_io_channel_shutdown (conn->chan, FALSE, NULL); - g_io_channel_unref (conn->chan); - conn->chan = NULL; - close (conn->fd); - conn->fd = -1; - g_free (message); - conn->conn_id = 0; - - return FALSE; - } - message[offset] = '\0'; - - subs = message; - finished = FALSE; - - while (finished == FALSE && *subs != '\0') - { - if (conn->func != NULL) - (*conn->func) (subs, conn->data); - - subs += strlen (subs) + 1; - if (subs - message >= offset) - finished = TRUE; - } - - g_free (message); - - return TRUE; -} - -static char * -find_file_with_pattern (const char *dir, const char *pattern) -{ - GDir *filedir; - char *found_filename; - const char *filename; - GPatternSpec *pat; - - filedir = g_dir_open (dir, 0, NULL); - if (filedir == NULL) - return NULL; - - pat = g_pattern_spec_new (pattern); - if (pat == NULL) - { - g_dir_close (filedir); - return NULL; - } - - found_filename = NULL; - - while ((filename = g_dir_read_name (filedir))) - { - if (g_pattern_match_string (pat, filename)) - { - char *tmp = g_build_filename (dir, filename, NULL); - if (is_owned_by_user_and_socket (tmp)) - found_filename = g_strdup (filename); - g_free (tmp); - } - - if (found_filename != NULL) - break; - } - - g_pattern_spec_free (pat); - g_dir_close (filedir); - - return found_filename; -} - -static char * -socket_filename (const char *prefix) -{ - char *pattern, *newfile, *path, *filename; - const char *tmpdir; - - pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ()); - tmpdir = g_get_tmp_dir (); - filename = find_file_with_pattern (tmpdir, pattern); - if (filename == NULL) - { - newfile = g_strdup_printf ("%s.%s.%u", prefix, - g_get_user_name (), g_random_int ()); - path = g_build_filename (tmpdir, newfile, NULL); - g_free (newfile); - } else { - path = g_build_filename (tmpdir, filename, NULL); - g_free (filename); - } - - g_free (pattern); - return path; -} - -static gboolean -try_server (BaconMessageConnection *conn) -{ - struct sockaddr_un uaddr; - - uaddr.sun_family = AF_UNIX; - strncpy (uaddr.sun_path, conn->path, - MIN (strlen(conn->path)+1, UNIX_PATH_MAX)); - conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1) - { - conn->fd = -1; - return FALSE; - } - listen (conn->fd, 5); - - return setup_connection (conn); -} - -static gboolean -try_client (BaconMessageConnection *conn) -{ - struct sockaddr_un uaddr; - - uaddr.sun_family = AF_UNIX; - strncpy (uaddr.sun_path, conn->path, - MIN(strlen(conn->path)+1, UNIX_PATH_MAX)); - conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (connect (conn->fd, (struct sockaddr *) &uaddr, - sizeof (uaddr)) == -1) - { - conn->fd = -1; - return FALSE; - } - - return setup_connection (conn); -} - -BaconMessageConnection * -bacon_message_connection_new (const char *prefix) -{ - BaconMessageConnection *conn; - - g_return_val_if_fail (prefix != NULL, NULL); - - conn = g_new0 (BaconMessageConnection, 1); - conn->path = socket_filename (prefix); - - if (test_is_socket (conn->path) == FALSE) - { - if (!try_server (conn)) - { - bacon_message_connection_free (conn); - return NULL; - } - - conn->is_server = TRUE; - return conn; - } - - if (try_client (conn) == FALSE) - { - unlink (conn->path); - try_server (conn); - if (conn->fd == -1) - { - bacon_message_connection_free (conn); - return NULL; - } - - conn->is_server = TRUE; - return conn; - } - - conn->is_server = FALSE; - return conn; -} - -void -bacon_message_connection_free (BaconMessageConnection *conn) -{ - GSList *child_conn; - - g_return_if_fail (conn != NULL); - /* Only servers can accept other connections */ - g_return_if_fail (conn->is_server != FALSE || - conn->accepted_connections == NULL); - - child_conn = conn->accepted_connections; - while (child_conn != NULL) { - bacon_message_connection_free (child_conn->data); - child_conn = g_slist_next (child_conn); - } - g_slist_free (conn->accepted_connections); - - if (conn->conn_id) { - g_source_remove (conn->conn_id); - conn->conn_id = 0; - } - if (conn->chan) { - g_io_channel_shutdown (conn->chan, FALSE, NULL); - g_io_channel_unref (conn->chan); - } - - if (conn->is_server != FALSE) { - unlink (conn->path); - } - if (conn->fd != -1) { - close (conn->fd); - } - - g_free (conn->path); - g_free (conn); -} - -void -bacon_message_connection_set_callback (BaconMessageConnection *conn, - BaconMessageReceivedFunc func, - gpointer user_data) -{ - g_return_if_fail (conn != NULL); - - conn->func = func; - conn->data = user_data; -} - -void -bacon_message_connection_send (BaconMessageConnection *conn, - const char *message) -{ - g_return_if_fail (conn != NULL); - g_return_if_fail (message != NULL); - - g_io_channel_write_chars (conn->chan, message, strlen (message), - NULL, NULL); - g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL); - g_io_channel_flush (conn->chan, NULL); -} - -gboolean -bacon_message_connection_get_is_server (BaconMessageConnection *conn) -{ - g_return_val_if_fail (conn != NULL, FALSE); - - return conn->is_server; -} - diff --git a/src/bacon-message-connection.h b/src/bacon-message-connection.h deleted file mode 100644 index db4a91262..000000000 --- a/src/bacon-message-connection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net> - * - * 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. - * - * The Totem project hereby grant permission for non-gpl compatible GStreamer - * plugins to be used and distributed together with GStreamer and Totem. This - * permission are above and beyond the permissions granted by the GPL license - * Totem is covered by. - * - * Monday 7th February 2005: Christian Schaller: Add excemption clause. - * See license_change file for details. - * - */ - -#ifndef BACON_MESSAGE_CONNECTION_H -#define BACON_MESSAGE_CONNECTION_H - -#include <glib.h> - -G_BEGIN_DECLS - -typedef void (*BaconMessageReceivedFunc) (const char *message, - gpointer user_data); - -typedef struct BaconMessageConnection BaconMessageConnection; - -BaconMessageConnection *bacon_message_connection_new (const char *prefix); -void bacon_message_connection_free (BaconMessageConnection *conn); -void bacon_message_connection_set_callback (BaconMessageConnection *conn, - BaconMessageReceivedFunc func, - gpointer user_data); -void bacon_message_connection_send (BaconMessageConnection *conn, - const char *message); -gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn); - -G_END_DECLS - -#endif /* BACON_MESSAGE_CONNECTION_H */ diff --git a/src/empathy-account-assistant.c b/src/empathy-account-assistant.c new file mode 100644 index 000000000..d8aa46f1d --- /dev/null +++ b/src/empathy-account-assistant.c @@ -0,0 +1,941 @@ +/* + * Copyright (C) 2009 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: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-account-assistant.c */ + +#include <glib/gi18n.h> +#include <telepathy-glib/util.h> +#include <gdk/gdkkeysyms.h> + +#include "empathy-account-assistant.h" +#include "empathy-import-widget.h" +#include "empathy-import-utils.h" + +#include <libempathy/empathy-account-settings.h> +#include <libempathy/empathy-utils.h> + +#include <libempathy-gtk/empathy-account-widget.h> +#include <libempathy-gtk/empathy-protocol-chooser.h> +#include <libempathy-gtk/empathy-ui-utils.h> + +G_DEFINE_TYPE (EmpathyAccountAssistant, empathy_account_assistant, + GTK_TYPE_ASSISTANT) + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountAssistant) + +typedef enum { + RESPONSE_IMPORT = 1, + RESPONSE_ENTER_ACCOUNT = 2, + RESPONSE_CREATE_ACCOUNT = 3, + RESPONSE_SALUT_ONLY = 4 +} FirstPageResponse; + +typedef enum { + RESPONSE_CREATE_AGAIN = 1, + RESPONSE_CREATE_STOP = 2 +} CreateEnterPageResponse; + +enum { + PAGE_INTRO = 0, + PAGE_IMPORT = 1, + PAGE_ENTER_CREATE = 2, +}; + +enum { + PROP_PARENT = 1 +}; + +typedef struct { + FirstPageResponse first_resp; + CreateEnterPageResponse create_enter_resp; + gboolean enter_create_forward; + + /* enter or create page */ + GtkWidget *enter_or_create_page; + GtkWidget *current_account_widget; + EmpathyAccountWidget *current_widget_object; + GtkWidget *first_label; + GtkWidget *second_label; + GtkWidget *chooser; + GtkWidget *create_again_radio; + EmpathyAccountSettings *settings; + gboolean is_creating; + + /* import page */ + EmpathyImportWidget *iw; + + GtkWindow *parent_window; + + gboolean dispose_run; +} EmpathyAccountAssistantPriv; + +static GtkWidget * account_assistant_build_enter_or_create_page ( + EmpathyAccountAssistant *self); +static void account_assistant_finish_enter_or_create_page ( + EmpathyAccountAssistant *self, + gboolean is_enter); + +static GtkWidget * +account_assistant_build_error_page (EmpathyAccountAssistant *self, + GError *error, gint page_num) +{ + GtkWidget *main_vbox, *w, *hbox; + GString *str; + char *message; + PangoAttrList *list; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + gtk_widget_show (main_vbox); + + hbox = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, + GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + /* translators: this is followed by the "while ..." strings some lines + * down this file. + */ + str = g_string_new (_("There has been an error ")); + + if (page_num == PAGE_IMPORT) + /* translators: this follows the "There has been an error " string */ + str = g_string_append (str, _("while importing the accounts.")); + else if (page_num >= PAGE_ENTER_CREATE && + priv->first_resp == RESPONSE_ENTER_ACCOUNT) + /* translators: this follows the "There has been an error " string */ + str = g_string_append (str, _("while parsing the account details.")); + else if (page_num >= PAGE_ENTER_CREATE && + priv->first_resp == RESPONSE_CREATE_ACCOUNT) + /* translators: this follows the "There has been an error " string */ + str = g_string_append (str, _("while creating the account.")); + + message = g_string_free (str, FALSE); + + w = gtk_label_new (message); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + list = pango_attr_list_new (); + pango_attr_list_insert (list, pango_attr_scale_new (PANGO_SCALE_LARGE)); + pango_attr_list_insert (list, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); + gtk_label_set_attributes (GTK_LABEL (w), list); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_widget_show (w); + + g_free (message); + pango_attr_list_unref (list); + + message = g_markup_printf_escaped + (_("The error message was: <span style=\"italic\">%s</span>"), + error->message); + w = gtk_label_new (message); + gtk_label_set_use_markup (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_widget_show (w); + + w = gtk_label_new (_("You can either go back and try to enter your " + "accounts' details again or quit this wizard and add accounts " + "later from the Edit menu.")); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_widget_show (w); + + return main_vbox; +} + +static void +account_assistant_back_button_clicked_cb (GtkButton *button, + EmpathyAccountAssistant *self) +{ + gint page_num; + + page_num = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), + "page-num")); + gtk_assistant_remove_action_widget (GTK_ASSISTANT (self), + GTK_WIDGET (button)); + gtk_assistant_set_current_page (GTK_ASSISTANT (self), page_num); +} + +static void +account_assistant_present_error_page (EmpathyAccountAssistant *self, + GError *error, gint page_num) +{ + GtkWidget *error_page, *back_button; + gint num; + + error_page = account_assistant_build_error_page (self, error, + page_num); + num = gtk_assistant_append_page (GTK_ASSISTANT (self), error_page); + gtk_assistant_set_page_title (GTK_ASSISTANT (self), error_page, + _("An error occurred")); + gtk_assistant_set_page_type (GTK_ASSISTANT (self), error_page, + GTK_ASSISTANT_PAGE_SUMMARY); + + back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK); + gtk_assistant_add_action_widget (GTK_ASSISTANT (self), back_button); + g_object_set_data (G_OBJECT (back_button), + "page-num", GINT_TO_POINTER (page_num)); + g_signal_connect (back_button, "clicked", + G_CALLBACK (account_assistant_back_button_clicked_cb), self); + gtk_widget_show (back_button); + + gtk_assistant_set_current_page (GTK_ASSISTANT (self), num); +} + +static void +account_assistant_reset_enter_create_page (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *page; + gint idx; + + page = account_assistant_build_enter_or_create_page (self); + idx = gtk_assistant_append_page (GTK_ASSISTANT (self), page); + gtk_assistant_set_page_type (GTK_ASSISTANT (self), page, + GTK_ASSISTANT_PAGE_CONFIRM); + priv->enter_or_create_page = page; + + gtk_assistant_set_current_page (GTK_ASSISTANT (self), idx); + + account_assistant_finish_enter_or_create_page (self, + priv->first_resp == RESPONSE_ENTER_ACCOUNT ? + TRUE : FALSE); +} + +static void +account_assistant_account_enabled_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + EmpathyAccountAssistant *self = user_data; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + empathy_account_set_enabled_finish (EMPATHY_ACCOUNT (source), + result, &error); + + if (error) + { + g_warning ("Error enabling an account: %s", error->message); + g_error_free (error); + } + + if (priv->create_enter_resp == RESPONSE_CREATE_STOP) + g_signal_emit_by_name (self, "close"); + else + account_assistant_reset_enter_create_page (self); +} + +static void +account_assistant_apply_account_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + EmpathyAccountAssistant *self = user_data; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source); + EmpathyAccount *account; + + empathy_account_settings_apply_finish (settings, result, &error); + + priv->is_creating = FALSE; + + if (error != NULL) + { + account_assistant_present_error_page (self, error, + gtk_assistant_get_current_page (GTK_ASSISTANT (self))); + g_error_free (error); + return; + } + + /* enable the newly created account */ + account = empathy_account_settings_get_account (settings); + empathy_account_set_enabled_async (account, TRUE, + account_assistant_account_enabled_cb, self); +} + +static void +account_assistant_apply_account_and_finish (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + if (priv->settings == NULL) + return; + + priv->is_creating = TRUE; + + empathy_account_settings_apply_async (priv->settings, + account_assistant_apply_account_cb, self); +} + +static void +account_assistant_handle_apply_cb (EmpathyAccountWidget *widget_object, + gboolean is_valid, + EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + gtk_assistant_set_page_complete (GTK_ASSISTANT (self), + priv->enter_or_create_page, is_valid); +} + +static void +account_assistant_protocol_changed_cb (GtkComboBox *chooser, + EmpathyAccountAssistant *self) +{ + TpConnectionManager *cm; + TpConnectionManagerProtocol *proto; + EmpathyAccountSettings *settings; + EmpathyAccountAssistantPriv *priv; + char *str; + GtkWidget *account_widget; + EmpathyAccountWidget *widget_object = NULL; + + priv = GET_PRIV (self); + + cm = empathy_protocol_chooser_dup_selected ( + EMPATHY_PROTOCOL_CHOOSER (chooser), &proto); + + if (cm == NULL || proto == NULL) + /* we are not ready yet */ + return; + + /* Create account */ + /* To translator: %s is the protocol name */ + str = g_strdup_printf (_("New %s account"), proto->name); + + settings = empathy_account_settings_new (cm->name, proto->name, str); + + if (priv->first_resp == RESPONSE_CREATE_ACCOUNT) + empathy_account_settings_set_boolean (settings, "register", TRUE); + + widget_object = empathy_account_widget_new_for_protocol (proto->name, + settings, TRUE); + account_widget = empathy_account_widget_get_widget (widget_object); + + if (priv->current_account_widget != NULL) + { + g_signal_handlers_disconnect_by_func (priv->current_widget_object, + account_assistant_handle_apply_cb, self); + gtk_widget_destroy (priv->current_account_widget); + } + + priv->current_account_widget = account_widget; + priv->current_widget_object = widget_object; + + if (priv->settings != NULL) + g_object_unref (priv->settings); + + priv->settings = settings; + + g_signal_connect (priv->current_widget_object, "handle-apply", + G_CALLBACK (account_assistant_handle_apply_cb), self); + + gtk_box_pack_start (GTK_BOX (priv->enter_or_create_page), account_widget, + FALSE, FALSE, 0); + gtk_widget_show (account_widget); + + g_free (str); +} + +static gboolean +account_assistant_chooser_enter_details_filter_func ( + TpConnectionManager *cm, + TpConnectionManagerProtocol *protocol, + gpointer user_data) +{ + if (!tp_strdiff (protocol->name, "local-xmpp") || + !tp_strdiff (protocol->name, "irc")) + return FALSE; + + return TRUE; +} + +static gboolean +account_assistant_chooser_create_account_filter_func ( + TpConnectionManager *cm, + TpConnectionManagerProtocol *protocol, + gpointer user_data) +{ + return tp_connection_manager_protocol_can_register (protocol); +} + +static void +account_assistant_finish_enter_or_create_page (EmpathyAccountAssistant *self, + gboolean is_enter) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + if (is_enter) + { + gtk_label_set_label (GTK_LABEL (priv->first_label), + _("What kind of chat account do you have?")); + /* gtk_label_set_label (GTK_LABEL (priv->second_label), + _("If you have other accounts to set up, you can do " + "that at any time from the Edit menu.")); + */ + gtk_label_set_label (GTK_LABEL (priv->second_label), + _("Do you have any other chat accounts you want to set up?")); + empathy_protocol_chooser_set_visible ( + EMPATHY_PROTOCOL_CHOOSER (priv->chooser), + account_assistant_chooser_enter_details_filter_func, self); + + gtk_assistant_set_page_title (GTK_ASSISTANT (self), + priv->enter_or_create_page, _("Enter your account details")); + } + else + { + gtk_label_set_label (GTK_LABEL (priv->first_label), + _("What kind of chat account do you want to create?")); + /* gtk_label_set_label (GTK_LABEL (priv->second_label), + _("You can register other accounts, or setup " + "an existing one at any time from the Edit menu.")); + */ + gtk_label_set_label (GTK_LABEL (priv->second_label), + _("Do you want to create other chat accounts?")); + empathy_protocol_chooser_set_visible ( + EMPATHY_PROTOCOL_CHOOSER (priv->chooser), + account_assistant_chooser_create_account_filter_func, self); + + gtk_assistant_set_page_title (GTK_ASSISTANT (self), + priv->enter_or_create_page, + _("Enter the details for the new account")); + } + + g_signal_connect (priv->chooser, "changed", + G_CALLBACK (account_assistant_protocol_changed_cb), self); + + /* trigger show the first account widget */ + account_assistant_protocol_changed_cb (GTK_COMBO_BOX (priv->chooser), self); +} + +static gint +account_assistant_page_forward_func (gint current_page, + gpointer user_data) +{ + EmpathyAccountAssistant *self = user_data; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + gint retval; + + retval = current_page; + + if (current_page == PAGE_INTRO) + { + if (priv->first_resp == RESPONSE_ENTER_ACCOUNT || + priv->first_resp == RESPONSE_CREATE_ACCOUNT) + retval = PAGE_ENTER_CREATE; + if (priv->first_resp == RESPONSE_IMPORT) + retval = PAGE_IMPORT; + } + + if (current_page == PAGE_IMPORT || + current_page >= PAGE_ENTER_CREATE) + /* don't forward anymore */ + retval = -1; + + if (current_page >= PAGE_ENTER_CREATE && + priv->create_enter_resp == RESPONSE_CREATE_AGAIN) + { + priv->enter_create_forward = TRUE; + retval = current_page; + } + + return retval; +} + +static void +account_assistant_radio_choice_toggled_cb (GtkToggleButton *button, + EmpathyAccountAssistant *self) +{ + FirstPageResponse response; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *intro_page; + + response = GPOINTER_TO_INT (g_object_get_data + (G_OBJECT (button), "response")); + + priv->first_resp = response; + + intro_page = gtk_assistant_get_nth_page (GTK_ASSISTANT (self), + PAGE_INTRO); + + if (response == RESPONSE_SALUT_ONLY) + gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page, + GTK_ASSISTANT_PAGE_SUMMARY); + else + gtk_assistant_set_page_type (GTK_ASSISTANT (self), intro_page, + GTK_ASSISTANT_PAGE_INTRO); +} + +static GtkWidget * +account_assistant_build_introduction_page (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *main_vbox, *hbox_1, *w, *vbox_1; + GtkWidget *radio = NULL; + GdkPixbuf *pix; + const gchar *str; + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_widget_show (main_vbox); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + + hbox_1 = gtk_hbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox_1, TRUE, TRUE, 0); + gtk_widget_show (hbox_1); + + w = gtk_label_new ( + _("With Empathy you can chat with people " + "online nearby and with friends and colleagues " + "who use Google Talk, AIM, Windows Live " + "and many other chat programs. With a microphone " + "or a webcam you can also have audio or video calls.")); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0.5); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + pix = empathy_pixbuf_from_icon_name_sized ("empathy", 80); + w = gtk_image_new_from_pixbuf (pix); + gtk_box_pack_start (GTK_BOX (hbox_1), w, FALSE, FALSE, 6); + gtk_widget_show (w); + + g_object_unref (pix); + + w = gtk_label_new (_("Do you have an account you've been using " + "with another chat program?")); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, TRUE, TRUE, 0); + gtk_widget_show (w); + + vbox_1 = gtk_vbox_new (TRUE, 0); + gtk_container_add (GTK_CONTAINER (w), vbox_1); + gtk_widget_show (vbox_1); + + if (empathy_import_accounts_to_import ()) + { + hbox_1 = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox_1), hbox_1, TRUE, TRUE, 0); + gtk_widget_show (hbox_1); + + radio = gtk_radio_button_new_with_label (NULL, + _("Yes, import my account details from ")); + gtk_box_pack_start (GTK_BOX (hbox_1), radio, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (radio), "response", + GINT_TO_POINTER (RESPONSE_IMPORT)); + gtk_widget_show (radio); + + w = gtk_combo_box_new_text (); + gtk_combo_box_append_text (GTK_COMBO_BOX (w), "Pidgin"); + gtk_box_pack_start (GTK_BOX (hbox_1), w, TRUE, TRUE, 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (w), 0); + gtk_widget_show (w); + + g_signal_connect (radio, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + priv->first_resp = RESPONSE_IMPORT; + } + else + { + priv->first_resp = RESPONSE_ENTER_ACCOUNT; + } + + str = _("Yes, I'll enter my account details now"); + + if (radio == NULL) + { + radio = gtk_radio_button_new_with_label (NULL, str); + w = radio; + } + else + { + w = gtk_radio_button_new_with_label_from_widget ( + GTK_RADIO_BUTTON (radio), str); + } + + gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_ENTER_ACCOUNT)); + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + + w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), + _("No, I want a new account")); + gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_CREATE_ACCOUNT)); + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + + w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), + _("No, I just want to see people online nearby for now")); + gtk_box_pack_start (GTK_BOX (vbox_1), w, TRUE, TRUE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_SALUT_ONLY)); + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_choice_toggled_cb), self); + + return main_vbox; +} + +static GtkWidget * +account_assistant_build_import_page (EmpathyAccountAssistant *self) +{ + GtkWidget *main_vbox, *w, *import; + EmpathyImportWidget *iw; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + w = gtk_label_new (_("Select the accounts you want to import:")); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); + gtk_widget_show (w); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 6); + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + /* NOTE: this is hardcoded as we support pidgin only */ + iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_PIDGIN); + import = empathy_import_widget_get_widget (iw); + gtk_container_add (GTK_CONTAINER (w), import); + gtk_widget_show (import); + + priv->iw = iw; + + gtk_widget_show (main_vbox); + + return main_vbox; +} + +static void +account_assistant_radio_create_again_clicked_cb (GtkButton *button, + EmpathyAccountAssistant *self) +{ + CreateEnterPageResponse response; + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + + response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), + "response")); + + priv->create_enter_resp = response; + + gtk_assistant_set_page_type (GTK_ASSISTANT (self), + priv->enter_or_create_page, + (response == RESPONSE_CREATE_AGAIN) ? + GTK_ASSISTANT_PAGE_CONTENT : GTK_ASSISTANT_PAGE_CONFIRM); +} + +static GtkWidget * +account_assistant_build_enter_or_create_page (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + GtkWidget *main_vbox, *w, *chooser, *vbox, *hbox, *radio; + + main_vbox = gtk_vbox_new (FALSE, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); + gtk_widget_show (main_vbox); + + w = gtk_label_new (NULL); + gtk_misc_set_alignment (GTK_MISC (w), 0, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + priv->first_label = w; + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + chooser = empathy_protocol_chooser_new (); + gtk_container_add (GTK_CONTAINER (w), chooser); + gtk_widget_show (chooser); + priv->chooser = chooser; + + vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_end (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); + gtk_widget_show (vbox); + + w = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5); + gtk_widget_show (w); + priv->second_label = w; + + w = gtk_alignment_new (0, 0, 0, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (w), 0, 0, 12, 0); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); + gtk_widget_show (w); + + hbox = gtk_hbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (w), hbox); + gtk_widget_show (hbox); + + radio = gtk_radio_button_new_with_label (NULL, _("Yes")); + gtk_box_pack_start (GTK_BOX (hbox), radio, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (radio), "response", + GINT_TO_POINTER (RESPONSE_CREATE_AGAIN)); + gtk_widget_show (radio); + + w = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio), + _("No, that's all for now")); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (w), "response", + GINT_TO_POINTER (RESPONSE_CREATE_STOP)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), TRUE); + priv->create_enter_resp = RESPONSE_CREATE_STOP; + priv->create_again_radio = w; + gtk_widget_show (w); + + g_signal_connect (w, "clicked", + G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self); + g_signal_connect (radio, "clicked", + G_CALLBACK (account_assistant_radio_create_again_clicked_cb), self); + + return main_vbox; +} + +static void +account_assistant_close_cb (GtkAssistant *assistant, + gpointer user_data) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (assistant); + + if (priv->is_creating) + return; + + gtk_widget_destroy (GTK_WIDGET (assistant)); +} + +static void +impl_signal_apply (GtkAssistant *assistant) +{ + EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant); + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + gint current_page; + + current_page = gtk_assistant_get_current_page (assistant); + + if (current_page >= PAGE_ENTER_CREATE) + account_assistant_apply_account_and_finish (self); + + if (current_page == PAGE_IMPORT) + empathy_import_widget_add_selected_accounts (priv->iw); +} + +static void +impl_signal_cancel (GtkAssistant *assistant) +{ + gtk_widget_destroy (GTK_WIDGET (assistant)); +} + +static void +impl_signal_prepare (GtkAssistant *assistant, + GtkWidget *current_page) +{ + EmpathyAccountAssistant *self = EMPATHY_ACCOUNT_ASSISTANT (assistant); + EmpathyAccountAssistantPriv *priv = GET_PRIV (self); + gint current_idx; + + current_idx = gtk_assistant_get_current_page (assistant); + + if (current_idx >= PAGE_ENTER_CREATE) + { + if (!priv->enter_create_forward) + { + account_assistant_finish_enter_or_create_page (self, + priv->first_resp == RESPONSE_ENTER_ACCOUNT ? + TRUE : FALSE); + } + else + { + priv->enter_create_forward = FALSE; + account_assistant_apply_account_and_finish (self); + } + } +} + +static void +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + priv->parent_window = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_constructed (GObject *object) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (object); + + /* set us as transient for the parent window if any */ + if (priv->parent_window) + gtk_window_set_transient_for (GTK_WINDOW (object), + priv->parent_window); + + /* set the dialog hint, so this will be centered over the parent window */ + gtk_window_set_type_hint (GTK_WINDOW (object), GDK_WINDOW_TYPE_HINT_DIALOG); +} + +static void +do_dispose (GObject *obj) +{ + EmpathyAccountAssistantPriv *priv = GET_PRIV (obj); + + if (priv->dispose_run) + return; + + priv->dispose_run = TRUE; + + if (priv->settings != NULL) + { + g_object_unref (priv->settings); + priv->settings = NULL; + } + + if (G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose != NULL) + G_OBJECT_CLASS (empathy_account_assistant_parent_class)->dispose (obj); +} + +static void +empathy_account_assistant_class_init (EmpathyAccountAssistantClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GtkAssistantClass *gtkclass = GTK_ASSISTANT_CLASS (klass); + GParamSpec *param_spec; + + oclass->get_property = do_get_property; + oclass->set_property = do_set_property; + oclass->constructed = do_constructed; + oclass->dispose = do_dispose; + + gtkclass->apply = impl_signal_apply; + gtkclass->prepare = impl_signal_prepare; + gtkclass->cancel = impl_signal_cancel; + + param_spec = g_param_spec_object ("parent-window", + "parent-window", "The parent window", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PARENT, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyAccountAssistantPriv)); +} + +static void +empathy_account_assistant_init (EmpathyAccountAssistant *self) +{ + EmpathyAccountAssistantPriv *priv; + GtkAssistant *assistant = GTK_ASSISTANT (self); + GtkWidget *page; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_ACCOUNT_ASSISTANT, + EmpathyAccountAssistantPriv); + self->priv = priv; + + g_signal_connect (self, "close", + G_CALLBACK (account_assistant_close_cb), NULL); + + gtk_assistant_set_forward_page_func (assistant, + account_assistant_page_forward_func, self, NULL); + + /* first page (introduction) */ + page = account_assistant_build_introduction_page (self); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_title (assistant, page, + _("Welcome to Empathy")); + gtk_assistant_set_page_type (assistant, page, + GTK_ASSISTANT_PAGE_INTRO); + gtk_assistant_set_page_complete (assistant, page, TRUE); + + /* second page (import accounts) */ + page = account_assistant_build_import_page (self); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_title (assistant, page, + _("Import your existing accounts")); + gtk_assistant_set_page_complete (assistant, page, TRUE); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM); + + /* third page (enter account details) */ + page = account_assistant_build_enter_or_create_page (self); + gtk_assistant_append_page (assistant, page); + gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONFIRM); + priv->enter_or_create_page = page; + + gtk_window_set_resizable (GTK_WINDOW (self), FALSE); +} + +GtkWidget * +empathy_account_assistant_new (GtkWindow *window) +{ + return g_object_new (EMPATHY_TYPE_ACCOUNT_ASSISTANT, "parent-window", + window, NULL); +} diff --git a/src/empathy-account-assistant.h b/src/empathy-account-assistant.h new file mode 100644 index 000000000..857460201 --- /dev/null +++ b/src/empathy-account-assistant.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 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: Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-account-assistant.h */ + +#ifndef __EMPATHY_ACCOUNT_ASSISTANT_H__ +#define __EMPATHY_ACCOUNT_ASSISTANT_H__ + +#include <glib-object.h> +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_ACCOUNT_ASSISTANT empathy_account_assistant_get_type() +#define EMPATHY_ACCOUNT_ASSISTANT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ + EmpathyAccountAssistant)) +#define EMPATHY_ACCOUNT_ASSISTANT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ + EmpathyAccountAssistantClass)) +#define EMPATHY_IS_ACCOUNT_ASSISTANT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT)) +#define EMPATHY_IS_ACCOUNT_ASSISTANT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_ACCOUNT_ASSISTANT)) +#define EMPATHY_ACCOUNT_ASSISTANT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNT_ASSISTANT,\ + EmpathyAccountAssistantClass)) + +typedef struct { + GtkAssistant parent; + + /* private */ + gpointer priv; +} EmpathyAccountAssistant; + +typedef struct { + GtkAssistantClass parent_class; +} EmpathyAccountAssistantClass; + +GType empathy_account_assistant_get_type (void); + +GtkWidget *empathy_account_assistant_new (GtkWindow *parent); + +G_END_DECLS + +#endif /* __EMPATHY_ACCOUNT_ASSISTANT_H__ */ diff --git a/src/empathy-accounts-dialog.c b/src/empathy-accounts-dialog.c index 5948a58ff..40f46e49e 100644 --- a/src/empathy-accounts-dialog.c +++ b/src/empathy-accounts-dialog.c @@ -1,7 +1,6 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2005-2007 Imendio AB - * Copyright (C) 2007-2008 Collabora Ltd. + * Copyright (C) 2007-2009 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 @@ -20,6 +19,8 @@ * * Authors: Martyn Russell <martyn@imendio.com> * Xavier Claessens <xclaesse@gmail.com> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + * Jonathan Tellier <jonathan.tellier@gmail.com> */ #include <config.h> @@ -31,20 +32,24 @@ #include <glib/gi18n.h> #include <dbus/dbus-glib.h> -#include <libmissioncontrol/mc-profile.h> #include <telepathy-glib/util.h> #include <libempathy/empathy-utils.h> #include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-connection-managers.h> #include <libempathy-gtk/empathy-ui-utils.h> -#include <libempathy-gtk/empathy-profile-chooser.h> + +#include <libempathy-gtk/empathy-protocol-chooser.h> #include <libempathy-gtk/empathy-account-widget.h> #include <libempathy-gtk/empathy-account-widget-irc.h> #include <libempathy-gtk/empathy-account-widget-sip.h> +#include <libempathy-gtk/empathy-cell-renderer-activatable.h> #include <libempathy-gtk/empathy-conf.h> +#include <libempathy-gtk/empathy-images.h> #include "empathy-accounts-dialog.h" #include "empathy-import-dialog.h" +#include "empathy-import-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT #include <libempathy/empathy-debug.h> @@ -52,1125 +57,1414 @@ /* Flashing delay for icons (milliseconds). */ #define FLASH_TIMEOUT 500 +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyAccountsDialog) +G_DEFINE_TYPE (EmpathyAccountsDialog, empathy_accounts_dialog, G_TYPE_OBJECT); + +static EmpathyAccountsDialog *dialog_singleton = NULL; + typedef struct { - GtkWidget *window; + GtkWidget *window; + + GtkWidget *alignment_settings; + + GtkWidget *vbox_details; + GtkWidget *frame_no_protocol; - GtkWidget *alignment_settings; + GtkWidget *treeview; - GtkWidget *vbox_details; - GtkWidget *frame_no_profile; + GtkWidget *button_add; - GtkWidget *treeview; + GtkWidget *frame_new_account; + GtkWidget *combobox_protocol; + GtkWidget *hbox_type; + GtkWidget *button_create; + GtkWidget *button_back; + GtkWidget *radiobutton_reuse; + GtkWidget *radiobutton_register; - GtkWidget *button_add; - GtkWidget *button_remove; - GtkWidget *button_import; + GtkWidget *image_type; + GtkWidget *label_name; + GtkWidget *label_type; + GtkWidget *settings_widget; - GtkWidget *frame_new_account; - GtkWidget *combobox_profile; - GtkWidget *hbox_type; - GtkWidget *button_create; - GtkWidget *button_back; - GtkWidget *radiobutton_reuse; - GtkWidget *radiobutton_register; + gboolean connecting_show; + guint connecting_id; - GtkWidget *image_type; - GtkWidget *label_name; - GtkWidget *label_type; - GtkWidget *settings_widget; + gulong settings_ready_id; + EmpathyAccountSettings *settings_ready; - gboolean connecting_show; - guint connecting_id; + EmpathyAccountManager *account_manager; + EmpathyConnectionManagers *cms; - EmpathyAccountManager *account_manager; - MissionControl *mc; -} EmpathyAccountsDialog; + GtkWindow *parent_window; + EmpathyAccount *initial_selection; +} EmpathyAccountsDialogPriv; enum { - COL_ENABLED, - COL_NAME, - COL_STATUS, - COL_ACCOUNT_POINTER, - COL_COUNT + COL_NAME, + COL_STATUS, + COL_ACCOUNT_POINTER, + COL_ACCOUNT_SETTINGS_POINTER, + COL_COUNT }; -static void accounts_dialog_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account); -static void accounts_dialog_model_setup (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog); -static void accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - EmpathyAccountsDialog *dialog); -static EmpathyAccount *accounts_dialog_model_get_selected (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, - EmpathyAccount *account); -static gboolean accounts_dialog_model_remove_selected (EmpathyAccountsDialog *dialog); -static void accounts_dialog_model_selection_changed (GtkTreeSelection *selection, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_add_or_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account); -static void accounts_dialog_account_added_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_account_removed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog); -static gboolean accounts_dialog_row_changed_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data); -static gboolean accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog); -static void accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - TpConnectionStatusReason reason, - TpConnectionStatus current, - TpConnectionStatus previous, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_create_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_back_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_add_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_help_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_remove_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_button_import_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyAccountsDialog *dialog); -static void accounts_dialog_destroy_cb (GtkWidget *widget, - EmpathyAccountsDialog *dialog); +enum { + PROP_PARENT = 1 +}; + +static EmpathyAccountSettings * accounts_dialog_model_get_selected_settings ( + EmpathyAccountsDialog *dialog); + +static void accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog); + +static void accounts_dialog_update (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings); + +static void accounts_dialog_update_settings (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings); static void accounts_dialog_update_name_label (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) + const gchar *display_name) { - gchar *text; + gchar *text; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - text = g_markup_printf_escaped ("<big><b>%s</b></big>", - empathy_account_get_display_name (account)); - gtk_label_set_markup (GTK_LABEL (dialog->label_name), text); + text = g_markup_printf_escaped ("<big><b>%s</b></big>", display_name); + gtk_label_set_markup (GTK_LABEL (priv->label_name), text); - g_free (text); + g_free (text); } static void -accounts_dialog_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) +empathy_account_dialog_widget_cancelled_cb (EmpathyAccountWidget *widget_object, + EmpathyAccountsDialog *dialog) { - McProfile *profile; - const gchar *config_ui; - - if (!account) { - GtkTreeView *view; - GtkTreeModel *model; - - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); - - if (gtk_tree_model_iter_n_children (model, NULL) > 0) { - /* We have configured accounts, select the first one */ - accounts_dialog_model_select_first (dialog); - return; - } - if (empathy_profile_chooser_n_profiles ( - EMPATHY_PROFILE_CHOOSER (dialog->combobox_profile)) > 0) { - /* We have no account configured but we have some - * profiles instsalled. The user obviously wants to add - * an account. Click on the Add button for him. */ - accounts_dialog_button_add_clicked_cb (dialog->button_add, - dialog); - return; - } - - /* No account and no profile, warn the user */ - gtk_widget_hide (dialog->vbox_details); - gtk_widget_hide (dialog->frame_new_account); - gtk_widget_show (dialog->frame_no_profile); - gtk_widget_set_sensitive (dialog->button_add, FALSE); - gtk_widget_set_sensitive (dialog->button_remove, FALSE); - return; - } - - /* We have an account selected, destroy old settings and create a new - * one for the account selected */ - gtk_widget_hide (dialog->frame_new_account); - gtk_widget_hide (dialog->frame_no_profile); - gtk_widget_show (dialog->vbox_details); - gtk_widget_set_sensitive (dialog->button_add, TRUE); - gtk_widget_set_sensitive (dialog->button_remove, TRUE); - - if (dialog->settings_widget) { - gtk_widget_destroy (dialog->settings_widget); - dialog->settings_widget = NULL; - } - - profile = empathy_account_get_profile (account); - config_ui = mc_profile_get_configuration_ui (profile); - if (!tp_strdiff (config_ui, "jabber")) { - dialog->settings_widget = - empathy_account_widget_jabber_new (account); - } - else if (!tp_strdiff (config_ui, "msn")) { - dialog ->settings_widget = - empathy_account_widget_msn_new (account); - } - else if (!tp_strdiff (config_ui, "local-xmpp")) { - dialog->settings_widget = - empathy_account_widget_salut_new (account); - } - else if (!tp_strdiff (config_ui, "irc")) { - dialog->settings_widget = - empathy_account_widget_irc_new (account); - } - else if (!tp_strdiff (config_ui, "icq")) { - dialog->settings_widget = - empathy_account_widget_icq_new (account); - } - else if (!tp_strdiff (config_ui, "aim")) { - dialog->settings_widget = - empathy_account_widget_aim_new (account); - } - else if (!tp_strdiff (config_ui, "yahoo")) { - dialog->settings_widget = - empathy_account_widget_yahoo_new (account); - } - else if (!tp_strdiff (config_ui, "sofiasip")) { - dialog->settings_widget = - empathy_account_widget_sip_new (account); - } - else if (!tp_strdiff (config_ui, "groupwise")) { - dialog->settings_widget = - empathy_account_widget_groupwise_new (account); - } - else { - dialog->settings_widget = - empathy_account_widget_generic_new (account); - } - - gtk_container_add (GTK_CONTAINER (dialog->alignment_settings), - dialog->settings_widget); - gtk_widget_show (dialog->settings_widget); - - - gtk_image_set_from_icon_name (GTK_IMAGE (dialog->image_type), - mc_profile_get_icon_name (profile), - GTK_ICON_SIZE_DIALOG); - gtk_widget_set_tooltip_text (dialog->image_type, - mc_profile_get_display_name (profile)); - - accounts_dialog_update_name_label (dialog, account); - - g_object_unref (profile); + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountSettings *settings; + EmpathyAccount *account; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + view = GTK_TREE_VIEW (priv->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_ACCOUNT_SETTINGS_POINTER, &settings, + COL_ACCOUNT_POINTER, &account, -1); + + empathy_account_settings_discard_changes (settings); + + if (account == NULL) + { + /* We were creating an account. We remove the selected row */ + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + } + else + { + /* We were modifying an account. We discard the changes by reloading the + * settings and the UI. */ + accounts_dialog_update_settings (dialog, settings); + g_object_unref (account); + } + + if (settings != NULL) + g_object_unref (settings); } static void -accounts_dialog_model_setup (EmpathyAccountsDialog *dialog) +empathy_account_dialog_account_created_cb (EmpathyAccountWidget *widget_object, + EmpathyAccountsDialog *dialog) { - GtkListStore *store; - GtkTreeSelection *selection; + EmpathyAccountSettings *settings = + accounts_dialog_model_get_selected_settings (dialog); + accounts_dialog_update_settings (dialog, settings); - store = gtk_list_store_new (COL_COUNT, - G_TYPE_BOOLEAN, /* enabled */ - G_TYPE_STRING, /* name */ - G_TYPE_UINT, /* status */ - EMPATHY_TYPE_ACCOUNT); /* account */ + if (settings) + g_object_unref (settings); +} - gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview), - GTK_TREE_MODEL (store)); +static GtkWidget * +get_account_setup_widget (EmpathyAccountSettings *settings, + EmpathyAccountWidget **widget_object) +{ + const gchar *proto = empathy_account_settings_get_protocol (settings); + EmpathyConnectionManagers *cm = + empathy_connection_managers_dup_singleton (); + GList *cms = empathy_connection_managers_get_cms (cm); + GList *l; + + for (l = cms; l; l = l->next) + { + TpConnectionManager *tp_cm = l->data; + if (tp_connection_manager_has_protocol (tp_cm, proto)) + { + g_object_unref (cm); + *widget_object = empathy_account_widget_new_for_protocol (proto, + settings, FALSE); + return empathy_account_widget_get_widget (*widget_object); + } + } + + g_object_unref (cm); + *widget_object = empathy_account_widget_new_for_protocol ("generic", settings, + FALSE); + return empathy_account_widget_get_widget (*widget_object); +} + +static void +account_dialog_create_settings_widget (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + EmpathyAccountWidget *widget_object = NULL; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + gchar *icon_name; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->treeview)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + priv->settings_widget = get_account_setup_widget (settings, &widget_object); + g_signal_connect (widget_object, "account-created", + G_CALLBACK (empathy_account_dialog_account_created_cb), dialog); + g_signal_connect (widget_object, "cancelled", + G_CALLBACK (empathy_account_dialog_widget_cancelled_cb), dialog); - g_signal_connect (selection, "changed", - G_CALLBACK (accounts_dialog_model_selection_changed), - dialog); + gtk_container_add (GTK_CONTAINER (priv->alignment_settings), + priv->settings_widget); + gtk_widget_show (priv->settings_widget); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), - COL_NAME, GTK_SORT_ASCENDING); + icon_name = empathy_account_settings_get_icon_name (settings); - accounts_dialog_model_add_columns (dialog); + gtk_image_set_from_icon_name (GTK_IMAGE (priv->image_type), + icon_name, GTK_ICON_SIZE_DIALOG); + gtk_widget_set_tooltip_text (priv->image_type, + empathy_account_settings_get_protocol (settings)); - g_object_unref (store); + accounts_dialog_update_name_label (dialog, + empathy_account_settings_get_display_name (settings)); } static void -accounts_dialog_name_edited_cb (GtkCellRendererText *renderer, - gchar *path, - gchar *new_text, - EmpathyAccountsDialog *dialog) +account_dialog_settings_ready_cb (EmpathyAccountSettings *settings, + GParamSpec *spec, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - GtkTreeModel *model; - GtkTreePath *treepath; - GtkTreeIter iter; - - if (empathy_account_manager_get_connecting_accounts (dialog->account_manager) > 0) { - dialog->connecting_id = g_timeout_add (FLASH_TIMEOUT, - (GSourceFunc) accounts_dialog_flash_connecting_cb, - dialog); - } - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - treepath = gtk_tree_path_new_from_string (path); - gtk_tree_model_get_iter (model, &iter, treepath); - gtk_tree_model_get (model, &iter, - COL_ACCOUNT_POINTER, &account, - -1); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_NAME, new_text, - -1); - gtk_tree_path_free (treepath); - - empathy_account_set_display_name (account, new_text); - g_object_unref (account); + if (empathy_account_settings_is_ready (settings)) + account_dialog_create_settings_widget (dialog, settings); } static void -accounts_dialog_enable_toggled_cb (GtkCellRendererToggle *cell_renderer, - gchar *path, - EmpathyAccountsDialog *dialog) +accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - GtkTreeModel *model; - GtkTreePath *treepath; - GtkTreeIter iter; - gboolean enabled; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - treepath = gtk_tree_path_new_from_string (path); - gtk_tree_model_get_iter (model, &iter, treepath); - gtk_tree_model_get (model, &iter, - COL_ACCOUNT_POINTER, &account, - -1); - gtk_tree_path_free (treepath); - - enabled = empathy_account_is_enabled (account); - empathy_account_set_enabled (account, !enabled); - - DEBUG ("%s account %s", enabled ? "Disabled" : "Enable", - empathy_account_get_display_name (account)); - - g_object_unref (account); + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* select first */ + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); + + if (gtk_tree_model_get_iter_first (model, &iter)) + { + selection = gtk_tree_view_get_selection (view); + gtk_tree_selection_select_iter (selection, &iter); + } + else + { + accounts_dialog_update_settings (dialog, NULL); + } } static void -accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer, - GtkCellEditable *editable, - gchar *path, - EmpathyAccountsDialog *dialog) +accounts_dialog_protocol_changed_cb (GtkWidget *widget, + EmpathyAccountsDialog *dialog) { - if (dialog->connecting_id) { - g_source_remove (dialog->connecting_id); - } - DEBUG ("Editing account name started; stopping flashing"); + TpConnectionManager *cm; + TpConnectionManagerProtocol *proto; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + cm = empathy_protocol_chooser_dup_selected ( + EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto); + + if (tp_connection_manager_protocol_can_register (proto)) + { + gtk_widget_show (priv->radiobutton_register); + gtk_widget_show (priv->radiobutton_reuse); + } + else + { + gtk_widget_hide (priv->radiobutton_register); + gtk_widget_hide (priv->radiobutton_reuse); + } + g_object_unref (cm); } static void -accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog) +accounts_dialog_button_add_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeViewColumn *column; - GtkCellRenderer *cell; - - view = GTK_TREE_VIEW (dialog->treeview); - gtk_tree_view_set_headers_visible (view, TRUE); - - /* Enabled column */ - cell = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (view, -1, - _("Enabled"), - cell, - "active", COL_ENABLED, - NULL); - g_signal_connect (cell, "toggled", - G_CALLBACK (accounts_dialog_enable_toggled_cb), - dialog); - - /* Account column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Accounts")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - /* Icon renderer */ - cell = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, cell, FALSE); - gtk_tree_view_column_set_cell_data_func (column, cell, - (GtkTreeCellDataFunc) - accounts_dialog_model_pixbuf_data_func, - dialog, - NULL); - - /* Name renderer */ - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "ellipsize", PANGO_ELLIPSIZE_END, - "width-chars", 25, - "editable", TRUE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); - g_signal_connect (cell, "edited", - G_CALLBACK (accounts_dialog_name_edited_cb), - dialog); - g_signal_connect (cell, "editing-started", - G_CALLBACK (accounts_dialog_name_editing_started_cb), - dialog); + GtkTreeView *view; + GtkTreeModel *model; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); + + gtk_widget_set_sensitive (priv->button_add, FALSE); + gtk_widget_hide (priv->vbox_details); + gtk_widget_hide (priv->frame_no_protocol); + gtk_widget_show (priv->frame_new_account); + + /* If we have no account, no need of a back button */ + if (gtk_tree_model_iter_n_children (model, NULL) > 0) + gtk_widget_show (priv->button_back); + else + gtk_widget_hide (priv->button_back); + + accounts_dialog_protocol_changed_cb (priv->radiobutton_register, dialog); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->radiobutton_reuse), + TRUE); + gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox_protocol), 0); + gtk_widget_grab_focus (priv->combobox_protocol); } static void -accounts_dialog_model_select_first (EmpathyAccountsDialog *dialog) +accounts_dialog_update_settings (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; - - /* select first */ - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); - - if (gtk_tree_model_get_iter_first (model, &iter)) { - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_select_iter (selection, &iter); - } else { - accounts_dialog_update_account (dialog, NULL); - } + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (priv->settings_ready != NULL) + { + g_signal_handler_disconnect (priv->settings_ready, + priv->settings_ready_id); + priv->settings_ready = NULL; + priv->settings_ready_id = 0; + } + + if (!settings) + { + GtkTreeView *view; + GtkTreeModel *model; + + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); + + if (gtk_tree_model_iter_n_children (model, NULL) > 0) + { + /* We have configured accounts, select the first one */ + accounts_dialog_model_select_first (dialog); + return; + } + if (empathy_connection_managers_get_cms_num (priv->cms) > 0) + { + /* We have no account configured but we have some + * profiles installed. The user obviously wants to add + * an account. Click on the Add button for him. */ + accounts_dialog_button_add_clicked_cb (priv->button_add, + dialog); + return; + } + + /* No account and no profile, warn the user */ + gtk_widget_hide (priv->vbox_details); + gtk_widget_hide (priv->frame_new_account); + gtk_widget_show (priv->frame_no_protocol); + gtk_widget_set_sensitive (priv->button_add, FALSE); + return; + } + + /* We have an account selected, destroy old settings and create a new + * one for the account selected */ + gtk_widget_hide (priv->frame_new_account); + gtk_widget_hide (priv->frame_no_protocol); + gtk_widget_show (priv->vbox_details); + gtk_widget_set_sensitive (priv->button_add, TRUE); + + if (priv->settings_widget) + { + gtk_widget_destroy (priv->settings_widget); + priv->settings_widget = NULL; + } + + if (empathy_account_settings_is_ready (settings)) + { + account_dialog_create_settings_widget (dialog, settings); + } + else + { + priv->settings_ready = settings; + priv->settings_ready_id = + g_signal_connect (settings, "notify::ready", + G_CALLBACK (account_dialog_settings_ready_cb), dialog); + } + } static void -accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column, - GtkCellRenderer *cell, - GtkTreeModel *model, - GtkTreeIter *iter, - EmpathyAccountsDialog *dialog) +accounts_dialog_name_editing_started_cb (GtkCellRenderer *renderer, + GtkCellEditable *editable, + gchar *path, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - const gchar *icon_name; - GdkPixbuf *pixbuf; - TpConnectionStatus status; - - gtk_tree_model_get (model, iter, - COL_STATUS, &status, - COL_ACCOUNT_POINTER, &account, - -1); - - icon_name = empathy_icon_name_from_account (account); - pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); - - if (pixbuf) { - if (status == TP_CONNECTION_STATUS_DISCONNECTED || - (status == TP_CONNECTION_STATUS_CONNECTING && - !dialog->connecting_show)) { - GdkPixbuf *modded_pixbuf; - - modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - TRUE, - 8, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - - gdk_pixbuf_saturate_and_pixelate (pixbuf, - modded_pixbuf, - 1.0, - TRUE); - g_object_unref (pixbuf); - pixbuf = modded_pixbuf; - } - } - - g_object_set (cell, - "visible", TRUE, - "pixbuf", pixbuf, - NULL); - - g_object_unref (account); - if (pixbuf) { - g_object_unref (pixbuf); - } + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (priv->connecting_id) + g_source_remove (priv->connecting_id); + + DEBUG ("Editing account name started; stopping flashing"); +} + +static void +accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccountSettings *settings; + gchar *icon_name; + GdkPixbuf *pixbuf; + TpConnectionStatus status; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + gtk_tree_model_get (model, iter, + COL_STATUS, &status, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); + + icon_name = empathy_account_settings_get_icon_name (settings); + pixbuf = empathy_pixbuf_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); + + if (pixbuf) + { + if (status == TP_CONNECTION_STATUS_DISCONNECTED || + (status == TP_CONNECTION_STATUS_CONNECTING && + !priv->connecting_show)) + { + GdkPixbuf *modded_pixbuf; + + modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + TRUE, + 8, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf)); + + gdk_pixbuf_saturate_and_pixelate (pixbuf, + modded_pixbuf, + 1.0, + TRUE); + g_object_unref (pixbuf); + pixbuf = modded_pixbuf; + } + } + + g_object_set (cell, + "visible", TRUE, + "pixbuf", pixbuf, + NULL); + + g_object_unref (settings); + + if (pixbuf) + g_object_unref (pixbuf); } static gboolean -accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog, - EmpathyAccount *account, - GtkTreeIter *iter) +accounts_dialog_row_changed_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) { - GtkTreeView *view; - GtkTreeSelection *selection; - GtkTreeModel *model; - gboolean ok; - - /* Update the status in the model */ - view = GTK_TREE_VIEW (dialog->treeview); - selection = gtk_tree_view_get_selection (view); - model = gtk_tree_view_get_model (view); - - for (ok = gtk_tree_model_get_iter_first (model, iter); - ok; - ok = gtk_tree_model_iter_next (model, iter)) { - EmpathyAccount *this_account; - gboolean equal; - - gtk_tree_model_get (model, iter, - COL_ACCOUNT_POINTER, &this_account, - -1); - - equal = empathy_account_equal (this_account, account); - g_object_unref (this_account); - - if (equal) { - return TRUE; - } - } - - return FALSE; + gtk_tree_model_row_changed (model, path, iter); + + return FALSE; } -static EmpathyAccount * -accounts_dialog_model_get_selected (EmpathyAccountsDialog *dialog) +static gboolean +accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; - EmpathyAccount *account; + GtkTreeView *view; + GtkTreeModel *model; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - view = GTK_TREE_VIEW (dialog->treeview); - selection = gtk_tree_view_get_selection (view); + priv->connecting_show = !priv->connecting_show; - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) { - return NULL; - } + view = GTK_TREE_VIEW (priv->treeview); + model = gtk_tree_view_get_model (view); - gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL); - return account; + return TRUE; } static void -accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) +accounts_dialog_name_edited_cb (GtkCellRendererText *renderer, + gchar *path, + gchar *new_text, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccountSettings *settings; + GtkTreeModel *model; + GtkTreePath *treepath; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (empathy_account_manager_get_connecting_accounts + (priv->account_manager) > 0) + { + priv->connecting_id = g_timeout_add (FLASH_TIMEOUT, + (GSourceFunc) accounts_dialog_flash_connecting_cb, + dialog); + } + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + treepath = gtk_tree_path_new_from_string (path); + gtk_tree_model_get_iter (model, &iter, treepath); + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, new_text, + -1); + gtk_tree_path_free (treepath); + + empathy_account_settings_set_display_name_async (settings, new_text, + NULL, NULL); + g_object_set (settings, "display-name-overridden", TRUE, NULL); + g_object_unref (settings); +} + +static void +accounts_dialog_delete_account_response_cb (GtkDialog *message_dialog, + gint response_id, + gpointer user_data) { - GtkTreeSelection *selection; - GtkTreeIter iter; + EmpathyAccount *account; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreeSelection *selection; + EmpathyAccountsDialog *account_dialog = EMPATHY_ACCOUNTS_DIALOG (user_data); + EmpathyAccountsDialogPriv *priv = GET_PRIV (account_dialog); + + if (response_id == GTK_RESPONSE_YES) + { + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->treeview)); - if (accounts_dialog_get_account_iter (dialog, account, &iter)) { - gtk_tree_selection_select_iter (selection, &iter); - } + gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + + if (account != NULL) + { + empathy_account_remove_async (account, NULL, NULL); + g_object_unref (account); + } + + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + accounts_dialog_model_select_first (account_dialog); + } + + gtk_widget_destroy (GTK_WIDGET (message_dialog)); } -static gboolean -accounts_dialog_model_remove_selected (EmpathyAccountsDialog *dialog) +static void +accounts_dialog_view_delete_activated_cb (EmpathyCellRendererActivatable *cell, + const gchar *path_string, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccount *account; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *message_dialog; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + if (!gtk_tree_model_get_iter_from_string (model, &iter, path_string)) + return; + + gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1); + + if (account == NULL || !empathy_account_is_valid (account)) + { + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + accounts_dialog_model_select_first (dialog); + return; + } + + message_dialog = gtk_message_dialog_new + (GTK_WINDOW (priv->window), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + _("You are about to remove your %s account!\n" + "Are you sure you want to proceed?"), + empathy_account_get_display_name (account)); + + gtk_message_dialog_format_secondary_text + (GTK_MESSAGE_DIALOG (message_dialog), + _("Any associated conversations and chat rooms will NOT be " + "removed if you decide to proceed.\n" + "\n" + "Should you decide to add the account back at a later time, " + "they will still be available.")); + + gtk_dialog_add_button (GTK_DIALOG (message_dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_NO); + gtk_dialog_add_button (GTK_DIALOG (message_dialog), + GTK_STOCK_REMOVE, + GTK_RESPONSE_YES); + + g_signal_connect (message_dialog, "response", + G_CALLBACK (accounts_dialog_delete_account_response_cb), dialog); + + gtk_widget_show (message_dialog); + + if (account != NULL) + g_object_unref (account); +} + +static void +accounts_dialog_model_add_columns (EmpathyAccountsDialog *dialog) +{ + GtkTreeView *view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + view = GTK_TREE_VIEW (priv->treeview); + gtk_tree_view_set_headers_visible (view, FALSE); + + /* Account column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + /* Icon renderer */ + cell = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + gtk_tree_view_column_set_cell_data_func (column, cell, + (GtkTreeCellDataFunc) + accounts_dialog_model_pixbuf_data_func, + dialog, + NULL); + + /* Name renderer */ + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, + "ellipsize", PANGO_ELLIPSIZE_END, + "width-chars", 25, + "editable", TRUE, + NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); + g_signal_connect (cell, "edited", + G_CALLBACK (accounts_dialog_name_edited_cb), + dialog); + g_signal_connect (cell, "editing-started", + G_CALLBACK (accounts_dialog_name_editing_started_cb), + dialog); + + /* Delete column */ + cell = empathy_cell_renderer_activatable_new (); + gtk_tree_view_column_pack_start (column, cell, FALSE); + g_object_set (cell, + "icon-name", GTK_STOCK_DELETE, + NULL); + + g_signal_connect (cell, "path-activated", + G_CALLBACK (accounts_dialog_view_delete_activated_cb), + dialog); +} + +static EmpathyAccountSettings * +accounts_dialog_model_get_selected_settings (EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; + GtkTreeView *view; + GtkTreeModel *model; + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountSettings *settings; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - view = GTK_TREE_VIEW (dialog->treeview); - selection = gtk_tree_view_get_selection (view); + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) { - return FALSE; - } + if (!gtk_tree_selection_get_selected (selection, &model, &iter)) + return NULL; - return gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, -1); + + return settings; } static void -accounts_dialog_model_selection_changed (GtkTreeSelection *selection, - EmpathyAccountsDialog *dialog) +accounts_dialog_model_selection_changed (GtkTreeSelection *selection, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean is_selection; + EmpathyAccountSettings *settings; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean is_selection; + + is_selection = gtk_tree_selection_get_selected (selection, &model, &iter); + + settings = accounts_dialog_model_get_selected_settings (dialog); - is_selection = gtk_tree_selection_get_selected (selection, &model, &iter); + if (settings != NULL) + empathy_account_settings_discard_changes (settings); - account = accounts_dialog_model_get_selected (dialog); - accounts_dialog_update_account (dialog, account); + accounts_dialog_update_settings (dialog, settings); - if (account) { - g_object_unref (account); - } + if (settings != NULL) + g_object_unref (settings); } static void -accounts_dialog_add_or_update_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account) +accounts_dialog_model_setup (EmpathyAccountsDialog *dialog) { - GtkTreeModel *model; - GtkTreeIter iter; - TpConnectionStatus status; - const gchar *name; - gboolean enabled; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - g_object_get (account, "status", &status, NULL); - name = empathy_account_get_display_name (account); - enabled = empathy_account_is_enabled (account); - - if (!accounts_dialog_get_account_iter (dialog, account, &iter)) { - DEBUG ("Adding new account"); - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - } - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_ENABLED, enabled, - COL_NAME, name, - COL_STATUS, status, - COL_ACCOUNT_POINTER, account, - -1); - - accounts_dialog_connection_changed_cb (dialog->account_manager, - account, - TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, - status, - TP_CONNECTION_STATUS_DISCONNECTED, - dialog); + GtkListStore *store; + GtkTreeSelection *selection; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + store = gtk_list_store_new (COL_COUNT, + G_TYPE_STRING, /* name */ + G_TYPE_UINT, /* status */ + EMPATHY_TYPE_ACCOUNT, /* account */ + EMPATHY_TYPE_ACCOUNT_SETTINGS); /* settings */ + + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), + GTK_TREE_MODEL (store)); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + g_signal_connect (selection, "changed", + G_CALLBACK (accounts_dialog_model_selection_changed), + dialog); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), + COL_NAME, GTK_SORT_ASCENDING); + + accounts_dialog_model_add_columns (dialog); + + g_object_unref (store); +} + +static gboolean +accounts_dialog_get_settings_iter (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings, + GtkTreeIter *iter) +{ + GtkTreeView *view; + GtkTreeSelection *selection; + GtkTreeModel *model; + gboolean ok; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); + model = gtk_tree_view_get_model (view); + + for (ok = gtk_tree_model_get_iter_first (model, iter); + ok; + ok = gtk_tree_model_iter_next (model, iter)) + { + EmpathyAccountSettings *this_settings; + gboolean equal; + + gtk_tree_model_get (model, iter, + COL_ACCOUNT_SETTINGS_POINTER, &this_settings, + -1); + + equal = (this_settings == settings); + g_object_unref (this_settings); + + if (equal) + return TRUE; + } + + return FALSE; +} + +static gboolean +accounts_dialog_get_account_iter (EmpathyAccountsDialog *dialog, + EmpathyAccount *account, + GtkTreeIter *iter) +{ + GtkTreeView *view; + GtkTreeSelection *selection; + GtkTreeModel *model; + gboolean ok; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + view = GTK_TREE_VIEW (priv->treeview); + selection = gtk_tree_view_get_selection (view); + model = gtk_tree_view_get_model (view); + + for (ok = gtk_tree_model_get_iter_first (model, iter); + ok; + ok = gtk_tree_model_iter_next (model, iter)) + { + EmpathyAccountSettings *settings; + gboolean equal; + + gtk_tree_model_get (model, iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); + + equal = empathy_account_settings_has_account (settings, account); + g_object_unref (settings); + + if (equal) + return TRUE; + } + + return FALSE; +} + +static void +accounts_dialog_model_set_selected (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + if (accounts_dialog_get_settings_iter (dialog, settings, &iter)) + gtk_tree_selection_select_iter (selection, &iter); +} +static void +accounts_dialog_add (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + GtkTreeModel *model; + GtkTreeIter iter; + const gchar *name; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + name = empathy_account_settings_get_display_name (settings); + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, name, + COL_STATUS, TP_CONNECTION_STATUS_DISCONNECTED, + COL_ACCOUNT_SETTINGS_POINTER, settings, + -1); +} + +static void +accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + TpConnectionStatusReason reason, + TpConnectionStatus current, + TpConnectionStatus previous, + EmpathyAccountsDialog *dialog) +{ + GtkTreeModel *model; + GtkTreeIter iter; + gboolean found; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + if (accounts_dialog_get_account_iter (dialog, account, &iter)) + { + GtkTreePath *path; + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_STATUS, current, + -1); + + path = gtk_tree_model_get_path (model, &iter); + gtk_tree_model_row_changed (model, path, &iter); + gtk_tree_path_free (path); + } + + found = (empathy_account_manager_get_connecting_accounts (manager) > 0); + + if (!found && priv->connecting_id) + { + g_source_remove (priv->connecting_id); + priv->connecting_id = 0; + } + + if (found && !priv->connecting_id) + priv->connecting_id = g_timeout_add (FLASH_TIMEOUT, + (GSourceFunc) accounts_dialog_flash_connecting_cb, + dialog); +} + +static void +accounts_dialog_add_account (EmpathyAccountsDialog *dialog, + EmpathyAccount *account) +{ + EmpathyAccountSettings *settings; + GtkTreeModel *model; + GtkTreeIter iter; + TpConnectionStatus status; + const gchar *name; + gboolean enabled; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + g_object_get (account, "connection-status", &status, NULL); + name = empathy_account_get_display_name (account); + enabled = empathy_account_is_enabled (account); + + if (!accounts_dialog_get_account_iter (dialog, account, &iter)) + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + settings = empathy_account_settings_new_for_account (account); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, name, + COL_STATUS, status, + COL_ACCOUNT_POINTER, account, + COL_ACCOUNT_SETTINGS_POINTER, settings, + -1); + + accounts_dialog_connection_changed_cb (priv->account_manager, + account, + TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, + status, + TP_CONNECTION_STATUS_DISCONNECTED, + dialog); + + g_object_unref (settings); +} + +static void +accounts_dialog_update (EmpathyAccountsDialog *dialog, + EmpathyAccountSettings *settings) +{ + GtkTreeModel *model; + GtkTreeIter iter; + TpConnectionStatus status = TP_CONNECTION_STATUS_DISCONNECTED; + const gchar *name; + gboolean enabled = FALSE; + EmpathyAccount *account; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + name = empathy_account_settings_get_display_name (settings); + + account = empathy_account_settings_get_account (settings); + if (account != NULL) + { + enabled = empathy_account_is_enabled (account); + g_object_get (account, "connection-status", &status, NULL); + } + + accounts_dialog_get_settings_iter (dialog, settings, &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_NAME, name, + COL_STATUS, status, + COL_ACCOUNT_POINTER, account, + COL_ACCOUNT_SETTINGS_POINTER, settings, + -1); } static void accounts_dialog_account_added_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) { - const gchar *current_name; - gchar *account_param = NULL; - - accounts_dialog_add_or_update_account (dialog, account); - - /* Change the display name to "%s (%s)" % (protocol, account). - * - The protocol is the display name of the profile. - * - The account should be the normalized name of the EmpathyAccount but - * it's not set until first connection, so we get the "account" - * parameter for CM that have it. */ - current_name = empathy_account_get_display_name (account); - account_param = empathy_account_get_param_string (account, "account"); - if (!EMP_STR_EMPTY (account_param)) { - McProfile *profile; - const gchar *profile_name; - gchar *new_name; - - profile = empathy_account_get_profile (account); - profile_name = mc_profile_get_display_name (profile); - new_name = g_strdup_printf ("%s (%s)", profile_name, - account_param); - - DEBUG ("Setting new display name for account %s: '%s'", - empathy_account_get_unique_name (account), new_name); - - empathy_account_set_display_name (account, new_name); - g_free (new_name); - g_object_unref (profile); - } else { - /* FIXME: This CM has no account parameter, what can be done? */ - } - g_free (account_param); + accounts_dialog_add_account (dialog, account); } + static void accounts_dialog_account_removed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) { + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - accounts_dialog_model_set_selected (dialog, account); - accounts_dialog_model_remove_selected (dialog); + if (accounts_dialog_get_account_iter (dialog, account, &iter)) + gtk_list_store_remove (GTK_LIST_STORE ( + gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview))), &iter); } -static gboolean -accounts_dialog_row_changed_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) +static void +enable_or_disable_account (EmpathyAccountsDialog *dialog, + EmpathyAccount *account, + gboolean enabled) { - gtk_tree_model_row_changed (model, path, iter); + GtkTreeModel *model; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Update the status in the model */ + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); - return FALSE; + DEBUG ("Account %s is now %s", + empathy_account_get_display_name (account), + enabled ? "enabled" : "disabled"); } -static gboolean -accounts_dialog_flash_connecting_cb (EmpathyAccountsDialog *dialog) +static void +accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) { - GtkTreeView *view; - GtkTreeModel *model; + enable_or_disable_account (dialog, account, FALSE); +} - dialog->connecting_show = !dialog->connecting_show; +static void +accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) +{ + enable_or_disable_account (dialog, account, TRUE); +} - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); +static void +accounts_dialog_account_changed_cb (EmpathyAccountManager *manager, + EmpathyAccount *account, + EmpathyAccountsDialog *dialog) +{ + EmpathyAccountSettings *settings, *selected_settings; + GtkTreeModel *model; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + if (!accounts_dialog_get_account_iter (dialog, account, &iter)) + return; + + gtk_tree_model_get (model, &iter, + COL_ACCOUNT_SETTINGS_POINTER, &settings, + -1); - gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL); + accounts_dialog_update (dialog, settings); + selected_settings = accounts_dialog_model_get_selected_settings (dialog); - return TRUE; + if (settings == selected_settings) + accounts_dialog_update_name_label (dialog, + empathy_account_settings_get_display_name (settings)); + + if (settings) + g_object_unref (settings); + + if (selected_settings) + g_object_unref (selected_settings); } static void -accounts_dialog_connection_changed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - TpConnectionStatusReason reason, - TpConnectionStatus current, - TpConnectionStatus previous, - EmpathyAccountsDialog *dialog) +accounts_dialog_button_create_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - GtkTreeModel *model; - GtkTreeIter iter; - gboolean found; + EmpathyAccountSettings *settings; + gchar *str; + TpConnectionManager *cm; + TpConnectionManagerProtocol *proto; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); - /* Update the status in the model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + cm = empathy_protocol_chooser_dup_selected ( + EMPATHY_PROTOCOL_CHOOSER (priv->combobox_protocol), &proto); - if (accounts_dialog_get_account_iter (dialog, account, &iter)) { - GtkTreePath *path; + /* Create account */ + /* To translator: %s is the protocol name */ + str = g_strdup_printf (_("New %s account"), proto->name); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_STATUS, current, - -1); + settings = empathy_account_settings_new (cm->name, proto->name, str); - path = gtk_tree_model_get_path (model, &iter); - gtk_tree_model_row_changed (model, path, &iter); - gtk_tree_path_free (path); - } + g_free (str); - found = (empathy_account_manager_get_connecting_accounts (manager) > 0); + if (tp_connection_manager_protocol_can_register (proto)) + { + gboolean active; - if (!found && dialog->connecting_id) { - g_source_remove (dialog->connecting_id); - dialog->connecting_id = 0; - } + active = gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON (priv->radiobutton_register)); + if (active) + empathy_account_settings_set_boolean (settings, "register", TRUE); + } - if (found && !dialog->connecting_id) { - dialog->connecting_id = g_timeout_add (FLASH_TIMEOUT, - (GSourceFunc) accounts_dialog_flash_connecting_cb, - dialog); - } + accounts_dialog_add (dialog, settings); + accounts_dialog_model_set_selected (dialog, settings); + + g_object_unref (settings); + g_object_unref (cm); } static void -enable_or_disable_account (EmpathyAccountsDialog *dialog, - EmpathyAccount *account, - gboolean enabled) +accounts_dialog_button_back_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - GtkTreeModel *model; - GtkTreeIter iter; + EmpathyAccountSettings *settings; - /* Update the status in the model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + settings = accounts_dialog_model_get_selected_settings (dialog); + accounts_dialog_update_settings (dialog, settings); - DEBUG ("Account %s is now %s", - empathy_account_get_display_name (account), - enabled ? "enabled" : "disabled"); - - if (accounts_dialog_get_account_iter (dialog, account, &iter)) { - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_ENABLED, enabled, - -1); - } + if (settings) + g_object_unref (settings); } static void -accounts_dialog_account_disabled_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) +accounts_dialog_button_help_clicked_cb (GtkWidget *button, + EmpathyAccountsDialog *dialog) { - enable_or_disable_account (dialog, account, FALSE); + empathy_url_show (button, "ghelp:empathy?empathy-create-account"); } static void -accounts_dialog_account_enabled_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) +accounts_dialog_response_cb (GtkWidget *widget, + gint response, + EmpathyAccountsDialog *dialog) { - enable_or_disable_account (dialog, account, TRUE); + if (response == GTK_RESPONSE_CLOSE) + gtk_widget_destroy (widget); } static void -accounts_dialog_account_changed_cb (EmpathyAccountManager *manager, - EmpathyAccount *account, - EmpathyAccountsDialog *dialog) +accounts_dialog_destroy_cb (GtkObject *obj, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *selected_account; + DEBUG ("%p", obj); - accounts_dialog_add_or_update_account (dialog, account); - selected_account = accounts_dialog_model_get_selected (dialog); - if (empathy_account_equal (account, selected_account)) { - accounts_dialog_update_name_label (dialog, account); - } + g_object_unref (dialog); } static void -accounts_dialog_button_create_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +accounts_dialog_set_selected_account (EmpathyAccountsDialog *dialog, + EmpathyAccount *account) { - McProfile *profile; - EmpathyAccount *account; - gchar *str; - McProfileCapabilityFlags cap; - - profile = empathy_profile_chooser_dup_selected ( - EMPATHY_PROFILE_CHOOSER (dialog->combobox_profile)); - - /* Create account */ - account = empathy_account_manager_create (dialog->account_manager, profile); - if (account == NULL) { - /* We can't display an error to the user as MC doesn't give us - * any clue about the reason of the failure... */ - g_object_unref (profile); - return; - } - - /* To translator: %s is the protocol name */ - str = g_strdup_printf (_("New %s account"), - mc_profile_get_display_name (profile)); - empathy_account_set_display_name (account, str); - g_free (str); - - cap = mc_profile_get_capabilities (profile); - if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) { - gboolean active; - - active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_register)); - if (active) { - empathy_account_set_param_boolean (account, "register", TRUE); - } - } - - accounts_dialog_add_or_update_account (dialog, account); - accounts_dialog_model_set_selected (dialog, account); - - g_object_unref (account); - g_object_unref (profile); + GtkTreeSelection *selection; + GtkTreeIter iter; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); + if (accounts_dialog_get_account_iter (dialog, account, &iter)) + gtk_tree_selection_select_iter (selection, &iter); } static void -accounts_dialog_button_back_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +accounts_dialog_cms_ready_cb (EmpathyConnectionManagers *cms, + GParamSpec *pspec, + EmpathyAccountsDialog *dialog) { - EmpathyAccount *account; - - account = accounts_dialog_model_get_selected (dialog); - accounts_dialog_update_account (dialog, account); + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + if (empathy_connection_managers_is_ready (cms)) + { + accounts_dialog_update_settings (dialog, NULL); + + if (priv->initial_selection != NULL) + { + accounts_dialog_set_selected_account + (dialog, priv->initial_selection); + g_object_unref (priv->initial_selection); + priv->initial_selection = NULL; + } + } } static void -accounts_dialog_profile_changed_cb (GtkWidget *widget, - EmpathyAccountsDialog *dialog) +accounts_dialog_build_ui (EmpathyAccountsDialog *dialog) { - McProfile *profile; - McProfileCapabilityFlags cap; - - profile = empathy_profile_chooser_dup_selected ( - EMPATHY_PROFILE_CHOOSER (dialog->combobox_profile)); - cap = mc_profile_get_capabilities (profile); - - if (cap & MC_PROFILE_CAPABILITY_REGISTRATION_UI) { - gtk_widget_show (dialog->radiobutton_register); - gtk_widget_show (dialog->radiobutton_reuse); - } else { - gtk_widget_hide (dialog->radiobutton_register); - gtk_widget_hide (dialog->radiobutton_reuse); - } - g_object_unref (profile); + GtkBuilder *gui; + gchar *filename; + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + filename = empathy_file_lookup ("empathy-accounts-dialog.ui", "src"); + + gui = empathy_builder_get_file (filename, + "accounts_dialog", &priv->window, + "vbox_details", &priv->vbox_details, + "frame_no_protocol", &priv->frame_no_protocol, + "alignment_settings", &priv->alignment_settings, + "treeview", &priv->treeview, + "frame_new_account", &priv->frame_new_account, + "hbox_type", &priv->hbox_type, + "button_create", &priv->button_create, + "button_back", &priv->button_back, + "radiobutton_reuse", &priv->radiobutton_reuse, + "radiobutton_register", &priv->radiobutton_register, + "image_type", &priv->image_type, + "label_name", &priv->label_name, + "button_add", &priv->button_add, + NULL); + g_free (filename); + + empathy_builder_connect (gui, dialog, + "accounts_dialog", "response", accounts_dialog_response_cb, + "accounts_dialog", "destroy", accounts_dialog_destroy_cb, + "button_create", "clicked", accounts_dialog_button_create_clicked_cb, + "button_back", "clicked", accounts_dialog_button_back_clicked_cb, + "button_add", "clicked", accounts_dialog_button_add_clicked_cb, + "button_help", "clicked", accounts_dialog_button_help_clicked_cb, + NULL); + + g_object_unref (gui); + + priv->combobox_protocol = empathy_protocol_chooser_new (); + gtk_box_pack_start (GTK_BOX (priv->hbox_type), + priv->combobox_protocol, + TRUE, TRUE, 0); + gtk_widget_show (priv->combobox_protocol); + g_signal_connect (priv->combobox_protocol, "changed", + G_CALLBACK (accounts_dialog_protocol_changed_cb), + dialog); + + if (priv->parent_window) + gtk_window_set_transient_for (GTK_WINDOW (priv->window), + priv->parent_window); } static void -accounts_dialog_button_add_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_dispose (GObject *obj) +{ + EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (obj); + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + + /* Disconnect signals */ + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_added_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_removed_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_enabled_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_disabled_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_account_changed_cb, + dialog); + g_signal_handlers_disconnect_by_func (priv->account_manager, + accounts_dialog_connection_changed_cb, + dialog); + + if (priv->connecting_id) + g_source_remove (priv->connecting_id); + + if (priv->account_manager != NULL) + { + g_object_unref (priv->account_manager); + priv->account_manager = NULL; + } + + if (priv->cms != NULL) + { + g_object_unref (priv->cms); + priv->cms = NULL; + } + + if (priv->initial_selection != NULL) + g_object_unref (priv->initial_selection); + priv->initial_selection = NULL; + + G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->dispose (obj); +} + +static GObject * +do_constructor (GType type, + guint n_props, + GObjectConstructParam *props) { - GtkTreeView *view; - GtkTreeSelection *selection; - GtkTreeModel *model; - - view = GTK_TREE_VIEW (dialog->treeview); - model = gtk_tree_view_get_model (view); - selection = gtk_tree_view_get_selection (view); - gtk_tree_selection_unselect_all (selection); - - gtk_widget_set_sensitive (dialog->button_add, FALSE); - gtk_widget_set_sensitive (dialog->button_remove, FALSE); - gtk_widget_hide (dialog->vbox_details); - gtk_widget_hide (dialog->frame_no_profile); - gtk_widget_show (dialog->frame_new_account); - - /* If we have no account, no need of a back button */ - if (gtk_tree_model_iter_n_children (model, NULL) > 0) { - gtk_widget_show (dialog->button_back); - } else { - gtk_widget_hide (dialog->button_back); - } - - accounts_dialog_profile_changed_cb (dialog->radiobutton_register, dialog); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->radiobutton_reuse), - TRUE); - gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->combobox_profile), 0); - gtk_widget_grab_focus (dialog->combobox_profile); + GObject *retval; + + if (dialog_singleton) + { + retval = G_OBJECT (dialog_singleton); + g_object_ref (retval); + } + else + { + retval = + G_OBJECT_CLASS (empathy_accounts_dialog_parent_class)->constructor + (type, n_props, props); + + dialog_singleton = EMPATHY_ACCOUNTS_DIALOG (retval); + g_object_add_weak_pointer (retval, (gpointer) &dialog_singleton); + } + + return retval; } static void -accounts_dialog_button_help_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - empathy_url_show (button, "ghelp:empathy#add-account"); + EmpathyAccountsDialogPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } } static void -accounts_dialog_button_remove_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - EmpathyAccount *account; - GtkWidget *message_dialog; - gint res; - - account = accounts_dialog_model_get_selected (dialog); - - if (!empathy_account_is_valid (account)) { - accounts_dialog_model_remove_selected (dialog); - accounts_dialog_model_select_first (dialog); - return; - } - message_dialog = gtk_message_dialog_new - (GTK_WINDOW (dialog->window), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - _("You are about to remove your %s account!\n" - "Are you sure you want to proceed?"), - empathy_account_get_display_name (account)); - - gtk_message_dialog_format_secondary_text - (GTK_MESSAGE_DIALOG (message_dialog), - _("Any associated conversations and chat rooms will NOT be " - "removed if you decide to proceed.\n" - "\n" - "Should you decide to add the account back at a later time, " - "they will still be available.")); - - gtk_dialog_add_button (GTK_DIALOG (message_dialog), - GTK_STOCK_CANCEL, - GTK_RESPONSE_NO); - gtk_dialog_add_button (GTK_DIALOG (message_dialog), - GTK_STOCK_REMOVE, - GTK_RESPONSE_YES); - - gtk_widget_show (message_dialog); - res = gtk_dialog_run (GTK_DIALOG (message_dialog)); - - if (res == GTK_RESPONSE_YES) { - empathy_account_manager_remove (dialog->account_manager, account); - accounts_dialog_model_select_first (dialog); - } - gtk_widget_destroy (message_dialog); + EmpathyAccountsDialogPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_PARENT: + priv->parent_window = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } } static void -accounts_dialog_button_import_clicked_cb (GtkWidget *button, - EmpathyAccountsDialog *dialog) +do_constructed (GObject *object) { - empathy_import_dialog_show (GTK_WINDOW (dialog->window), TRUE); + EmpathyAccountsDialog *dialog = EMPATHY_ACCOUNTS_DIALOG (object); + EmpathyAccountsDialogPriv *priv = GET_PRIV (dialog); + GList *accounts, *l; + gboolean import_asked; + + accounts_dialog_build_ui (dialog); + + /* Set up signalling */ + priv->account_manager = empathy_account_manager_dup_singleton (); + + g_signal_connect (priv->account_manager, "account-created", + G_CALLBACK (accounts_dialog_account_added_cb), + dialog); + g_signal_connect (priv->account_manager, "account-deleted", + G_CALLBACK (accounts_dialog_account_removed_cb), + dialog); + g_signal_connect (priv->account_manager, "account-enabled", + G_CALLBACK (accounts_dialog_account_enabled_cb), + dialog); + g_signal_connect (priv->account_manager, "account-disabled", + G_CALLBACK (accounts_dialog_account_disabled_cb), + dialog); + g_signal_connect (priv->account_manager, "account-changed", + G_CALLBACK (accounts_dialog_account_changed_cb), + dialog); + g_signal_connect (priv->account_manager, "account-connection-changed", + G_CALLBACK (accounts_dialog_connection_changed_cb), + dialog); + + accounts_dialog_model_setup (dialog); + + /* Add existing accounts */ + accounts = empathy_account_manager_dup_accounts (priv->account_manager); + for (l = accounts; l; l = l->next) + { + accounts_dialog_add_account (dialog, l->data); + g_object_unref (l->data); + } + g_list_free (accounts); + + priv->cms = empathy_connection_managers_dup_singleton (); + if (!empathy_connection_managers_is_ready (priv->cms)) + g_signal_connect (priv->cms, "notify::ready", + G_CALLBACK (accounts_dialog_cms_ready_cb), dialog); + + accounts_dialog_model_select_first (dialog); + + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_IMPORT_ASKED, &import_asked); + + + if (empathy_import_accounts_to_import ()) + { + + if (!import_asked) + { + GtkWidget *import_dialog; + + empathy_conf_set_bool (empathy_conf_get (), + EMPATHY_PREFS_IMPORT_ASKED, TRUE); + import_dialog = empathy_import_dialog_new (GTK_WINDOW (priv->window), + FALSE); + gtk_widget_show (import_dialog); + } + } } static void -accounts_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyAccountsDialog *dialog) +empathy_accounts_dialog_class_init (EmpathyAccountsDialogClass *klass) { - if (response == GTK_RESPONSE_CLOSE) { - gtk_widget_destroy (widget); - } + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + oclass->constructor = do_constructor; + oclass->dispose = do_dispose; + oclass->constructed = do_constructed; + oclass->set_property = do_set_property; + oclass->get_property = do_get_property; + + param_spec = g_param_spec_object ("parent", + "parent", "The parent window", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PARENT, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyAccountsDialogPriv)); } static void -accounts_dialog_destroy_cb (GtkWidget *widget, - EmpathyAccountsDialog *dialog) +empathy_accounts_dialog_init (EmpathyAccountsDialog *dialog) { - GList *accounts, *l; - - /* Disconnect signals */ - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_added_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_removed_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_enabled_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_disabled_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_account_changed_cb, - dialog); - g_signal_handlers_disconnect_by_func (dialog->account_manager, - accounts_dialog_connection_changed_cb, - dialog); - - /* Delete incomplete accounts */ - accounts = empathy_account_manager_dup_accounts (dialog->account_manager); - for (l = accounts; l; l = l->next) { - EmpathyAccount *account; - - account = l->data; - if (!empathy_account_is_valid (account)) { - /* FIXME: Warn the user the account is not complete - * and is going to be removed. */ - empathy_account_manager_remove (dialog->account_manager, account); - } - - g_object_unref (account); - } - g_list_free (accounts); - - if (dialog->connecting_id) { - g_source_remove (dialog->connecting_id); - } - - g_object_unref (dialog->account_manager); - g_object_unref (dialog->mc); - - g_free (dialog); + EmpathyAccountsDialogPriv *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE ((dialog), + EMPATHY_TYPE_ACCOUNTS_DIALOG, + EmpathyAccountsDialogPriv); + dialog->priv = priv; } +/* public methods */ + GtkWidget * empathy_accounts_dialog_show (GtkWindow *parent, - EmpathyAccount *selected_account) + EmpathyAccount *selected_account) { - static EmpathyAccountsDialog *dialog = NULL; - GtkBuilder *gui; - gchar *filename; - GList *accounts, *l; - gboolean import_asked; - - if (dialog) { - gtk_window_present (GTK_WINDOW (dialog->window)); - return dialog->window; - } - - dialog = g_new0 (EmpathyAccountsDialog, 1); - - filename = empathy_file_lookup ("empathy-accounts-dialog.ui", - "src"); - gui = empathy_builder_get_file (filename, - "accounts_dialog", &dialog->window, - "vbox_details", &dialog->vbox_details, - "frame_no_profile", &dialog->frame_no_profile, - "alignment_settings", &dialog->alignment_settings, - "treeview", &dialog->treeview, - "frame_new_account", &dialog->frame_new_account, - "hbox_type", &dialog->hbox_type, - "button_create", &dialog->button_create, - "button_back", &dialog->button_back, - "radiobutton_reuse", &dialog->radiobutton_reuse, - "radiobutton_register", &dialog->radiobutton_register, - "image_type", &dialog->image_type, - "label_name", &dialog->label_name, - "button_add", &dialog->button_add, - "button_remove", &dialog->button_remove, - "button_import", &dialog->button_import, - NULL); - g_free (filename); - - empathy_builder_connect (gui, dialog, - "accounts_dialog", "destroy", accounts_dialog_destroy_cb, - "accounts_dialog", "response", accounts_dialog_response_cb, - "button_create", "clicked", accounts_dialog_button_create_clicked_cb, - "button_back", "clicked", accounts_dialog_button_back_clicked_cb, - "button_add", "clicked", accounts_dialog_button_add_clicked_cb, - "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb, - "button_import", "clicked", accounts_dialog_button_import_clicked_cb, - "button_help", "clicked", accounts_dialog_button_help_clicked_cb, - NULL); - - g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog); - - g_object_unref (gui); - - /* Create profile chooser */ - dialog->combobox_profile = empathy_profile_chooser_new (); - gtk_box_pack_end (GTK_BOX (dialog->hbox_type), - dialog->combobox_profile, - TRUE, TRUE, 0); - gtk_widget_show (dialog->combobox_profile); - g_signal_connect (dialog->combobox_profile, "changed", - G_CALLBACK (accounts_dialog_profile_changed_cb), - dialog); - - /* Set up signalling */ - dialog->account_manager = empathy_account_manager_dup_singleton (); - dialog->mc = empathy_mission_control_dup_singleton (); - - g_signal_connect (dialog->account_manager, "account-created", - G_CALLBACK (accounts_dialog_account_added_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-deleted", - G_CALLBACK (accounts_dialog_account_removed_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-enabled", - G_CALLBACK (accounts_dialog_account_enabled_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-disabled", - G_CALLBACK (accounts_dialog_account_disabled_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-changed", - G_CALLBACK (accounts_dialog_account_changed_cb), - dialog); - g_signal_connect (dialog->account_manager, "account-connection-changed", - G_CALLBACK (accounts_dialog_connection_changed_cb), - dialog); - - accounts_dialog_model_setup (dialog); - - /* Add existing accounts */ - accounts = empathy_account_manager_dup_accounts (dialog->account_manager); - for (l = accounts; l; l = l->next) { - accounts_dialog_add_or_update_account (dialog, l->data); - g_object_unref (l->data); - } - g_list_free (accounts); - - if (selected_account) { - accounts_dialog_model_set_selected (dialog, selected_account); - } else { - accounts_dialog_model_select_first (dialog); - } - - if (parent) { - gtk_window_set_transient_for (GTK_WINDOW (dialog->window), - GTK_WINDOW (parent)); - } - - gtk_widget_show (dialog->window); - - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_IMPORT_ASKED, &import_asked); - - - if (empathy_import_dialog_accounts_to_import ()) { - - if (!import_asked) { - empathy_conf_set_bool (empathy_conf_get (), - EMPATHY_PREFS_IMPORT_ASKED, TRUE); - empathy_import_dialog_show (GTK_WINDOW (dialog->window), - FALSE); - } - } else { - gtk_widget_set_sensitive (dialog->button_import, FALSE); - } - - return dialog->window; -} + EmpathyAccountsDialog *dialog; + EmpathyAccountsDialogPriv *priv; + + dialog = g_object_new (EMPATHY_TYPE_ACCOUNTS_DIALOG, + "parent", parent, NULL); + priv = GET_PRIV (dialog); + + if (selected_account) + { + if (empathy_connection_managers_is_ready (priv->cms)) + accounts_dialog_set_selected_account (dialog, selected_account); + else + /* save the selection to set it later when the cms + * becomes ready. + */ + priv->initial_selection = g_object_ref (selected_account); + } + + gtk_window_present (GTK_WINDOW (priv->window)); + + return priv->window; +} diff --git a/src/empathy-accounts-dialog.h b/src/empathy-accounts-dialog.h index 11e237c8f..aa8f7c06b 100644 --- a/src/empathy-accounts-dialog.h +++ b/src/empathy-accounts-dialog.h @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2005-2007 Imendio AB * Copyright (C) 2007-2008 Collabora Ltd. @@ -31,8 +30,32 @@ G_BEGIN_DECLS +#define EMPATHY_TYPE_ACCOUNTS_DIALOG empathy_accounts_dialog_get_type() +#define EMPATHY_ACCOUNTS_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_ACCOUNTS_DIALOG, EmpathyAccountsDialog)) +#define EMPATHY_ACCOUNTS_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_ACCOUNTS_DIALOG, EmpathyAccountsDialogClass)) +#define EMPATHY_IS_ACCOUNTS_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_ACCOUNTS_DIALOG)) +#define EMPATHY_IS_ACCOUNTS_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_ACCOUNTS_DIALOG)) +#define EMPATHY_ACCOUNTS_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_ACCOUNTS_DIALOG, EmpathyAccountsDialogClass)) + +typedef struct { + GObject parent; + + /* private */ + gpointer priv; +} EmpathyAccountsDialog; + +typedef struct { + GObjectClass parent_class; +} EmpathyAccountsDialogClass; + +GType empathy_accounts_dialog_get_type (void); GtkWidget *empathy_accounts_dialog_show (GtkWindow *parent, - EmpathyAccount *selected_account); + EmpathyAccount *selected_account); G_END_DECLS diff --git a/src/empathy-accounts-dialog.ui b/src/empathy-accounts-dialog.ui index da00f45d7..e5226b270 100644 --- a/src/empathy-accounts-dialog.ui +++ b/src/empathy-accounts-dialog.ui @@ -2,14 +2,11 @@ <interface> <requires lib="gtk+" version="2.16"/> <!-- interface-naming-policy toplevel-contextual --> - <object class="GtkImage" id="add_image"> - <property name="stock">gtk-add</property> - <property name="icon-size">4</property> - </object> <object class="GtkDialog" id="accounts_dialog"> <property name="border_width">5</property> <property name="title" translatable="yes">Accounts</property> <property name="role">accounts</property> + <property name="default_width">640</property> <property name="type_hint">dialog</property> <property name="has_separator">False</property> <child internal-child="vbox"> @@ -46,62 +43,18 @@ </packing> </child> <child> - <object class="GtkVBox" id="vbox1"> + <object class="GtkButton" id="button_add"> + <property name="label" translatable="yes">_Add...</property> <property name="visible">True</property> - <property name="spacing">6</property> - <property name="homogeneous">True</property> - <child> - <object class="GtkHBox" id="hbox148"> - <property name="visible">True</property> - <property name="spacing">6</property> - <property name="homogeneous">True</property> - <child> - <object class="GtkButton" id="button_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="image">add_image</property> - <property name="label" translatable="yes">_Add...</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_remove"> - <property name="label">gtk-remove</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_import"> - <property name="label" translatable="yes">Import Accounts...</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="image">add_image</property> + <property name="use_underline">True</property> </object> <packing> <property name="expand">False</property> - <property name="position">1</property> + <property name="fill">False</property> + <property name="position">2</property> </packing> </child> </object> @@ -127,12 +80,11 @@ <object class="GtkLabel" id="label_name"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Gmail</property> + <property name="selectable">True</property> <attributes> <attribute name="weight" value="bold"/> - <attribute name="scale" value="1.2"/> + <attribute name="scale" value="1.200000"/> </attributes> - <property name="selectable">True</property> </object> <packing> <property name="position">0</property> @@ -159,28 +111,12 @@ </packing> </child> <child> - <object class="GtkFrame" id="frame2"> + <object class="GtkAlignment" id="alignment_settings"> <property name="visible">True</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> + <property name="top_padding">6</property> + <property name="left_padding">20</property> <child> - <object class="GtkAlignment" id="alignment_settings"> - <property name="visible">True</property> - <property name="top_padding">6</property> - <property name="left_padding">20</property> - <child> - <placeholder/> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label599"> - <property name="visible">True</property> - <property name="label" translatable="yes">Settings</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> + <placeholder/> </child> </object> <packing> @@ -206,29 +142,6 @@ <property name="visible">True</property> <property name="spacing">12</property> <child> - <object class="GtkHBox" id="hbox_type"> - <property name="visible">True</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label645"> - <property name="visible">True</property> - <property name="label" translatable="yes">Type:</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="position">0</property> - </packing> - </child> - <child> <object class="GtkVBox" id="vbox2"> <property name="visible">True</property> <property name="orientation">vertical</property> @@ -347,12 +260,45 @@ </object> </child> <child type="label"> - <object class="GtkLabel" id="label643"> + <object class="GtkHBox" id="hbox_add_account"> <property name="visible">True</property> - <property name="label" translatable="yes">Add Account</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> + <child> + <object class="GtkLabel" id="label643"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add new</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="padding">5</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox_type"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="label645"> + <property name="visible">True</property> + <property name="label" translatable="yes">account</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> </object> </child> </object> @@ -362,7 +308,7 @@ </packing> </child> <child> - <object class="GtkFrame" id="frame_no_profile"> + <object class="GtkFrame" id="frame_no_protocol"> <property name="label_xalign">0</property> <property name="shadow_type">none</property> <child> @@ -454,4 +400,7 @@ <action-widget response="-7">button_close</action-widget> </action-widgets> </object> + <object class="GtkImage" id="add_image"> + <property name="stock">gtk-add</property> + </object> </interface> diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index fb5a5c796..5f81ac167 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -35,7 +35,6 @@ #include <libnotify/notification.h> #include <telepathy-glib/util.h> -#include <libmissioncontrol/mission-control.h> #include <libempathy/empathy-contact.h> #include <libempathy/empathy-message.h> @@ -1268,7 +1267,7 @@ chat_window_drag_data_received (GtkWidget *widget, strv = g_strsplit (id, "/", 2); account_id = strv[0]; contact_id = strv[1]; - account = empathy_account_manager_lookup (account_manager, account_id); + account = empathy_account_manager_get_account (account_manager, account_id); chat = empathy_chat_window_find_chat (account, contact_id); if (!chat) { @@ -1281,11 +1280,9 @@ chat_window_drag_data_received (GtkWidget *widget, connection, contact_id, NULL, NULL); } - g_object_unref (account); g_strfreev (strv); return; } - g_object_unref (account); g_object_unref (account_manager); g_strfreev (strv); @@ -1777,7 +1774,7 @@ empathy_chat_window_find_chat (EmpathyAccount *account, chat = ll->data; - if (empathy_account_equal (account, empathy_chat_get_account (chat)) && + if (account == empathy_chat_get_account (chat) && !tp_strdiff (id, empathy_chat_get_id (chat))) { return chat; } diff --git a/src/empathy-chatrooms-window.c b/src/empathy-chatrooms-window.c index 3b5dd1f77..4ec71ec49 100644 --- a/src/empathy-chatrooms-window.c +++ b/src/empathy-chatrooms-window.c @@ -514,7 +514,7 @@ chatrooms_window_chatroom_added_cb (EmpathyChatroomManager *manager, if (!account) { chatrooms_window_model_add (window, chatroom, FALSE); } else { - if (empathy_account_equal (account, empathy_chatroom_get_account (chatroom))) { + if (account == empathy_chatroom_get_account (chatroom)) { chatrooms_window_model_add (window, chatroom, FALSE); } diff --git a/src/empathy-debug-dialog.c b/src/empathy-debug-dialog.c index 9d047bab1..d71542db0 100644 --- a/src/empathy-debug-dialog.c +++ b/src/empathy-debug-dialog.c @@ -284,7 +284,6 @@ debug_dialog_cm_chooser_changed_cb (GtkComboBox *cm_chooser, EmpathyDebugDialog *debug_dialog) { EmpathyDebugDialogPriv *priv = GET_PRIV (debug_dialog); - MissionControl *mc; TpDBusDaemon *dbus; GError *error = NULL; gchar *bus_name; @@ -302,13 +301,11 @@ debug_dialog_cm_chooser_changed_cb (GtkComboBox *cm_chooser, return; } - mc = empathy_mission_control_dup_singleton (); dbus = tp_dbus_daemon_dup (&error); if (error != NULL) { DEBUG ("Failed at duping the dbus daemon: %s", error->message); - g_object_unref (mc); } gtk_tree_model_get (GTK_TREE_MODEL (priv->cms), &iter, @@ -344,7 +341,6 @@ debug_dialog_cm_chooser_changed_cb (GtkComboBox *cm_chooser, debug_dialog_get_messages_cb, debug_dialog, NULL, NULL); g_object_unref (dbus); - g_object_unref (mc); } typedef struct diff --git a/src/empathy-event-manager.c b/src/empathy-event-manager.c index 1a7ec09cb..1be3ff7ce 100644 --- a/src/empathy-event-manager.c +++ b/src/empathy-event-manager.c @@ -25,6 +25,7 @@ #include <glib/gi18n.h> #include <telepathy-glib/util.h> +#include <telepathy-glib/interfaces.h> #include <libempathy/empathy-account-manager.h> #include <libempathy/empathy-dispatcher.h> diff --git a/src/empathy-import-dialog.c b/src/empathy-import-dialog.c index 1e135892d..94c6fd765 100644 --- a/src/empathy-import-dialog.c +++ b/src/empathy-import-dialog.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 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 @@ -17,12 +17,11 @@ * Boston, MA 02110-1301 USA * * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> - * */ + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ #include <config.h> -#include <string.h> - #include <glib.h> #include <gtk/gtk.h> #include <glib/gi18n.h> @@ -31,401 +30,210 @@ #include "empathy-import-dialog.h" #include "empathy-import-pidgin.h" +#include "empathy-import-widget.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER #include <libempathy/empathy-debug.h> #include <libempathy/empathy-utils.h> -#include <libempathy/empathy-account-manager.h> - #include <libempathy-gtk/empathy-ui-utils.h> -typedef struct -{ - GtkWidget *window; - GtkWidget *treeview; - GtkWidget *button_ok; - GtkWidget *button_cancel; - GList *accounts; -} EmpathyImportDialog; - -enum -{ - COL_IMPORT = 0, - COL_PROTOCOL, - COL_NAME, - COL_SOURCE, - COL_ACCOUNT_DATA, - COL_COUNT +enum { + PROP_PARENT = 1, + PROP_SHOW_WARNING }; -EmpathyImportAccountData * -empathy_import_account_data_new (const gchar *source) -{ - EmpathyImportAccountData *data; +typedef struct { + GtkWindow *parent_window; - g_return_val_if_fail (!EMP_STR_EMPTY (source), NULL); + EmpathyImportWidget *iw; - data = g_slice_new0 (EmpathyImportAccountData); - data->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, - (GDestroyNotify) tp_g_value_slice_free); - data->source = g_strdup (source); + gboolean show_warning; +} EmpathyImportDialogPriv; - return data; -} - -void -empathy_import_account_data_free (EmpathyImportAccountData *data) -{ - if (data == NULL) - return; - if (data->profile != NULL) - g_object_unref (data->profile); - if (data->settings != NULL) - g_hash_table_destroy (data->settings); - if (data->source != NULL) - g_free (data->source); - - g_slice_free (EmpathyImportAccountData, data); -} +G_DEFINE_TYPE (EmpathyImportDialog, empathy_import_dialog, GTK_TYPE_DIALOG) +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyImportDialog) static void -import_dialog_add_account (EmpathyImportAccountData *data) +import_dialog_add_import_widget (EmpathyImportDialog *self) { - EmpathyAccountManager *account_manager; - EmpathyAccount *account; - GHashTableIter iter; - gpointer key, value; - gchar *display_name; - GValue *username; - - account_manager = empathy_account_manager_dup_singleton (); - account = empathy_account_manager_create (account_manager, data->profile); - g_object_unref (account_manager); - if (account == NULL) - { - DEBUG ("Failed to create account"); - return; - } + EmpathyImportWidget *iw; + EmpathyImportDialogPriv *priv = GET_PRIV (self); + GtkWidget *widget, *area; - g_hash_table_iter_init (&iter, data->settings); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const gchar *param = key; - GValue *gvalue = value; + area = gtk_dialog_get_content_area (GTK_DIALOG (self)); - switch (G_VALUE_TYPE (gvalue)) - { - case G_TYPE_STRING: - DEBUG ("Set param '%s' to '%s' (string)", - param, g_value_get_string (gvalue)); - empathy_account_set_param_string (account, - param, g_value_get_string (gvalue)); - break; - - case G_TYPE_BOOLEAN: - DEBUG ("Set param '%s' to %s (boolean)", - param, g_value_get_boolean (gvalue) ? "TRUE" : "FALSE"); - empathy_account_set_param_boolean (account, - param, g_value_get_boolean (gvalue)); - break; - - case G_TYPE_INT: - DEBUG ("Set param '%s' to '%i' (integer)", - param, g_value_get_int (gvalue)); - empathy_account_set_param_int (account, - param, g_value_get_int (gvalue)); - break; - } - } + iw = empathy_import_widget_new (EMPATHY_IMPORT_APPLICATION_ALL); + widget = empathy_import_widget_get_widget (iw); + gtk_box_pack_start (GTK_BOX (area), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); - /* Set the display name of the account */ - username = g_hash_table_lookup (data->settings, "account"); - display_name = g_strdup_printf ("%s (%s)", - mc_profile_get_display_name (data->profile), - g_value_get_string (username)); - empathy_account_set_display_name (account, display_name); + priv->iw = iw; - g_free (display_name); - g_object_unref (account); -} - -static gboolean -import_dialog_account_id_in_list (GList *accounts, - const gchar *account_id) -{ - GList *l; - - for (l = accounts; l; l = l->next) - { - McAccount *account = l->data; - gchar *value = NULL; - gboolean result; - - mc_account_get_param_string (account, "account", &value); - - if (value == NULL) - continue; - - result = tp_strdiff (value, account_id); - - g_free (value); - - if (!result) - return TRUE; - } - - return FALSE; + gtk_dialog_add_buttons (GTK_DIALOG (self), GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); } static void -import_dialog_add_accounts_to_model (EmpathyImportDialog *dialog) +import_dialog_show_warning_message (EmpathyImportDialog *self) { - GtkTreeModel *model; - GtkTreeIter iter; - GList *l; + GtkWidget *hbox, *vbox, *w; - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + vbox = gtk_vbox_new (FALSE, 12); + hbox = gtk_hbox_new (FALSE, 12); - for (l = dialog->accounts; l; l = l->next) - { - GValue *value; - EmpathyImportAccountData *data = l->data; - gboolean import; - GList *accounts; + w = gtk_label_new (_("No accounts to import could be found. Empathy " + "currently only supports importing accounts from Pidgin.")); + gtk_label_set_line_wrap (GTK_LABEL (w), TRUE); + gtk_label_set_selectable (GTK_LABEL (w), TRUE); + gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0); - value = g_hash_table_lookup (data->settings, "account"); + w = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, + GTK_ICON_SIZE_DIALOG); + gtk_misc_set_alignment (GTK_MISC (w), 0.5, 0.0); + gtk_box_pack_start (GTK_BOX (hbox), w, FALSE, FALSE, 0); - accounts = mc_accounts_list_by_profile (data->profile); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); - /* Only set the "Import" cell to be active if there isn't already an - * account set up with the same account id. */ - import = !import_dialog_account_id_in_list (accounts, - g_value_get_string (value)); + w = gtk_dialog_get_content_area (GTK_DIALOG (self)); + gtk_box_pack_start (GTK_BOX (w), hbox, FALSE, FALSE, 0); - mc_accounts_list_free (accounts); + gtk_box_set_spacing (GTK_BOX (w), 14); /* 14 + 2 * 5 = 24 */ - gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CLOSE, + GTK_RESPONSE_CLOSE); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_IMPORT, import, - COL_PROTOCOL, mc_profile_get_display_name (data->profile), - COL_NAME, g_value_get_string (value), - COL_SOURCE, data->source, - COL_ACCOUNT_DATA, data, - -1); - } + gtk_widget_show_all (w); } static void -import_dialog_cell_toggled_cb (GtkCellRendererToggle *cell_renderer, - const gchar *path_str, - EmpathyImportDialog *dialog) +impl_signal_response (GtkDialog *dialog, + gint response_id) { - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; + EmpathyImportDialogPriv *priv = GET_PRIV (dialog); - path = gtk_tree_path_new_from_string (path_str); - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); + if (response_id == GTK_RESPONSE_OK) + empathy_import_widget_add_selected_accounts (priv->iw); - gtk_tree_model_get_iter (model, &iter, path); - - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer), - -1); - - gtk_tree_path_free (path); + gtk_widget_destroy (GTK_WIDGET (dialog)); } static void -import_dialog_set_up_account_list (EmpathyImportDialog *dialog) -{ - GtkListStore *store; - GtkTreeView *view; - GtkTreeViewColumn *column; - GtkCellRenderer *cell; - - store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); - - gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview), - GTK_TREE_MODEL (store)); - - g_object_unref (store); - - view = GTK_TREE_VIEW (dialog->treeview); - gtk_tree_view_set_headers_visible (view, TRUE); - - /* Import column */ - cell = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (view, -1, - /* Translators: this is the header of a treeview column */ - _("Import"), cell, - "active", COL_IMPORT, - NULL); - - g_signal_connect (cell, "toggled", - G_CALLBACK (import_dialog_cell_toggled_cb), dialog); - - /* Protocol column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Protocol")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "editable", FALSE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL); - - /* Account column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Account")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "editable", FALSE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); - - /* Source column */ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("Source")); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_append_column (view, column); - - cell = gtk_cell_renderer_text_new (); - g_object_set (cell, - "editable", FALSE, - NULL); - gtk_tree_view_column_pack_start (column, cell, TRUE); - gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE); - - import_dialog_add_accounts_to_model (dialog); -} - -static gboolean -import_dialog_tree_model_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer user_data) +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) { - gboolean to_import; - EmpathyImportAccountData *data; - - gtk_tree_model_get (model, iter, - COL_IMPORT, &to_import, - COL_ACCOUNT_DATA, &data, - -1); - - if (to_import) - import_dialog_add_account (data); - - return FALSE; -} + EmpathyImportDialogPriv *priv = GET_PRIV (object); -static void -import_dialog_response_cb (GtkWidget *widget, - gint response, - EmpathyImportDialog *dialog) -{ - if (response == GTK_RESPONSE_OK) + switch (property_id) { - GtkTreeModel *model; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview)); - gtk_tree_model_foreach (model, import_dialog_tree_model_foreach, dialog); + case PROP_PARENT: + g_value_set_object (value, priv->parent_window); + break; + case PROP_SHOW_WARNING: + g_value_set_boolean (value, priv->show_warning); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } - - gtk_widget_destroy (dialog->window); } static void -import_dialog_destroy_cb (GtkWidget *widget, - EmpathyImportDialog *dialog) +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) { - g_list_foreach (dialog->accounts, (GFunc) empathy_import_account_data_free, - NULL); - g_list_free (dialog->accounts); - g_slice_free (EmpathyImportDialog, dialog); -} + EmpathyImportDialogPriv *priv = GET_PRIV (object); -gboolean -empathy_import_dialog_accounts_to_import (void) -{ - return empathy_import_pidgin_accounts_to_import (); + switch (property_id) + { + case PROP_PARENT: + priv->parent_window = g_value_get_object (value); + break; + case PROP_SHOW_WARNING: + priv->show_warning = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } } -void -empathy_import_dialog_show (GtkWindow *parent, - gboolean warning) +static void +do_constructed (GObject *obj) { - static EmpathyImportDialog *dialog = NULL; - GtkBuilder *gui; - gchar *filename; - GList *accounts = NULL; - - /* This window is a singleton. If it already exist, present it */ - if (dialog) - { - gtk_window_present (GTK_WINDOW (dialog->window)); - return; - } + EmpathyImportDialog *self = EMPATHY_IMPORT_DIALOG (obj); + EmpathyImportDialogPriv *priv = GET_PRIV (self); + gboolean have_accounts; - /* Load all accounts from all supported applications */ - accounts = g_list_concat (accounts, empathy_import_pidgin_load ()); + have_accounts = empathy_import_accounts_to_import (); - /* Check if we have accounts to import before creating the window */ - if (!accounts) + if (!have_accounts) { - GtkWidget *message; - - if (warning) + if (priv->show_warning) { - message = gtk_message_dialog_new (parent, - GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, - _("No accounts to import could be found. Empathy currently only " - "supports importing accounts from Pidgin.")); - - gtk_dialog_run (GTK_DIALOG (message)); - gtk_widget_destroy (message); + import_dialog_show_warning_message (self); } else DEBUG ("No accounts to import; closing dialog silently."); - - return; + } + else + { + import_dialog_add_import_widget (self); } - /* We have accounts, let's display the window with them */ - dialog = g_slice_new0 (EmpathyImportDialog); - dialog->accounts = accounts; - - filename = empathy_file_lookup ("empathy-import-dialog.ui", "src"); - gui = empathy_builder_get_file (filename, - "import_dialog", &dialog->window, - "treeview", &dialog->treeview, - NULL); - - empathy_builder_connect (gui, dialog, - "import_dialog", "destroy", import_dialog_destroy_cb, - "import_dialog", "response", import_dialog_response_cb, - NULL); - - g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog); + if (priv->parent_window) + gtk_window_set_transient_for (GTK_WINDOW (self), priv->parent_window); +} - g_free (filename); - g_object_unref (gui); +static void +empathy_import_dialog_init (EmpathyImportDialog *self) +{ + EmpathyImportDialogPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + EMPATHY_TYPE_IMPORT_DIALOG, EmpathyImportDialogPriv); - if (parent) - gtk_window_set_transient_for (GTK_WINDOW (dialog->window), parent); + self->priv = priv; - import_dialog_set_up_account_list (dialog); + gtk_container_set_border_width (GTK_CONTAINER (self), 5); + gtk_window_set_title (GTK_WINDOW (self), _("Import Accounts")); + gtk_window_set_modal (GTK_WINDOW (self), TRUE); + gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE); +} - gtk_widget_show (dialog->window); +static void +empathy_import_dialog_class_init (EmpathyImportDialogClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GtkDialogClass *gtkclass = GTK_DIALOG_CLASS (klass); + GParamSpec *param_spec; + + oclass->constructed = do_constructed; + oclass->get_property = do_get_property; + oclass->set_property = do_set_property; + + gtkclass->response = impl_signal_response; + + param_spec = g_param_spec_object ("parent-window", + "parent-window", "The parent window", + GTK_TYPE_WINDOW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_PARENT, param_spec); + + param_spec = g_param_spec_boolean ("show-warning", + "show-warning", "Whether a warning should be shown when there are no " + "sources for importing accounts.", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_SHOW_WARNING, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyImportDialogPriv)); } +GtkWidget * +empathy_import_dialog_new (GtkWindow *parent, + gboolean warning) +{ + return g_object_new (EMPATHY_TYPE_IMPORT_DIALOG, "parent-window", + parent, "show-warning", warning, NULL); +} diff --git a/src/empathy-import-dialog.h b/src/empathy-import-dialog.h index 0e3fd148f..0e9d225c4 100644 --- a/src/empathy-import-dialog.h +++ b/src/empathy-import-dialog.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008-2009 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 @@ -17,30 +17,46 @@ * Boston, MA 02110-1301 USA * * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> */ #include <gtk/gtk.h> -#include <libmissioncontrol/mc-profile.h> #ifndef __EMPATHY_IMPORT_DIALOG_H__ #define __EMPATHY_IMPORT_DIALOG_H__ G_BEGIN_DECLS -typedef struct -{ - /* Table mapping CM param string to a GValue */ - GHashTable *settings; - /* The profile to use for this account */ - McProfile *profile; - /* The name of the account import source */ - gchar *source; -} EmpathyImportAccountData; - -EmpathyImportAccountData *empathy_import_account_data_new (const gchar *source); -void empathy_import_account_data_free (EmpathyImportAccountData *data); -gboolean empathy_import_dialog_accounts_to_import (void); -void empathy_import_dialog_show (GtkWindow *parent, gboolean warning); +#define EMPATHY_TYPE_IMPORT_DIALOG empathy_import_dialog_get_type() +#define EMPATHY_IMPORT_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_IMPORT_DIALOG,\ + EmpathyImportDialog)) +#define EMPATHY_IMPORT_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_IMPORT_DIALOG,\ + EmpathyImportDialogClass)) +#define EMPATHY_IS_IMPORT_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_IMPORT_DIALOG)) +#define EMPATHY_IS_IMPORT_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_IMPORT_DIALOG)) +#define EMPATHY_IMPORT_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_IMPORT_DIALOG,\ + EmpathyImportDialogClass)) + +typedef struct { + GtkDialog parent; + + /* private */ + gpointer priv; +} EmpathyImportDialog; + +typedef struct { + GtkDialogClass parent_class; +} EmpathyImportDialogClass; + +GType empathy_import_dialog_get_type (void); + +GtkWidget* empathy_import_dialog_new (GtkWindow *parent_window, + gboolean show_warning); G_END_DECLS diff --git a/src/empathy-import-dialog.ui b/src/empathy-import-dialog.ui index 38ba434e4..ce7a56a74 100644 --- a/src/empathy-import-dialog.ui +++ b/src/empathy-import-dialog.ui @@ -1,73 +1,29 @@ <?xml version="1.0"?> -<!--Generated with glade3 3.4.5 on Fri Oct 17 11:01:30 2008 --> <interface> - <object class="GtkDialog" id="import_dialog"> - <property name="border_width">5</property> - <property name="title" translatable="yes">Import Accounts</property> - <property name="modal">True</property> - <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> - <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> - <property name="has_separator">False</property> - <child internal-child="vbox"> - <object class="GtkVBox" id="dialog-vbox1"> + <!-- interface-requires gtk+ 2.12 --> + <!-- interface-naming-policy toplevel-contextual --> + <object class="GtkVBox" id="widget_vbox"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <object class="GtkScrolledWindow" id="scrolledwindow17"> <property name="visible">True</property> - <property name="spacing">2</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">never</property> + <property name="vscrollbar_policy">automatic</property> + <property name="shadow_type">in</property> <child> - <object class="GtkScrolledWindow" id="scrolledwindow17"> + <object class="GtkTreeView" id="treeview"> + <property name="height_request">200</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> - <object class="GtkTreeView" id="treeview"> - <property name="height_request">200</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="enable_search">False</property> - </object> - </child> + <property name="enable_search">False</property> </object> - <packing> - <property name="position">1</property> - </packing> - </child> - <child internal-child="action_area"> - <object class="GtkHButtonBox" id="dialog-action_area1"> - <property name="visible">True</property> - <property name="layout_style">GTK_BUTTONBOX_END</property> - <child> - <object class="GtkButton" id="button_cancel"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label">gtk-cancel</property> - <property name="use_stock">True</property> - </object> - </child> - <child> - <object class="GtkButton" id="button_ok"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="label">gtk-ok</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="pack_type">GTK_PACK_END</property> - </packing> </child> </object> + <packing> + <property name="position">1</property> + </packing> </child> - <action-widgets> - <action-widget response="0">button_cancel</action-widget> - <action-widget response="-5">button_ok</action-widget> - </action-widgets> </object> </interface> diff --git a/src/empathy-import-mc4-accounts.c b/src/empathy-import-mc4-accounts.c new file mode 100644 index 000000000..968293bd2 --- /dev/null +++ b/src/empathy-import-mc4-accounts.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2009 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: Arnaud Maillet <arnaud.maillet@collabora.co.uk> + */ + +#include <stdio.h> +#include <string.h> +#include <glib.h> +#include <glib/gi18n.h> +#include <gconf/gconf-client.h> +#include <telepathy-glib/util.h> +#include <telepathy-glib/defs.h> +#include <dbus/dbus-protocol.h> +#include <gnome-keyring.h> +#include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-account-settings.h> +#include <libempathy/empathy-connection-managers.h> + +#include "empathy-import-mc4-accounts.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_IMPORT_MC4_ACCOUNTS +#include <libempathy/empathy-debug.h> + +#define MC_ACCOUNTS_GCONF_BASE "/apps/telepathy/mc/accounts" +#define IMPORTED_MC4_ACCOUNTS "/apps/empathy/accounts/imported_mc4_accounts" + +typedef struct +{ + gchar *profile; + gchar *protocol; +} ProfileProtocolMapItem; + +static ProfileProtocolMapItem profile_protocol_map[] = +{ + { "ekiga", "sip" }, + { "fwd", "sip" }, + { "gtalk", "jabber" }, + { "msn-haze", "msn" }, + { "salut", "local-xmpp" }, + { "sipphone", "sip" }, + { "sofiasip", "sip" }, +}; + +typedef struct { + gchar *account_name; + gboolean enable; +} Misc; + +static gchar * +_account_name_from_key (const gchar *key) +{ + guint base_len = strlen (MC_ACCOUNTS_GCONF_BASE); + const gchar *base, *slash; + + g_assert (g_str_has_prefix (key, MC_ACCOUNTS_GCONF_BASE)); + g_assert (strlen (key) > base_len + 1); + + base = key + base_len + 1; + slash = strchr (base, '/'); + + if (slash == NULL) + return g_strdup (base); + else + return g_strndup (base, slash - base); +} + +static gchar * +_param_name_from_key (const gchar *key) +{ + const gchar *base, *slash; + gchar *account_name; + gchar *ret; + + account_name = _account_name_from_key (key); + base = strstr (key, account_name); + slash = strchr (base, '/'); + + ret = g_strdup (slash+1); + g_free (account_name); + + return ret; +} + +static gchar * +_create_default_display_name (const gchar *protocol) +{ + if (!tp_strdiff (protocol, "local-xmpp")) + return g_strdup (_("People Nearby")); + + return g_strdup_printf (_("%s account"), protocol); +} + +static const gchar * +_get_manager_for_protocol (EmpathyConnectionManagers *managers, + const gchar *protocol) +{ + GList *cms = empathy_connection_managers_get_cms (managers); + GList *l; + TpConnectionManager *haze = NULL; + TpConnectionManager *cm = NULL; + + for (l = cms; l; l = l->next) + { + TpConnectionManager *tp_cm = l->data; + + /* Only use haze if no other cm provides this protocol */ + if (!tp_strdiff (tp_connection_manager_get_name (tp_cm), "haze")) + { + haze = tp_cm; + continue; + } + + if (tp_connection_manager_has_protocol (tp_cm, protocol)) + { + cm = tp_cm; + goto out; + } + } + + if (haze != NULL && tp_connection_manager_has_protocol (haze, protocol)) + return tp_connection_manager_get_name (haze); + +out: + return cm != NULL ? tp_connection_manager_get_name (cm) : NULL; +} + +static void +_move_contents (const gchar *old, const gchar *new) +{ + GDir *source; + const gchar *f; + int ret; + + ret = g_mkdir_with_parents (new, 0777); + if (ret == -1) + return; + + source = g_dir_open (old, 0, NULL); + if (source == NULL) + return; + + while ((f = g_dir_read_name (source)) != NULL) + { + gchar *old_path; + gchar *new_path; + + old_path = g_build_path (G_DIR_SEPARATOR_S, old, f, NULL); + new_path = g_build_path (G_DIR_SEPARATOR_S, new, f, NULL); + + if (g_file_test (old_path, G_FILE_TEST_IS_DIR)) + { + _move_contents (old_path, new_path); + } + else + { + GFile *f_old, *f_new; + + f_old = g_file_new_for_path (old_path); + f_new = g_file_new_for_path (new_path); + + g_file_move (f_old, f_new, G_FILE_COPY_NONE, + NULL, NULL, NULL, NULL); + + g_object_unref (f_old); + g_object_unref (f_new); + } + + g_free (old_path); + g_free (new_path); + } + + g_dir_close (source); +} + +static void +_move_logs (EmpathyAccount *account, const gchar *account_name) +{ + gchar *old_path, *new_path, *escaped; + const gchar *name; + + name = empathy_account_get_unique_name (account); + if (g_str_has_prefix (name, TP_ACCOUNT_OBJECT_PATH_BASE)) + name += strlen (TP_ACCOUNT_OBJECT_PATH_BASE); + + escaped = g_strdelimit (g_strdup (name), "/", '_'); + new_path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), + PACKAGE_NAME, "logs", escaped, NULL); + g_free (escaped); + + old_path = g_build_path (G_DIR_SEPARATOR_S, + g_get_home_dir (), + ".gnome2", PACKAGE_NAME, "logs", account_name, NULL); + + _move_contents (old_path, new_path); +} + +static void +_create_account_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccount *account; + GError *error = NULL; + Misc *misc = (Misc *) user_data; + + if (!empathy_account_settings_apply_finish ( + EMPATHY_ACCOUNT_SETTINGS (source), result, &error)) + { + DEBUG ("Failed to create account: %s", error->message); + g_error_free (error); + goto out; + } + + DEBUG ("account created\n"); + account = empathy_account_settings_get_account ( + EMPATHY_ACCOUNT_SETTINGS (source)); + + _move_logs (account, misc->account_name); + + empathy_account_set_enabled_async (account, + misc->enable, NULL, NULL); + + g_free (misc->account_name); + g_slice_free (Misc, misc); + +out: + g_object_unref (source); +} + +static gchar * +_get_protocol_from_profile (const gchar *profile) +{ + gint i; + + DEBUG ("profile: %s\n", profile); + + for (i = 0; i < G_N_ELEMENTS (profile_protocol_map); i++) + if (!tp_strdiff (profile, profile_protocol_map[i].profile)) + return g_strdup (profile_protocol_map[i].protocol); + + return g_strdup (profile); +} + +static void +_set_password_from_keyring (EmpathyAccountSettings *settings, + const gchar *account_name, const gchar *key) +{ + GnomeKeyringResult res; + gchar *password; + GnomeKeyringPasswordSchema keyring_schema = { + GNOME_KEYRING_ITEM_GENERIC_SECRET, + { + { "account", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { "param", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING }, + { NULL, 0 } + } + }; + + res = gnome_keyring_find_password_sync (&keyring_schema, + &password, + "account", account_name, + "param", key, + NULL); + + if (res == GNOME_KEYRING_RESULT_OK) + { + empathy_account_settings_set_string (settings, key, password); + gnome_keyring_free_password (password); + } +} + +static void +_handle_entry (EmpathyAccountSettings *settings, const gchar *account_name, + const gchar *key, + GConfEntry *entry) +{ + const gchar *signature; + + signature = empathy_account_settings_get_dbus_signature (settings, key); + if (signature == NULL) + { + DEBUG ("Parameter %s is unknown", signature); + return; + } + + switch ((int)*signature) + { + case DBUS_TYPE_INT16: + case DBUS_TYPE_INT32: + { + gint v = gconf_value_get_int (gconf_entry_get_value (entry)); + empathy_account_settings_set_int32 (settings, key, v); + break; + } + case DBUS_TYPE_UINT16: + case DBUS_TYPE_UINT32: + { + gint v = gconf_value_get_int (gconf_entry_get_value (entry)); + empathy_account_settings_set_uint32 (settings, key, v); + break; + } + case DBUS_TYPE_STRING: + { + const gchar *v = gconf_value_get_string ( + gconf_entry_get_value (entry)); + + /* MC 4 would put password in the keyring and leave the password in + * gconf keyring */ + + if (!tp_strdiff (key, "password") && !tp_strdiff (v, "keyring")) + _set_password_from_keyring (settings, account_name, key); + else + empathy_account_settings_set_string (settings, key, v); + break; + } + case DBUS_TYPE_BOOLEAN: + { + gboolean v = gconf_value_get_bool ( + gconf_entry_get_value (entry)); + + empathy_account_settings_set_boolean (settings, key, v); + break; + } + default: + DEBUG ("Unsupported type in signature: %s", signature); + } +} + +static void +_recurse_account (GSList *entries, EmpathyAccountSettings *settings, + const gchar *account_name) +{ + GSList *tmp; + + for (tmp = entries; tmp != NULL; tmp = tmp->next) + { + + GConfEntry *entry; + gchar *param; + + entry = (GConfEntry *) tmp->data; + param = _param_name_from_key (gconf_entry_get_key (entry)); + + if (g_str_has_prefix (param, "param-")) + { + _handle_entry (settings, account_name, param + strlen ("param-"), + entry); + } + + g_free (param); + gconf_entry_unref (entry); + } +} + +static gboolean +import_one_account (const char *path, + EmpathyConnectionManagers *managers, + GConfClient *client) +{ + gchar *account_name = _account_name_from_key (path); + EmpathyAccountSettings *settings; + GError *error = NULL; + GSList *entries = NULL; + gchar *profile = NULL; + gchar *protocol = NULL; + const gchar *manager; + gchar *display_name; + gchar *key; + gboolean enabled = FALSE; + gboolean ret = FALSE; + Misc *misc; + + DEBUG ("Starting import of %s (%s)", path, account_name); + + key = g_strdup_printf ("%s/profile", path); + profile = gconf_client_get_string (client, key, NULL); + g_free (key); + + if (profile == NULL) + { + DEBUG ("Account is missing a profile entry\n"); + goto failed; + } + + protocol = _get_protocol_from_profile (profile); + manager = _get_manager_for_protocol (managers, protocol); + if (manager == NULL) + { + DEBUG ("No manager available for this protocol %s", protocol); + goto failed; + } + + key = g_strdup_printf ("%s/display_name", path); + display_name = gconf_client_get_string (client, key, NULL); + g_free (key); + + if (display_name == NULL) + display_name = _create_default_display_name (protocol); + + settings = empathy_account_settings_new (manager, protocol, display_name); + g_free (display_name); + + /* Bit of a hack, as we know EmpathyConnectionManagers is ready the + * EmpathyAccountSettings should be ready right away as well */ + g_assert (empathy_account_settings_is_ready (settings)); + + entries = gconf_client_all_entries (client, path, &error); + + if (entries == NULL) + { + DEBUG ("Failed to get all entries: %s\n", error->message); + g_error_free (error); + goto failed; + } + + _recurse_account (entries, settings, account_name); + + key = g_strdup_printf ("%s/enabled", path); + enabled = gconf_client_get_bool (client, key, NULL); + g_free (key); + + misc = g_slice_new (Misc); + misc->account_name = account_name; + misc->enable = enabled; + + empathy_account_settings_apply_async (settings, + _create_account_cb, misc); + ret = TRUE; + +out: + g_free (protocol); + g_free (profile); + g_slist_free (entries); + + return ret; + +failed: + DEBUG ("Failed to import %s", path); + g_free (account_name); + if (settings != NULL) + g_object_unref (settings); + goto out; +} + +gboolean +empathy_import_mc4_has_imported (void) +{ + GConfClient *client; + gboolean ret; + + client = gconf_client_get_default (); + + ret = gconf_client_get_bool (client, IMPORTED_MC4_ACCOUNTS, NULL); + g_object_unref (client); + + return ret; +} + +gboolean +empathy_import_mc4_accounts (EmpathyConnectionManagers *managers) +{ + GConfClient *client; + GError *error = NULL; + GSList *dir, *dirs = NULL; + gboolean imported_mc4_accounts; + gboolean imported = FALSE; + + g_return_val_if_fail (empathy_connection_managers_is_ready (managers), + FALSE); + + client = gconf_client_get_default (); + + imported_mc4_accounts = gconf_client_get_bool (client, + IMPORTED_MC4_ACCOUNTS, &error); + + if (error != NULL) + { + DEBUG ("Failed to get import_mc4_accounts key: %s\n", error->message); + g_error_free (error); + goto out; + } + + if (imported_mc4_accounts) + { + DEBUG ("Mc4 accounts previously imported"); + goto out; + } + + DEBUG ("MC 4 accounts are going to be imported\n"); + + dirs = gconf_client_all_dirs (client, MC_ACCOUNTS_GCONF_BASE, &error); + + if (error != NULL) + { + DEBUG ("Failed to get MC4 account dirs: %s\n", + error->message); + g_clear_error (&error); + g_object_unref (client); + goto out; + } + + for (dir = dirs; NULL != dir; dir = dir->next) + { + if (import_one_account ((gchar *) dir->data, managers, client)) + imported = TRUE; + g_free (dir->data); + } + +out: + gconf_client_set_bool (client, IMPORTED_MC4_ACCOUNTS, TRUE, NULL); + + g_slist_free (dirs); + g_object_unref (client); + return imported; +} diff --git a/src/empathy-import-mc4-accounts.h b/src/empathy-import-mc4-accounts.h new file mode 100644 index 000000000..0a30fdff7 --- /dev/null +++ b/src/empathy-import-mc4-accounts.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2009 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: Arnaud Maillet <arnaud.maillet@collabora.co.uk> + */ + +#ifndef __EMPATHY_IMPORT_MC4_ACCOUNTS_H__ +#define __EMPATHY_IMPORT_MC4_ACCOUNTS_H__ + +G_BEGIN_DECLS + +#include <libempathy/empathy-connection-managers.h> + +gboolean empathy_import_mc4_accounts (EmpathyConnectionManagers *managers); +gboolean empathy_import_mc4_has_imported (void); + +G_END_DECLS + +#endif /* __EMPATHY_IMPORT_MC4_ACCOUNTS_H__ */ diff --git a/src/empathy-import-pidgin.c b/src/empathy-import-pidgin.c index 935c022ea..23b1d84f5 100644 --- a/src/empathy-import-pidgin.c +++ b/src/empathy-import-pidgin.c @@ -22,6 +22,7 @@ #include <config.h> #include <string.h> +#include <unistd.h> #include <glib.h> #include <glib/gstdio.h> @@ -31,7 +32,7 @@ #include <telepathy-glib/util.h> #include <telepathy-glib/dbus.h> -#include "empathy-import-dialog.h" +#include "empathy-import-utils.h" #include "empathy-import-pidgin.h" #define DEBUG_FLAG EMPATHY_DEBUG_OTHER @@ -114,8 +115,7 @@ import_dialog_pidgin_parse_setting (EmpathyImportAccountData *data, /* Search for the map corresponding to setting we are parsing */ for (i = 0; i < G_N_ELEMENTS (pidgin_cm_map); i++) { - if (!tp_strdiff (mc_profile_get_protocol_name (data->profile), - pidgin_cm_map[i].protocol) && + if (!tp_strdiff (data->protocol, pidgin_cm_map[i].protocol) && !tp_strdiff (tag_name, pidgin_cm_map[i].pidgin_name)) { item = pidgin_cm_map + i; @@ -199,23 +199,26 @@ empathy_import_pidgin_load (void) if (!tp_strdiff ((gchar *) child->name, PIDGIN_ACCOUNT_TAG_PROTOCOL)) { - gchar *content; + xmlChar *content; const gchar *protocol; - protocol = content = (gchar *) xmlNodeGetContent (child); + content = xmlNodeGetContent (child); + + protocol = (const gchar *) content; if (g_str_has_prefix (protocol, "prpl-")) protocol += 5; if (!tp_strdiff (protocol, PIDGIN_PROTOCOL_BONJOUR)) - protocol = "salut"; + data->protocol = g_strdup ("salut"); else if (!tp_strdiff (protocol, PIDGIN_PROTOCOL_NOVELL)) - protocol = "groupwise"; + data->protocol = g_strdup ("groupwise"); + else + data->protocol = g_strdup (protocol); - data->profile = mc_profile_lookup (protocol); - g_free (content); + xmlFree (content); - if (data->profile == NULL) + if (data->protocol == NULL) break; } @@ -240,8 +243,7 @@ empathy_import_pidgin_load (void) username = name; /* Split "username@server" if it is an IRC account */ - if (strstr (name, "@") && !tp_strdiff ( - mc_profile_get_protocol_name (data->profile), "irc")) + if (strstr (name, "@") && !tp_strdiff (data->protocol, "irc")) { nick_server = g_strsplit (name, "@", 2); username = nick_server[0]; @@ -287,12 +289,11 @@ empathy_import_pidgin_load (void) /* If we have the needed settings, add the account data to the list, * otherwise free the data */ - if (data->profile != NULL && g_hash_table_size (data->settings) > 0) + if (data->protocol != NULL && g_hash_table_size (data->settings) > 0) { /* Special-case XMPP: * http://bugzilla.gnome.org/show_bug.cgi?id=579992 */ - if (!tp_strdiff ( - mc_profile_get_protocol_name (data->profile), "jabber")) + if (!tp_strdiff (data->protocol, "jabber")) { if (EMP_STR_EMPTY (tp_asv_get_string (data->settings, "server"))) { diff --git a/src/empathy-import-utils.c b/src/empathy-import-utils.c new file mode 100644 index 000000000..f84b20609 --- /dev/null +++ b/src/empathy-import-utils.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 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: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +#include <telepathy-glib/util.h> + +#include <libempathy/empathy-utils.h> + +#include "empathy-import-utils.h" +#include "empathy-import-pidgin.h" + +EmpathyImportAccountData * +empathy_import_account_data_new (const gchar *source) +{ + EmpathyImportAccountData *data; + + g_return_val_if_fail (!EMP_STR_EMPTY (source), NULL); + + data = g_slice_new0 (EmpathyImportAccountData); + data->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, + (GDestroyNotify) tp_g_value_slice_free); + data->source = g_strdup (source); + data->protocol = NULL; + data->connection_manager = NULL; + + return data; +} + +void +empathy_import_account_data_free (EmpathyImportAccountData *data) +{ + if (data == NULL) + return; + if (data->protocol != NULL) + g_free (data->protocol); + if (data->connection_manager != NULL) + g_free (data->connection_manager); + if (data->settings != NULL) + g_hash_table_destroy (data->settings); + if (data->source != NULL) + g_free (data->source); + + g_slice_free (EmpathyImportAccountData, data); +} + +gboolean +empathy_import_accounts_to_import (void) +{ + return empathy_import_pidgin_accounts_to_import (); +} + +GList * +empathy_import_accounts_load (EmpathyImportApplication id) +{ + if (id == EMPATHY_IMPORT_APPLICATION_PIDGIN) + return empathy_import_pidgin_load (); + + return empathy_import_pidgin_load (); +} diff --git a/src/empathy-import-utils.h b/src/empathy-import-utils.h new file mode 100644 index 000000000..8c971a04d --- /dev/null +++ b/src/empathy-import-utils.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2009 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: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +#ifndef __EMPATHY_IMPORT_UTILS_H__ +#define __EMPATHY_IMPORT_UTILS_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +typedef struct +{ + /* Table mapping CM param string to a GValue */ + GHashTable *settings; + /* Protocol name */ + gchar *protocol; + /* Connection manager name */ + gchar *connection_manager; + /* The name of the account import source */ + gchar *source; +} EmpathyImportAccountData; + +typedef enum { + EMPATHY_IMPORT_APPLICATION_ALL = 0, + EMPATHY_IMPORT_APPLICATION_PIDGIN, + EMPATHY_IMPORT_APPLICATION_INVALID +} EmpathyImportApplication; + +EmpathyImportAccountData *empathy_import_account_data_new ( + const gchar *source); +void empathy_import_account_data_free (EmpathyImportAccountData *data); + +gboolean empathy_import_accounts_to_import (void); +GList *empathy_import_accounts_load (EmpathyImportApplication id); + +G_END_DECLS + +#endif /* __EMPATHY_IMPORT_UTILS_H__ */ diff --git a/src/empathy-import-widget.c b/src/empathy-import-widget.c new file mode 100644 index 000000000..17f196229 --- /dev/null +++ b/src/empathy-import-widget.c @@ -0,0 +1,516 @@ +/* + * Copyright (C) 2008-2009 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-import-widget.c */ + +#include "empathy-import-dialog.h" +#include "empathy-import-widget.h" +#include "empathy-import-pidgin.h" + +#define DEBUG_FLAG EMPATHY_DEBUG_OTHER +#include <libempathy/empathy-debug.h> +#include <libempathy/empathy-account.h> +#include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-connection-managers.h> +#include <libempathy/empathy-utils.h> + +#include <libempathy-gtk/empathy-ui-utils.h> + +#include <telepathy-glib/util.h> + +#include <glib/gi18n.h> + +G_DEFINE_TYPE (EmpathyImportWidget, empathy_import_widget, G_TYPE_OBJECT) + +#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyImportWidget) + +enum +{ + COL_IMPORT = 0, + COL_PROTOCOL, + COL_NAME, + COL_SOURCE, + COL_ACCOUNT_DATA, + COL_COUNT +}; + +enum { + PROP_APPLICATION_ID = 1 +}; + +typedef struct { + GtkWidget *vbox; + GtkWidget *treeview; + + GList *accounts; + EmpathyImportApplication app_id; + + EmpathyConnectionManagers *cms; + + gboolean dispose_run; +} EmpathyImportWidgetPriv; + +static gboolean +import_widget_account_id_in_list (GList *accounts, + const gchar *account_id) +{ + GList *l; + + for (l = accounts; l; l = l->next) + { + EmpathyAccount *account = l->data; + const gchar *account_string; + GValue *value; + gboolean result; + const GHashTable *parameters; + + parameters = empathy_account_get_parameters (account); + + value = g_hash_table_lookup ((GHashTable *) parameters, "account"); + + if (value == NULL) + continue; + + account_string = g_value_get_string (value); + + result = tp_strdiff (account_string, account_id); + + if (!result) + return TRUE; + } + + return FALSE; +} + +static gboolean +protocol_is_supported (EmpathyImportWidget *self, + EmpathyImportAccountData *data) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + GList *cms = empathy_connection_managers_get_cms (priv->cms); + GList *l; + gboolean proto_is_supported = FALSE; + + for (l = cms; l; l = l->next) + { + TpConnectionManager *tp_cm = l->data; + const gchar *cm_name = tp_connection_manager_get_name (tp_cm); + if (tp_connection_manager_has_protocol (tp_cm, + (const gchar*) data->protocol)) + { + data->connection_manager = g_strdup (cm_name); + proto_is_supported = TRUE; + break; + } + } + + return proto_is_supported; +} + +static void +import_widget_add_accounts_to_model (EmpathyImportWidget *self) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GList *l; + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + EmpathyAccountManager *manager = empathy_account_manager_dup_singleton (); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + for (l = priv->accounts; l; l = l->next) + { + GValue *value; + EmpathyImportAccountData *data = l->data; + gboolean import; + GList *accounts; + + if (!protocol_is_supported (self, data)) + continue; + + value = g_hash_table_lookup (data->settings, "account"); + + accounts = empathy_account_manager_dup_accounts (manager); + + /* Only set the "Import" cell to be active if there isn't already an + * account set up with the same account id. */ + import = !import_widget_account_id_in_list (accounts, + g_value_get_string (value)); + + g_list_foreach (accounts, (GFunc) g_object_unref, NULL); + g_list_free (accounts); + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_IMPORT, import, + COL_PROTOCOL, data->protocol, + COL_NAME, g_value_get_string (value), + COL_SOURCE, data->source, + COL_ACCOUNT_DATA, data, + -1); + } + + g_object_unref (manager); +} + +static void +import_widget_create_account_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + EmpathyAccount *account; + GError *error = NULL; + EmpathyImportWidget *self = user_data; + + account = empathy_account_manager_create_account_finish ( + EMPATHY_ACCOUNT_MANAGER (source), result, &error); + + if (account == NULL) + { + DEBUG ("Failed to create account: %s", + error ? error->message : "No error given"); + g_clear_error (&error); + return; + } + + DEBUG ("account created\n"); + + g_object_unref (self); +} + +static void +import_widget_add_account (EmpathyImportWidget *self, + EmpathyImportAccountData *data) +{ + EmpathyAccountManager *account_manager; + gchar *display_name; + GHashTable *properties; + GValue *username; + + account_manager = empathy_account_manager_dup_singleton (); + + DEBUG ("connection_manager: %s\n", data->connection_manager); + + /* Set the display name of the account */ + username = g_hash_table_lookup (data->settings, "account"); + display_name = g_strdup_printf ("%s (%s)", + data->protocol, + g_value_get_string (username)); + + DEBUG ("display name: %s\n", display_name); + + properties = g_hash_table_new (NULL, NULL); + + empathy_account_manager_create_account_async (account_manager, + (const gchar*) data->connection_manager, data->protocol, display_name, + data->settings, properties, import_widget_create_account_cb, + g_object_ref (self)); + + g_hash_table_unref (properties); + g_free (display_name); + g_object_unref (account_manager); +} + +static gboolean +import_widget_tree_model_foreach (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer user_data) +{ + gboolean to_import; + EmpathyImportAccountData *data; + EmpathyImportWidget *self = user_data; + + gtk_tree_model_get (model, iter, + COL_IMPORT, &to_import, + COL_ACCOUNT_DATA, &data, + -1); + + if (to_import) + import_widget_add_account (self, data); + + return FALSE; +} + +static void +import_widget_cell_toggled_cb (GtkCellRendererToggle *cell_renderer, + const gchar *path_str, + EmpathyImportWidget *self) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + + path = gtk_tree_path_new_from_string (path_str); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + + gtk_tree_model_get_iter (model, &iter, path); + + gtk_list_store_set (GTK_LIST_STORE (model), &iter, + COL_IMPORT, !gtk_cell_renderer_toggle_get_active (cell_renderer), + -1); + + gtk_tree_path_free (path); +} + +static void +import_widget_set_up_account_list (EmpathyImportWidget *self) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + GtkListStore *store; + GtkTreeView *view; + GtkTreeViewColumn *column; + GtkCellRenderer *cell; + + store = gtk_list_store_new (COL_COUNT, G_TYPE_BOOLEAN, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), + GTK_TREE_MODEL (store)); + + g_object_unref (store); + + view = GTK_TREE_VIEW (priv->treeview); + gtk_tree_view_set_headers_visible (view, TRUE); + + /* Import column */ + cell = gtk_cell_renderer_toggle_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + /* Translators: this is the header of a treeview column */ + _("Import"), cell, + "active", COL_IMPORT, + NULL); + + g_signal_connect (cell, "toggled", + G_CALLBACK (import_widget_cell_toggled_cb), self); + + /* Protocol column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Protocol")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", FALSE, NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_PROTOCOL); + + /* Account column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Account")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", FALSE, NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_NAME); + + if (priv->app_id == EMPATHY_IMPORT_APPLICATION_ALL) + { + /* Source column */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, _("Source")); + gtk_tree_view_column_set_expand (column, TRUE); + gtk_tree_view_append_column (view, column); + + cell = gtk_cell_renderer_text_new (); + g_object_set (cell, "editable", FALSE, NULL); + gtk_tree_view_column_pack_start (column, cell, TRUE); + gtk_tree_view_column_add_attribute (column, cell, "text", COL_SOURCE); + } + + import_widget_add_accounts_to_model (self); +} + +static void +import_widget_cms_ready_cb (EmpathyConnectionManagers *cms, + GParamSpec *pspec, + EmpathyImportWidget *self) +{ + if (empathy_connection_managers_is_ready (cms)) + import_widget_set_up_account_list (self); +} + +static void +import_widget_destroy_cb (GtkWidget *w, + EmpathyImportWidget *self) +{ + g_object_unref (self); +} + +static void +do_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_APPLICATION_ID: + g_value_set_int (value, priv->app_id); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_APPLICATION_ID: + priv->app_id = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +do_finalize (GObject *obj) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (obj); + + g_list_foreach (priv->accounts, (GFunc) empathy_import_account_data_free, + NULL); + g_list_free (priv->accounts); + + if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize != NULL) + G_OBJECT_CLASS (empathy_import_widget_parent_class)->finalize (obj); +} + +static void +do_dispose (GObject *obj) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (obj); + + if (priv->dispose_run) + return; + + priv->dispose_run = TRUE; + + if (priv->cms != NULL) + { + g_object_unref (priv->cms); + priv->cms = NULL; + } + + if (G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose != NULL) + G_OBJECT_CLASS (empathy_import_widget_parent_class)->dispose (obj); +} + +static void +do_constructed (GObject *obj) +{ + EmpathyImportWidget *self = EMPATHY_IMPORT_WIDGET (obj); + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + GtkBuilder *gui; + gchar *filename; + + priv->accounts = empathy_import_accounts_load (priv->app_id); + + filename = empathy_file_lookup ("empathy-import-dialog.ui", "src"); + gui = empathy_builder_get_file (filename, + "widget_vbox", &priv->vbox, + "treeview", &priv->treeview, + NULL); + + g_free (filename); + empathy_builder_unref_and_keep_widget (gui, priv->vbox); + + g_signal_connect (priv->vbox, "destroy", + G_CALLBACK (import_widget_destroy_cb), self); + + if (empathy_connection_managers_is_ready (priv->cms)) + import_widget_set_up_account_list (self); + else + g_signal_connect (priv->cms, "notify::ready", + G_CALLBACK (import_widget_cms_ready_cb), self); +} + +static void +empathy_import_widget_class_init (EmpathyImportWidgetClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + GParamSpec *param_spec; + + oclass->constructed = do_constructed; + oclass->finalize = do_finalize; + oclass->dispose = do_dispose; + oclass->set_property = do_set_property; + oclass->get_property = do_get_property; + + param_spec = g_param_spec_int ("application-id", + "application-id", "The application id to import from", + 0, EMPATHY_IMPORT_APPLICATION_INVALID, EMPATHY_IMPORT_APPLICATION_ALL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (oclass, PROP_APPLICATION_ID, param_spec); + + g_type_class_add_private (klass, sizeof (EmpathyImportWidgetPriv)); +} + +static void +empathy_import_widget_init (EmpathyImportWidget *self) +{ + EmpathyImportWidgetPriv *priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, EMPATHY_TYPE_IMPORT_WIDGET, + EmpathyImportWidgetPriv); + + self->priv = priv; + + priv->cms = empathy_connection_managers_dup_singleton (); +} + +EmpathyImportWidget * +empathy_import_widget_new (EmpathyImportApplication id) +{ + return g_object_new (EMPATHY_TYPE_IMPORT_WIDGET, "application-id", id, NULL); +} + +GtkWidget * +empathy_import_widget_get_widget (EmpathyImportWidget *self) +{ + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + + return priv->vbox; +} + +void +empathy_import_widget_add_selected_accounts (EmpathyImportWidget *self) +{ + GtkTreeModel *model; + EmpathyImportWidgetPriv *priv = GET_PRIV (self); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->treeview)); + gtk_tree_model_foreach (model, import_widget_tree_model_foreach, self); +} diff --git a/src/empathy-import-widget.h b/src/empathy-import-widget.h new file mode 100644 index 000000000..48f2e1d48 --- /dev/null +++ b/src/empathy-import-widget.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2009 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * Authors: Jonny Lamb <jonny.lamb@collabora.co.uk> + * Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> + */ + +/* empathy-import-widget.h */ + +#ifndef __EMPATHY_IMPORT_WIDGET_H__ +#define __EMPATHY_IMPORT_WIDGET_H__ + +#include <glib-object.h> + +#include "empathy-import-utils.h" + +G_BEGIN_DECLS + +#define EMPATHY_TYPE_IMPORT_WIDGET empathy_import_widget_get_type() +#define EMPATHY_IMPORT_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), EMPATHY_TYPE_IMPORT_WIDGET,\ + EmpathyImportWidget)) +#define EMPATHY_IMPORT_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), EMPATHY_TYPE_IMPORT_WIDGET,\ + EmpathyImportWidgetClass)) +#define EMPATHY_IS_IMPORT_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EMPATHY_TYPE_IMPORT_WIDGET)) +#define EMPATHY_IS_IMPORT_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), EMPATHY_TYPE_IMPORT_WIDGET)) +#define EMPATHY_IMPORT_WIDGET_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_IMPORT_WIDGET,\ + EmpathyImportWidgetClass)) + +typedef struct { + GObject parent; + + /* private */ + gpointer priv; +} EmpathyImportWidget; + +typedef struct { + GObjectClass parent_class; +} EmpathyImportWidgetClass; + +GType empathy_import_widget_get_type (void); + +EmpathyImportWidget* empathy_import_widget_new (EmpathyImportApplication id); + +GtkWidget * empathy_import_widget_get_widget (EmpathyImportWidget *self); + +void empathy_import_widget_add_selected_accounts (EmpathyImportWidget *self); + +G_END_DECLS + +#endif /* __EMPATHY_IMPORT_WIDGET_H__ */ diff --git a/src/empathy-main-window.c b/src/empathy-main-window.c index a600fd429..d61a05c27 100644 --- a/src/empathy-main-window.c +++ b/src/empathy-main-window.c @@ -49,8 +49,6 @@ #include <libempathy-gtk/empathy-sound.h> #include <libempathy-gtk/empathy-ui-utils.h> -#include <libmissioncontrol/mission-control.h> - #include "empathy-accounts-dialog.h" #include "empathy-main-window.h" #include "ephy-spinner.h" @@ -81,7 +79,6 @@ typedef struct { EmpathyContactListView *list_view; EmpathyContactListStore *list_store; - MissionControl *mc; EmpathyAccountManager *account_manager; EmpathyChatroomManager *chatroom_manager; EmpathyEventManager *event_manager; @@ -654,7 +651,6 @@ main_window_destroy_cb (GtkWidget *widget, g_list_free (window->actions_connected); - g_object_unref (window->mc); g_object_unref (window->account_manager); g_object_unref (window->list_store); g_hash_table_destroy (window->errors); @@ -1252,15 +1248,14 @@ empathy_main_window_show (void) gtk_action_set_visible (show_map_widget, FALSE); #endif - window->mc = empathy_mission_control_dup_singleton (); window->account_manager = empathy_account_manager_dup_singleton (); g_signal_connect (window->account_manager, "account-connection-changed", G_CALLBACK (main_window_connection_changed_cb), window); - window->errors = g_hash_table_new_full (empathy_account_hash, - empathy_account_equal, + window->errors = g_hash_table_new_full (g_direct_hash, + g_direct_equal, g_object_unref, NULL); @@ -1409,6 +1404,8 @@ empathy_main_window_show (void) main_window_update_status (window, window->account_manager); + gtk_widget_show (window->window); + return window->window; } diff --git a/src/empathy-new-chatroom-dialog.c b/src/empathy-new-chatroom-dialog.c index e16da91a7..219be371d 100644 --- a/src/empathy-new-chatroom-dialog.c +++ b/src/empathy-new-chatroom-dialog.c @@ -32,9 +32,6 @@ #include <glib/gi18n.h> #include <glib/gprintf.h> -#include <libmissioncontrol/mission-control.h> -#include <libmissioncontrol/mc-profile.h> - #include <libempathy/empathy-tp-roomlist.h> #include <libempathy/empathy-chatroom.h> #include <libempathy/empathy-utils.h> @@ -358,14 +355,16 @@ new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog) { EmpathyAccountChooser *account_chooser; EmpathyAccount *account; - McProfile *profile; const gchar *protocol; const gchar *room; account_chooser = EMPATHY_ACCOUNT_CHOOSER (dialog->account_chooser); account = empathy_account_chooser_dup_account (account_chooser); - profile = empathy_account_get_profile (account); - protocol = mc_profile_get_protocol_name (profile); + + if (account == NULL) + return; + + protocol = empathy_account_get_protocol (account); gtk_entry_set_text (GTK_ENTRY (dialog->entry_server), ""); @@ -390,7 +389,6 @@ new_chatroom_dialog_update_widgets (EmpathyNewChatroomDialog *dialog) gtk_widget_grab_focus (dialog->entry_room); g_object_unref (account); - g_object_unref (profile); } static void diff --git a/src/empathy-status-icon.c b/src/empathy-status-icon.c index bbb97f410..430c93343 100644 --- a/src/empathy-status-icon.c +++ b/src/empathy-status-icon.c @@ -314,24 +314,7 @@ status_icon_set_visibility (EmpathyStatusIcon *icon, if (!visible) { empathy_window_iconify (priv->window, priv->icon); } else { - GList *accounts; - GList *l; - gboolean one_enabled = FALSE; - empathy_window_present (GTK_WINDOW (priv->window), TRUE); - - /* Show the accounts dialog if there is no enabled accounts */ - accounts = empathy_account_manager_dup_accounts (priv->account_manager); - for (l = accounts ; l != NULL ; l = g_list_next (l)) { - one_enabled = empathy_account_is_enabled (EMPATHY_ACCOUNT (l->data)) - || one_enabled; - g_object_unref (l->data); - } - g_list_free (accounts); - if (!one_enabled) { - DEBUG ("No enabled account, Showing account dialog"); - empathy_accounts_dialog_show (GTK_WINDOW (priv->window), NULL); - } } } diff --git a/src/empathy-tube-dispatch.c b/src/empathy-tube-dispatch.c index 67db5a3a3..66efa217d 100644 --- a/src/empathy-tube-dispatch.c +++ b/src/empathy-tube-dispatch.c @@ -25,6 +25,7 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> #include <telepathy-glib/proxy-subclass.h> +#include <telepathy-glib/interfaces.h> #include <gtk/gtk.h> #include <glib/gi18n.h> diff --git a/src/empathy.c b/src/empathy.c index 660e47cea..38fd56c54 100644 --- a/src/empathy.c +++ b/src/empathy.c @@ -1,6 +1,5 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Copyright (C) 2007-2008 Collabora Ltd. + * Copyright (C) 2007-2009 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 @@ -30,6 +29,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> #include <gdk/gdkx.h> +#include <unique/unique.h> #if HAVE_LIBCHAMPLAIN #include <clutter-gtk/clutter-gtk.h> @@ -40,14 +40,17 @@ #include <telepathy-glib/dbus.h> #include <telepathy-glib/util.h> -#include <libmissioncontrol/mission-control.h> +#include <telepathy-glib/connection-manager.h> +#include <telepathy-glib/interfaces.h> #include <libempathy/empathy-idle.h> #include <libempathy/empathy-utils.h> #include <libempathy/empathy-call-factory.h> #include <libempathy/empathy-chatroom-manager.h> +#include <libempathy/empathy-account-settings.h> #include <libempathy/empathy-connectivity.h> #include <libempathy/empathy-account-manager.h> +#include <libempathy/empathy-connection-managers.h> #include <libempathy/empathy-debugger.h> #include <libempathy/empathy-dispatcher.h> #include <libempathy/empathy-dispatch-operation.h> @@ -60,13 +63,14 @@ #include <libempathy-gtk/empathy-ui-utils.h> #include <libempathy-gtk/empathy-location-manager.h> +#include "empathy-account-assistant.h" #include "empathy-accounts-dialog.h" #include "empathy-main-window.h" #include "empathy-status-icon.h" #include "empathy-call-window.h" #include "empathy-chat-window.h" #include "empathy-ft-manager.h" -#include "bacon-message-connection.h" +#include "empathy-import-mc4-accounts.h" #include "extensions/extensions.h" @@ -75,444 +79,432 @@ #include <gst/gst.h> -static BaconMessageConnection *connection = NULL; +#define COMMAND_ACCOUNTS_DIALOG 1 static void dispatch_cb (EmpathyDispatcher *dispatcher, - EmpathyDispatchOperation *operation, - gpointer user_data) + EmpathyDispatchOperation *operation, + gpointer user_data) { - GQuark channel_type; - - channel_type = empathy_dispatch_operation_get_channel_type_id (operation); - - if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) { - EmpathyTpChat *tp_chat; - EmpathyChat *chat = NULL; - const gchar *id; - - tp_chat = EMPATHY_TP_CHAT ( - empathy_dispatch_operation_get_channel_wrapper (operation)); - - id = empathy_tp_chat_get_id (tp_chat); - if (!id) { - EmpathyContact *contact; - - contact = empathy_tp_chat_get_remote_contact (tp_chat); - if (contact) { - id = empathy_contact_get_id (contact); - } - } - - if (id) { - EmpathyAccountManager *manager; - TpConnection *connection; - EmpathyAccount *account; - - manager = empathy_account_manager_dup_singleton (); - connection = empathy_tp_chat_get_connection (tp_chat); - account = empathy_account_manager_get_account (manager, - connection); - chat = empathy_chat_window_find_chat (account, id); - g_object_unref (manager); - } - - if (chat) { - empathy_chat_set_tp_chat (chat, tp_chat); - } else { - chat = empathy_chat_new (tp_chat); - } - - empathy_chat_window_present_chat (chat); - - empathy_dispatch_operation_claim (operation); - } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) { - EmpathyCallFactory *factory; - - factory = empathy_call_factory_get (); - empathy_call_factory_claim_channel (factory, operation); - } else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER) { - EmpathyFTFactory *factory; - - factory = empathy_ft_factory_dup_singleton (); - - /* if the operation is not incoming, don't claim it, - * as it might have been triggered by another client, and - * we are observing it. - */ - if (empathy_dispatch_operation_is_incoming (operation)) { - empathy_ft_factory_claim_channel (factory, operation); - } - } + GQuark channel_type; + + channel_type = empathy_dispatch_operation_get_channel_type_id (operation); + + if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT) + { + EmpathyTpChat *tp_chat; + EmpathyChat *chat = NULL; + const gchar *id; + + tp_chat = EMPATHY_TP_CHAT + (empathy_dispatch_operation_get_channel_wrapper (operation)); + + id = empathy_tp_chat_get_id (tp_chat); + if (!id) + { + EmpathyContact *contact; + + contact = empathy_tp_chat_get_remote_contact (tp_chat); + if (contact) + id = empathy_contact_get_id (contact); + } + + if (id) + { + EmpathyAccountManager *manager; + TpConnection *connection; + EmpathyAccount *account; + + manager = empathy_account_manager_dup_singleton (); + connection = empathy_tp_chat_get_connection (tp_chat); + account = empathy_account_manager_get_account_for_connection ( + manager, connection); + chat = empathy_chat_window_find_chat (account, id); + g_object_unref (manager); + } + + if (chat) + empathy_chat_set_tp_chat (chat, tp_chat); + else + chat = empathy_chat_new (tp_chat); + + empathy_chat_window_present_chat (chat); + + empathy_dispatch_operation_claim (operation); + } + else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA) + { + EmpathyCallFactory *factory; + + factory = empathy_call_factory_get (); + empathy_call_factory_claim_channel (factory, operation); + } + else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER) + { + EmpathyFTFactory *factory; + + factory = empathy_ft_factory_dup_singleton (); + + /* if the operation is not incoming, don't claim it, + * as it might have been triggered by another client, and + * we are observing it. + */ + if (empathy_dispatch_operation_is_incoming (operation)) + empathy_ft_factory_claim_channel (factory, operation); + } } -static void -service_ended_cb (MissionControl *mc, - gpointer user_data) +/* Salut account creation */ +static gboolean +should_create_salut_account (void) { - DEBUG ("Mission Control stopped"); + EmpathyAccountManager *manager; + gboolean salut_created = FALSE; + GList *accounts, *l; + + /* Check if we already created a salut account */ + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, + &salut_created); + + if (salut_created) + { + DEBUG ("Gconf says we already created a salut account once"); + return FALSE; + } + + manager = empathy_account_manager_dup_singleton (); + accounts = empathy_account_manager_dup_accounts (manager); + + for (l = accounts; l != NULL; l = g_list_next (l)) + { + EmpathyAccount *account = EMPATHY_ACCOUNT (l->data); + + if (!tp_strdiff (empathy_account_get_protocol (account), "local-xmpp")) + salut_created = TRUE; + + g_object_unref (account); + } + + g_object_unref (manager); + + if (salut_created) + { + DEBUG ("Existing salut account already exists, flagging so in gconf"); + empathy_conf_set_bool (empathy_conf_get (), + EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, + TRUE); + } + + return !salut_created; } static void -operation_error_cb (MissionControl *mc, - guint operation_id, - guint error_code, - gpointer user_data) +salut_account_created (GObject *source, + GAsyncResult *result, + gpointer user_data) { - const gchar *message; - - switch (error_code) { - case MC_DISCONNECTED_ERROR: - message = "Disconnected"; - break; - case MC_INVALID_HANDLE_ERROR: - message = "Invalid handle"; - break; - case MC_NO_MATCHING_CONNECTION_ERROR: - message = "No matching connection"; - break; - case MC_INVALID_ACCOUNT_ERROR: - message = "Invalid account"; - break; - case MC_PRESENCE_FAILURE_ERROR: - message = "Presence failure"; - break; - case MC_NO_ACCOUNTS_ERROR: - message = "No accounts"; - break; - case MC_NETWORK_ERROR: - message = "Network error"; - break; - case MC_CONTACT_DOES_NOT_SUPPORT_VOICE_ERROR: - message = "Contact does not support voice"; - break; - case MC_LOWMEM_ERROR: - message = "Lowmem"; - break; - case MC_CHANNEL_REQUEST_GENERIC_ERROR: - message = "Channel request generic error"; - break; - case MC_CHANNEL_BANNED_ERROR: - message = "Channel banned"; - break; - case MC_CHANNEL_FULL_ERROR: - message = "Channel full"; - break; - case MC_CHANNEL_INVITE_ONLY_ERROR: - message = "Channel invite only"; - break; - default: - message = "Unknown error code"; - } - - DEBUG ("Error during operation %d: %s", operation_id, message); + EmpathyAccountSettings *settings = EMPATHY_ACCOUNT_SETTINGS (source); + EmpathyAccount *account; + GError *error = NULL; + + if (!empathy_account_settings_apply_finish (settings, result, &error)) + { + DEBUG ("Failed to create salut account: %s", error->message); + g_error_free (error); + return; + } + + account = empathy_account_settings_get_account (settings); + + empathy_account_set_enabled_async (account, TRUE, NULL, NULL); + empathy_conf_set_bool (empathy_conf_get (), + EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, + TRUE); } static void use_conn_notify_cb (EmpathyConf *conf, - const gchar *key, - gpointer user_data) + const gchar *key, + gpointer user_data) { - EmpathyConnectivity *connectivity = user_data; - gboolean use_conn; + EmpathyConnectivity *connectivity = user_data; + gboolean use_conn; - if (empathy_conf_get_bool (conf, key, &use_conn)) { - empathy_connectivity_set_use_conn (connectivity, use_conn); - } + if (empathy_conf_get_bool (conf, key, &use_conn)) + { + empathy_connectivity_set_use_conn (connectivity, use_conn); + } } static void -create_salut_account (void) +create_salut_account_if_needed (EmpathyConnectionManagers *managers) { - McProfile *profile; - McProtocol *protocol; - gboolean salut_created = FALSE; - EmpathyAccount *account; - EmpathyAccountManager *account_manager; - GList *accounts; - EBook *book; - EContact *contact; - gchar *nickname = NULL; - gchar *first_name = NULL; - gchar *last_name = NULL; - gchar *email = NULL; - gchar *jid = NULL; - GError *error = NULL; - - /* Check if we already created a salut account */ - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, - &salut_created); - if (salut_created) { - return; - } - - DEBUG ("Try to add a salut account..."); - - /* Check if the salut CM is installed */ - profile = mc_profile_lookup ("salut"); - if (!profile) { - DEBUG ("No salut profile"); - return; - } - protocol = mc_profile_get_protocol (profile); - if (!protocol) { - DEBUG ("Salut not installed"); - g_object_unref (profile); - return; - } - g_object_unref (protocol); - - /* Get self EContact from EDS */ - if (!e_book_get_self (&contact, &book, &error)) { - DEBUG ("Failed to get self econtact: %s", - error ? error->message : "No error given"); - g_clear_error (&error); - g_object_unref (profile); - return; - } - - empathy_conf_set_bool (empathy_conf_get (), - EMPATHY_PREFS_SALUT_ACCOUNT_CREATED, - TRUE); - - /* Check if there is already a salut account */ - accounts = mc_accounts_list_by_profile (profile); - if (accounts) { - DEBUG ("There is already a salut account"); - mc_accounts_list_free (accounts); - g_object_unref (profile); - return; - } - - account_manager = empathy_account_manager_dup_singleton (); - account = empathy_account_manager_create (account_manager, profile); - empathy_account_set_display_name (account, _("People nearby")); - g_object_unref (account_manager); - - nickname = e_contact_get (contact, E_CONTACT_NICKNAME); - first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); - last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME); - email = e_contact_get (contact, E_CONTACT_EMAIL_1); - jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1); - - if (!tp_strdiff (nickname, "nickname")) { - g_free (nickname); - nickname = NULL; - } - - DEBUG ("Salut account created:\nnickname=%s\nfirst-name=%s\n" - "last-name=%s\nemail=%s\njid=%s\n", - nickname, first_name, last_name, email, jid); - - empathy_account_set_param_string (account, "nickname", nickname ? nickname : ""); - empathy_account_set_param_string (account, "first-name", first_name ? first_name : ""); - empathy_account_set_param_string (account, "last-name", last_name ? last_name : ""); - empathy_account_set_param_string (account, "email", email ? email : ""); - empathy_account_set_param_string (account, "jid", jid ? jid : ""); - - g_free (nickname); - g_free (first_name); - g_free (last_name); - g_free (email); - g_free (jid); - g_object_unref (account); - g_object_unref (profile); - g_object_unref (contact); - g_object_unref (book); + EmpathyAccountSettings *settings; + TpConnectionManager *manager; + const TpConnectionManagerProtocol *protocol; + EBook *book; + EContact *contact; + gchar *nickname = NULL; + gchar *first_name = NULL; + gchar *last_name = NULL; + gchar *email = NULL; + gchar *jid = NULL; + GError *error = NULL; + + + if (!should_create_salut_account ()) + return; + + manager = empathy_connection_managers_get_cm (managers, "salut"); + if (manager == NULL) + { + DEBUG ("Salut not installed, not making a salut account"); + return; + } + + protocol = tp_connection_manager_get_protocol (manager, "local-xmpp"); + if (protocol == NULL) + { + DEBUG ("Salut doesn't support local-xmpp!!"); + return; + } + + DEBUG ("Trying to add a salut account..."); + + /* Get self EContact from EDS */ + if (!e_book_get_self (&contact, &book, &error)) + { + DEBUG ("Failed to get self econtact: %s", + error ? error->message : "No error given"); + g_clear_error (&error); + return; + } + + settings = empathy_account_settings_new ("salut", "local-xmpp", + _("People nearby")); + + nickname = e_contact_get (contact, E_CONTACT_NICKNAME); + first_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME); + last_name = e_contact_get (contact, E_CONTACT_FAMILY_NAME); + email = e_contact_get (contact, E_CONTACT_EMAIL_1); + jid = e_contact_get (contact, E_CONTACT_IM_JABBER_HOME_1); + + if (!tp_strdiff (nickname, "nickname")) + { + g_free (nickname); + nickname = NULL; + } + + DEBUG ("Salut account created:\nnickname=%s\nfirst-name=%s\n" + "last-name=%s\nemail=%s\njid=%s\n", + nickname, first_name, last_name, email, jid); + + empathy_account_settings_set_string (settings, + "nickname", nickname ? nickname : ""); + empathy_account_settings_set_string (settings, + "first-name", first_name ? first_name : ""); + empathy_account_settings_set_string (settings, + "last-name", last_name ? last_name : ""); + empathy_account_settings_set_string (settings, "email", email ? email : ""); + empathy_account_settings_set_string (settings, "jid", jid ? jid : ""); + + empathy_account_settings_apply_async (settings, + salut_account_created, NULL); + + g_free (nickname); + g_free (first_name); + g_free (last_name); + g_free (email); + g_free (jid); + g_object_unref (settings); + g_object_unref (contact); + g_object_unref (book); } static void -migrate_config_to_xdg_dir (void) +maybe_show_account_assistant (void) { - gchar *xdg_dir, *old_dir, *xdg_filename, *old_filename; - int i; - GFile *xdg_file, *old_file; - static const gchar* filenames[] = { - "geometry.ini", - "irc-networks.xml", - "chatrooms.xml", - "contact-groups.xml", - "status-presets.xml", - "accels.txt", - NULL - }; - - xdg_dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); - if (g_file_test (xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - /* xdg config dir already exists */ - g_free (xdg_dir); - return; - } - - old_dir = g_build_filename (g_get_home_dir (), ".gnome2", PACKAGE_NAME, NULL); - if (!g_file_test (old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - /* old config dir didn't exist */ - g_free (xdg_dir); - g_free (old_dir); - return; - } - - if (g_mkdir_with_parents (xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR)) == -1) { - DEBUG ("Failed to create configuration directory; aborting migration"); - g_free (xdg_dir); - g_free (old_dir); - return; - } - - for (i = 0; filenames[i]; i++) { - old_filename = g_build_filename (old_dir, filenames[i], NULL); - if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) { - g_free (old_filename); - continue; - } - xdg_filename = g_build_filename (xdg_dir, filenames[i], NULL); - old_file = g_file_new_for_path (old_filename); - xdg_file = g_file_new_for_path (xdg_filename); - if (!g_file_move (old_file, xdg_file, G_FILE_COPY_NONE, - NULL, NULL, NULL, NULL)) { - DEBUG ("Failed to migrate %s", filenames[i]); - } - g_free (old_filename); - g_free (xdg_filename); - g_object_unref (old_file); - g_object_unref (xdg_file); - } - - g_free (xdg_dir); - g_free (old_dir); + EmpathyAccountManager *manager; + manager = empathy_account_manager_dup_singleton (); + + if (empathy_account_manager_get_count (manager) == 0) + { + GtkWidget * assistant = empathy_account_assistant_new ( + GTK_WINDOW (empathy_main_window_get ())); + gtk_window_present (GTK_WINDOW (assistant)); + } } -/* The code that handles single-instance and startup notification is - * copied from gedit. - * - * Copyright (C) 2005 - Paolo Maggi - */ -static void -on_bacon_message_received (const char *message, - gpointer data) +static gboolean +check_connection_managers_ready (EmpathyConnectionManagers *managers) { - GtkWidget *window = data; - guint32 startup_timestamp; - - g_return_if_fail (message != NULL); - - DEBUG ("Other instance launched, presenting the main window. message='%s'", - message); - - if (strcmp (message, "accounts") == 0) { - /* accounts dialog requested */ - empathy_accounts_dialog_show (GTK_WINDOW (window), NULL); - } else { - startup_timestamp = atoi (message); - - /* Set the proper interaction time on the window. - * Fall back to roundtripping to the X server when we - * don't have the timestamp, e.g. when launched from - * terminal. We also need to make sure that the window - * has been realized otherwise it will not work. lame. */ - if (startup_timestamp == 0) { - /* Work if launched from the terminal */ - DEBUG ("Using X server timestamp as a fallback"); - - if (!GTK_WIDGET_REALIZED (window)) { - gtk_widget_realize (GTK_WIDGET (window)); - } - - startup_timestamp = gdk_x11_get_server_time (gtk_widget_get_window (window)); - } - - gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp); - } + if (empathy_connection_managers_is_ready (managers)) + { + if (!empathy_import_mc4_accounts (managers)) + maybe_show_account_assistant (); + + create_salut_account_if_needed (managers); + g_object_unref (managers); + managers = NULL; + return TRUE; + } + return FALSE; } -static guint32 -get_startup_timestamp () +static void +connection_managers_ready_cb (EmpathyConnectionManagers *managers, + GParamSpec *spec, + gpointer user_data) { - const gchar *startup_id_env; - gchar *startup_id = NULL; - gchar *time_str; - gchar *end; - gulong retval = 0; - - /* we don't unset the env, since startup-notification - * may still need it */ - startup_id_env = g_getenv ("DESKTOP_STARTUP_ID"); - if (startup_id_env == NULL) { - goto out; - } - - startup_id = g_strdup (startup_id_env); - - time_str = g_strrstr (startup_id, "_TIME"); - if (time_str == NULL) { - goto out; - } - - errno = 0; - - /* Skip past the "_TIME" part */ - time_str += 5; - - retval = strtoul (time_str, &end, 0); - if (end == time_str || errno != 0) - retval = 0; + check_connection_managers_ready (managers); +} - out: - g_free (startup_id); +static void +migrate_config_to_xdg_dir (void) +{ + gchar *xdg_dir, *old_dir, *xdg_filename, *old_filename; + int i; + GFile *xdg_file, *old_file; + static const gchar* filenames[] = { + "geometry.ini", + "irc-networks.xml", + "chatrooms.xml", + "contact-groups.xml", + "status-presets.xml", + "accels.txt", + NULL + }; + + xdg_dir = g_build_filename (g_get_user_config_dir (), PACKAGE_NAME, NULL); + if (g_file_test (xdg_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + { + /* xdg config dir already exists */ + g_free (xdg_dir); + return; + } + + old_dir = g_build_filename (g_get_home_dir (), ".gnome2", + PACKAGE_NAME, NULL); + if (!g_file_test (old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) + { + /* old config dir didn't exist */ + g_free (xdg_dir); + g_free (old_dir); + return; + } + + if (g_mkdir_with_parents (xdg_dir, (S_IRUSR | S_IWUSR | S_IXUSR)) == -1) + { + DEBUG ("Failed to create configuration directory; aborting migration"); + g_free (xdg_dir); + g_free (old_dir); + return; + } + + for (i = 0; filenames[i]; i++) + { + old_filename = g_build_filename (old_dir, filenames[i], NULL); + if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) + { + g_free (old_filename); + continue; + } + xdg_filename = g_build_filename (xdg_dir, filenames[i], NULL); + old_file = g_file_new_for_path (old_filename); + xdg_file = g_file_new_for_path (xdg_filename); + + if (!g_file_move (old_file, xdg_file, G_FILE_COPY_NONE, + NULL, NULL, NULL, NULL)) + DEBUG ("Failed to migrate %s", filenames[i]); + + g_free (old_filename); + g_free (xdg_filename); + g_object_unref (old_file); + g_object_unref (xdg_file); + } + + g_free (xdg_dir); + g_free (old_dir); +} - return (retval > 0) ? retval : 0; +static UniqueResponse +unique_app_message_cb (UniqueApp *unique_app, + gint command, + UniqueMessageData *data, + guint timestamp, + gpointer user_data) +{ + GtkWidget *window = user_data; + + DEBUG ("Other instance launched, presenting the main window. " + "Command=%d, timestamp %u", command, timestamp); + + if (command == COMMAND_ACCOUNTS_DIALOG) + { + empathy_accounts_dialog_show (GTK_WINDOW (window), NULL); + } + else + { + gtk_window_set_screen (GTK_WINDOW (window), + unique_message_data_get_screen (data)); + gtk_window_set_startup_id (GTK_WINDOW (window), + unique_message_data_get_startup_id (data)); + gtk_window_present_with_time (GTK_WINDOW (window), timestamp); + } + + return UNIQUE_RESPONSE_OK; } static gboolean show_version_cb (const char *option_name, - const char *value, - gpointer data, - GError **error) + const char *value, + gpointer data, + GError **error) { - g_print ("%s\n", PACKAGE_STRING); + g_print ("%s\n", PACKAGE_STRING); - exit (EXIT_SUCCESS); + exit (EXIT_SUCCESS); - return FALSE; + return FALSE; } static void new_incoming_transfer_cb (EmpathyFTFactory *factory, - EmpathyFTHandler *handler, - GError *error, - gpointer user_data) + EmpathyFTHandler *handler, + GError *error, + gpointer user_data) { - if (error) { - empathy_ft_manager_display_error (handler, error); - } else { - empathy_receive_file_with_file_chooser (handler); - } + if (error) + empathy_ft_manager_display_error (handler, error); + else + empathy_receive_file_with_file_chooser (handler); } static void new_ft_handler_cb (EmpathyFTFactory *factory, - EmpathyFTHandler *handler, - GError *error, - gpointer user_data) + EmpathyFTHandler *handler, + GError *error, + gpointer user_data) { - if (error) { - empathy_ft_manager_display_error (handler, error); - } else { - empathy_ft_manager_add_handler (handler); - } + if (error) + empathy_ft_manager_display_error (handler, error); + else + empathy_ft_manager_add_handler (handler); - g_object_unref (handler); + g_object_unref (handler); } static void -new_call_handler_cb (EmpathyCallFactory *factory, EmpathyCallHandler *handler, - gboolean outgoing, gpointer user_data) +new_call_handler_cb (EmpathyCallFactory *factory, + EmpathyCallHandler *handler, + gboolean outgoing, + gpointer user_data) { - EmpathyCallWindow *window; + EmpathyCallWindow *window; - window = empathy_call_window_new (handler); - gtk_widget_show (GTK_WIDGET (window)); + window = empathy_call_window_new (handler); + gtk_widget_show (GTK_WIDGET (window)); } #ifdef ENABLE_DEBUG @@ -522,249 +514,246 @@ default_log_handler (const gchar *log_domain, const gchar *message, gpointer user_data) { - g_log_default_handler (log_domain, log_level, message, NULL); - - /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the - * debugger as they already have in empathy_debug. */ - if (log_level != G_LOG_LEVEL_DEBUG - || tp_strdiff (log_domain, G_LOG_DOMAIN)) { - EmpathyDebugger *dbg; - GTimeVal now; - - dbg = empathy_debugger_get_singleton (); - g_get_current_time (&now); - - empathy_debugger_add_message (dbg, &now, log_domain, - log_level, message); - } + g_log_default_handler (log_domain, log_level, message, NULL); + + /* G_LOG_DOMAIN = "empathy". No need to send empathy messages to the + * debugger as they already have in empathy_debug. */ + if (log_level != G_LOG_LEVEL_DEBUG + || tp_strdiff (log_domain, G_LOG_DOMAIN)) + { + EmpathyDebugger *dbg; + GTimeVal now; + + dbg = empathy_debugger_get_singleton (); + g_get_current_time (&now); + + empathy_debugger_add_message (dbg, &now, log_domain, + log_level, message); + } } #endif /* ENABLE_DEBUG */ +static void +account_manager_ready_cb (EmpathyAccountManager *manager, + GParamSpec *spec, + gpointer user_data) +{ + if (!empathy_account_manager_is_ready (manager)) + return; + + if (should_create_salut_account () || !empathy_import_mc4_has_imported ()) + { + EmpathyConnectionManagers *managers; + managers = empathy_connection_managers_dup_singleton (); + + if (!check_connection_managers_ready (managers)) + { + g_signal_connect (managers, "notify::ready", + G_CALLBACK (connection_managers_ready_cb), NULL); + } + } + else + { + maybe_show_account_assistant (); + } +} + int main (int argc, char *argv[]) { - guint32 startup_timestamp; #if HAVE_GEOCLUE - EmpathyLocationManager *location_manager = NULL; + EmpathyLocationManager *location_manager = NULL; #endif - EmpathyStatusIcon *icon; - EmpathyDispatcher *dispatcher; - EmpathyLogManager *log_manager; - EmpathyChatroomManager *chatroom_manager; - EmpathyCallFactory *call_factory; - EmpathyFTFactory *ft_factory; - GtkWidget *window; - MissionControl *mc; - EmpathyIdle *idle; - EmpathyConnectivity *connectivity; - gboolean autoconnect = TRUE; - gboolean no_connect = FALSE; - gboolean hide_contact_list = FALSE; - gboolean accounts_dialog = FALSE; - GError *error = NULL; - TpDBusDaemon *dbus_daemon; - GOptionEntry options[] = { - { "no-connect", 'n', - 0, G_OPTION_ARG_NONE, &no_connect, - N_("Don't connect on startup"), - NULL }, - { "hide-contact-list", 'h', - 0, G_OPTION_ARG_NONE, &hide_contact_list, - N_("Don't show the contact list on startup"), - NULL }, - { "accounts", 'a', - 0, G_OPTION_ARG_NONE, &accounts_dialog, - N_("Show the accounts dialog"), - NULL }, - { "version", 'v', - G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, NULL, NULL }, - { NULL } - }; - - /* Init */ - g_thread_init (NULL); - empathy_init (); - - if (!gtk_init_with_args (&argc, &argv, - N_("- Empathy IM Client"), - options, GETTEXT_PACKAGE, &error)) { - g_warning ("Error in empathy init: %s", error->message); - return EXIT_FAILURE; - } - - empathy_gtk_init (); - g_set_application_name (_(PACKAGE_NAME)); - g_setenv ("PULSE_PROP_media.role", "phone", TRUE); - - gst_init (&argc, &argv); + EmpathyStatusIcon *icon; + EmpathyDispatcher *dispatcher; + EmpathyAccountManager *account_manager; + EmpathyLogManager *log_manager; + EmpathyChatroomManager *chatroom_manager; + EmpathyCallFactory *call_factory; + EmpathyFTFactory *ft_factory; + GtkWidget *window; + EmpathyIdle *idle; + EmpathyConnectivity *connectivity; + gboolean autoconnect = TRUE; + gboolean no_connect = FALSE; + gboolean hide_contact_list = FALSE; + gboolean accounts_dialog = FALSE; + GError *error = NULL; + TpDBusDaemon *dbus_daemon; + UniqueApp *unique_app; + + GOptionEntry options[] = { + { "no-connect", 'n', + 0, G_OPTION_ARG_NONE, &no_connect, + N_("Don't connect on startup"), + NULL }, + { "hide-contact-list", 'h', + 0, G_OPTION_ARG_NONE, &hide_contact_list, + N_("Don't show the contact list on startup"), + NULL }, + { "accounts", 'a', + 0, G_OPTION_ARG_NONE, &accounts_dialog, + N_("Show the accounts dialog"), + NULL }, + { "version", 'v', + G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_cb, + NULL, NULL }, + { NULL } + }; + + /* Init */ + g_thread_init (NULL); + empathy_init (); + + if (!gtk_init_with_args (&argc, &argv, N_("- Empathy IM Client"), + options, GETTEXT_PACKAGE, &error)) + { + g_warning ("Error in empathy init: %s", error->message); + return EXIT_FAILURE; + } + + empathy_gtk_init (); + g_set_application_name (_(PACKAGE_NAME)); + g_setenv ("PULSE_PROP_media.role", "phone", TRUE); + + gst_init (&argc, &argv); #if HAVE_LIBCHAMPLAIN - gtk_clutter_init (&argc, &argv); + gtk_clutter_init (&argc, &argv); #endif - gtk_window_set_default_icon_name ("empathy"); - textdomain (GETTEXT_PACKAGE); + gtk_window_set_default_icon_name ("empathy"); + textdomain (GETTEXT_PACKAGE); #ifdef ENABLE_DEBUG - /* Set up debugger */ - g_log_set_default_handler (default_log_handler, NULL); + /* Set up debugger */ + g_log_set_default_handler (default_log_handler, NULL); #endif - /* Setting up the bacon connection */ - startup_timestamp = get_startup_timestamp (); - connection = bacon_message_connection_new ("empathy"); - if (connection != NULL) { - if (!bacon_message_connection_get_is_server (connection)) { - gchar *message; - - if (accounts_dialog) { - DEBUG ("Showing accounts dialog from existing Empathy instance"); - - message = g_strdup ("accounts"); - - } else { - - DEBUG ("Activating existing instance"); - - message = g_strdup_printf ("%" G_GUINT32_FORMAT, - startup_timestamp); - } - - bacon_message_connection_send (connection, message); - - /* We never popup a window, so tell startup-notification - * that we are done. */ - gdk_notify_startup_complete (); - - g_free (message); - bacon_message_connection_free (connection); - - return EXIT_SUCCESS; - } - } else { - g_warning ("Cannot create the 'empathy' bacon connection."); - } - - /* Take well-known name */ - dbus_daemon = tp_dbus_daemon_dup (&error); - if (error == NULL) { - if (!tp_dbus_daemon_request_name (dbus_daemon, - "org.gnome.Empathy", - TRUE, &error)) { - DEBUG ("Failed to request well-known name: %s", - error ? error->message : "no message"); - g_clear_error (&error); - } - g_object_unref (dbus_daemon); - } else { - DEBUG ("Failed to dup dbus daemon: %s", - error ? error->message : "no message"); - g_clear_error (&error); - } - - /* Setting up MC */ - mc = empathy_mission_control_dup_singleton (); - g_signal_connect (mc, "ServiceEnded", - G_CALLBACK (service_ended_cb), - NULL); - g_signal_connect (mc, "Error", - G_CALLBACK (operation_error_cb), - NULL); - - if (accounts_dialog) { - GtkWidget *dialog; - - dialog = empathy_accounts_dialog_show (NULL, NULL); - g_signal_connect (dialog, "destroy", - G_CALLBACK (gtk_main_quit), - NULL); - - gtk_main (); - return 0; - } - - /* Setting up Idle */ - idle = empathy_idle_dup_singleton (); - empathy_idle_set_auto_away (idle, TRUE); - - /* Setting up Connectivity */ - connectivity = empathy_connectivity_dup_singleton (); - use_conn_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, - connectivity); - empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, - use_conn_notify_cb, connectivity); - - /* Autoconnect */ - empathy_conf_get_bool (empathy_conf_get (), - EMPATHY_PREFS_AUTOCONNECT, - &autoconnect); - if (autoconnect && ! no_connect && - tp_connection_presence_type_cmp_availability (empathy_idle_get_state - (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) <= 0) { - empathy_idle_set_state (idle, MC_PRESENCE_AVAILABLE); - } - - - migrate_config_to_xdg_dir (); - create_salut_account (); - - /* Setting up UI */ - window = empathy_main_window_show (); - icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list); - - if (connection) { - /* We se the callback here because we need window */ - bacon_message_connection_set_callback (connection, - on_bacon_message_received, - window); - } - - /* Handle channels */ - dispatcher = empathy_dispatcher_dup_singleton (); - g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL); - - /* Logging */ - log_manager = empathy_log_manager_dup_singleton (); - empathy_log_manager_observe (log_manager, dispatcher); - - chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL); - empathy_chatroom_manager_observe (chatroom_manager, dispatcher); - - notify_init (_(PACKAGE_NAME)); - /* Create the call factory */ - call_factory = empathy_call_factory_initialise (); - g_signal_connect (G_OBJECT (call_factory), "new-call-handler", - G_CALLBACK (new_call_handler_cb), NULL); - /* Create the FT factory */ - ft_factory = empathy_ft_factory_dup_singleton (); - g_signal_connect (ft_factory, "new-ft-handler", - G_CALLBACK (new_ft_handler_cb), NULL); - g_signal_connect (ft_factory, "new-incoming-transfer", - G_CALLBACK (new_incoming_transfer_cb), NULL); - - /* Location mananger */ + unique_app = unique_app_new_with_commands ("org.gnome.Empathy", + NULL, "accounts_dialog", COMMAND_ACCOUNTS_DIALOG, NULL); + + if (unique_app_is_running (unique_app)) + { + unique_app_send_message (unique_app, accounts_dialog ? + COMMAND_ACCOUNTS_DIALOG : UNIQUE_ACTIVATE, NULL); + + g_object_unref (unique_app); + return EXIT_SUCCESS; + } + + /* Take well-known name */ + dbus_daemon = tp_dbus_daemon_dup (&error); + if (error == NULL) + { + if (!tp_dbus_daemon_request_name (dbus_daemon, + "org.gnome.Empathy", TRUE, &error)) + { + DEBUG ("Failed to request well-known name: %s", + error ? error->message : "no message"); + g_clear_error (&error); + } + g_object_unref (dbus_daemon); + } + else + { + DEBUG ("Failed to dup dbus daemon: %s", + error ? error->message : "no message"); + g_clear_error (&error); + } + + if (accounts_dialog) + { + GtkWidget *dialog; + + dialog = empathy_accounts_dialog_show (NULL, NULL); + g_signal_connect (dialog, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_main (); + return 0; + } + + /* Setting up Idle */ + idle = empathy_idle_dup_singleton (); + empathy_idle_set_auto_away (idle, TRUE); + + /* Setting up Connectivity */ + connectivity = empathy_connectivity_dup_singleton (); + use_conn_notify_cb (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, + connectivity); + empathy_conf_notify_add (empathy_conf_get (), EMPATHY_PREFS_USE_CONN, + use_conn_notify_cb, connectivity); + + /* Autoconnect */ + empathy_conf_get_bool (empathy_conf_get (), + EMPATHY_PREFS_AUTOCONNECT, &autoconnect); + if (autoconnect && !no_connect && + tp_connection_presence_type_cmp_availability + (empathy_idle_get_state (idle), TP_CONNECTION_PRESENCE_TYPE_OFFLINE) + <= 0) + empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE); + + /* account management */ + account_manager = empathy_account_manager_dup_singleton (); + g_signal_connect (account_manager, "notify::ready", + G_CALLBACK (account_manager_ready_cb), NULL); + + migrate_config_to_xdg_dir (); + + /* Setting up UI */ + window = empathy_main_window_show (); + icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list); + + g_signal_connect (unique_app, "message-received", + G_CALLBACK (unique_app_message_cb), window); + + /* Handle channels */ + dispatcher = empathy_dispatcher_dup_singleton (); + g_signal_connect (dispatcher, "dispatch", G_CALLBACK (dispatch_cb), NULL); + + /* Logging */ + log_manager = empathy_log_manager_dup_singleton (); + empathy_log_manager_observe (log_manager, dispatcher); + + chatroom_manager = empathy_chatroom_manager_dup_singleton (NULL); + empathy_chatroom_manager_observe (chatroom_manager, dispatcher); + + notify_init (_(PACKAGE_NAME)); + /* Create the call factory */ + call_factory = empathy_call_factory_initialise (); + g_signal_connect (G_OBJECT (call_factory), "new-call-handler", + G_CALLBACK (new_call_handler_cb), NULL); + /* Create the FT factory */ + ft_factory = empathy_ft_factory_dup_singleton (); + g_signal_connect (ft_factory, "new-ft-handler", + G_CALLBACK (new_ft_handler_cb), NULL); + g_signal_connect (ft_factory, "new-incoming-transfer", + G_CALLBACK (new_incoming_transfer_cb), NULL); + + /* Location mananger */ #if HAVE_GEOCLUE - location_manager = empathy_location_manager_dup_singleton (); + location_manager = empathy_location_manager_dup_singleton (); #endif - gtk_main (); + gtk_main (); - empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE); + empathy_idle_set_state (idle, TP_CONNECTION_PRESENCE_TYPE_OFFLINE); - g_object_unref (mc); - g_object_unref (idle); - g_object_unref (connectivity); - g_object_unref (icon); - g_object_unref (log_manager); - g_object_unref (dispatcher); - g_object_unref (chatroom_manager); + g_object_unref (idle); + g_object_unref (connectivity); + g_object_unref (icon); + g_object_unref (account_manager); + g_object_unref (log_manager); + g_object_unref (dispatcher); + g_object_unref (chatroom_manager); #if HAVE_GEOCLUE - g_object_unref (location_manager); + g_object_unref (location_manager); #endif - g_object_unref (ft_factory); + g_object_unref (ft_factory); + g_object_unref (unique_app); - notify_uninit (); + notify_uninit (); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } - diff --git a/tests/.gitignore b/tests/.gitignore index eac793465..a522514bd 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -4,6 +4,7 @@ contact-run-until-ready contact-run-until-ready-2 *.log empetit +test-empathy-account-assistant test-empathy-presence-chooser test-empathy-status-preset-dialog -test-empathy-profile-chooser +test-empathy-protocol-chooser diff --git a/tests/Makefile.am b/tests/Makefile.am index f96650e79..8832181dd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,15 +25,25 @@ LDADD = \ noinst_PROGRAMS = \ contact-manager \ empetit \ + test-empathy-account-assistant \ test-empathy-presence-chooser \ test-empathy-status-preset-dialog \ - test-empathy-profile-chooser + test-empathy-protocol-chooser contact_manager_SOURCES = contact-manager.c empetit_SOURCES = empetit.c test_empathy_presence_chooser_SOURCES = test-empathy-presence-chooser.c test_empathy_status_preset_dialog_SOURCES = test-empathy-status-preset-dialog.c -test_empathy_profile_chooser_SOURCES = test-empathy-profile-chooser.c +test_empathy_protocol_chooser_SOURCES = test-empathy-protocol-chooser.c +test_empathy_account_assistant_SOURCES = test-empathy-account-assistant.c + +test_empathy_account_assistant_CFLAGS = -I$(top_srcdir)/src +test_empathy_account_assistant_LDADD = \ + $(top_builddir)/src/empathy-account-assistant.o \ + $(top_builddir)/src/empathy-import-utils.o \ + $(top_builddir)/src/empathy-import-pidgin.o \ + $(top_builddir)/src/empathy-import-widget.o \ + $(LDADD) check_PROGRAMS = check-main TESTS = check-main diff --git a/tests/check-empathy-chatroom-manager.c b/tests/check-empathy-chatroom-manager.c index 1c0f924a2..5a3384fe4 100644 --- a/tests/check-empathy-chatroom-manager.c +++ b/tests/check-empathy-chatroom-manager.c @@ -18,6 +18,7 @@ #define CHATROOM_SAMPLE "chatrooms-sample.xml" #define CHATROOM_FILE "chatrooms.xml" +#if 0 static void check_chatroom (EmpathyChatroom *chatroom, const gchar *name, @@ -384,15 +385,18 @@ START_TEST (test_empathy_chatroom_manager_change_chatroom) g_object_unref (account_manager); } END_TEST +#endif TCase * make_empathy_chatroom_manager_tcase (void) { TCase *tc = tcase_create ("empathy-chatroom-manager"); + /* tcase_add_test (tc, test_empathy_chatroom_manager_dup_singleton); tcase_add_test (tc, test_empathy_chatroom_manager_add); tcase_add_test (tc, test_empathy_chatroom_manager_remove); tcase_add_test (tc, test_empathy_chatroom_manager_change_favorite); tcase_add_test (tc, test_empathy_chatroom_manager_change_chatroom); + */ return tc; } diff --git a/tests/check-empathy-chatroom.c b/tests/check-empathy-chatroom.c index f2110a8f8..4d0b7e1ee 100644 --- a/tests/check-empathy-chatroom.c +++ b/tests/check-empathy-chatroom.c @@ -9,6 +9,7 @@ #include <libempathy/empathy-chatroom.h> +#if 0 static EmpathyChatroom * create_chatroom (void) { @@ -143,13 +144,16 @@ START_TEST (test_change_favorite) fail_if (!changed); } END_TEST +#endif TCase * make_empathy_chatroom_tcase (void) { TCase *tc = tcase_create ("empathy-chatroom"); + /* tcase_add_test (tc, test_empathy_chatroom_new); tcase_add_test (tc, test_favorite_and_auto_connect); tcase_add_test (tc, test_change_favorite); + */ return tc; } diff --git a/tests/check-empathy-helpers.c b/tests/check-empathy-helpers.c index c77cf9b75..5fb8b4a35 100644 --- a/tests/check-empathy-helpers.c +++ b/tests/check-empathy-helpers.c @@ -65,6 +65,7 @@ copy_xml_file (const gchar *orig, g_free (buffer); } +#if 0 EmpathyAccount * get_test_account (void) { @@ -79,7 +80,8 @@ get_test_account (void) if (g_list_length (accounts) == 0) { /* need to create a test account */ - account = empathy_account_manager_create (account_manager, profile); + account = empathy_account_manager_create_by_profile (account_manager, + profile); } else { @@ -165,3 +167,4 @@ destroy_test_account (EmpathyAccount *account) g_object_unref (account); g_object_unref (manager); } +#endif diff --git a/tests/test-empathy-account-assistant.c b/tests/test-empathy-account-assistant.c new file mode 100644 index 000000000..6d1330eeb --- /dev/null +++ b/tests/test-empathy-account-assistant.c @@ -0,0 +1,25 @@ +#include <config.h> + +#include <gtk/gtk.h> + +#include <libempathy-gtk/empathy-ui-utils.h> +#include "empathy-account-assistant.h" + +int main (int argc, char **argv) +{ + GtkWidget *assistant; + + gtk_init (&argc, &argv); + empathy_gtk_init (); + + assistant = empathy_account_assistant_new (NULL); + + gtk_widget_show_all (assistant); + + g_signal_connect_swapped (assistant, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_main (); + + return 0; +} diff --git a/tests/test-empathy-profile-chooser.c b/tests/test-empathy-protocol-chooser.c index 9078bbde4..90b1797a3 100644 --- a/tests/test-empathy-profile-chooser.c +++ b/tests/test-empathy-protocol-chooser.c @@ -3,21 +3,21 @@ #include <gtk/gtk.h> #include <libempathy-gtk/empathy-ui-utils.h> -#include <libempathy-gtk/empathy-profile-chooser.h> +#include <libempathy-gtk/empathy-protocol-chooser.h> int main (int argc, char **argv) { - GtkWidget *window; - GtkWidget *chooser; + GtkWidget *window, *c; gtk_init (&argc, &argv); empathy_gtk_init (); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - chooser = empathy_profile_chooser_new (); - gtk_container_add (GTK_CONTAINER (window), chooser); + c = empathy_protocol_chooser_new (); + + gtk_container_add (GTK_CONTAINER (window), c); /* gtk_window_set_default_size (GTK_WINDOW (window), 150, -1);*/ gtk_widget_show_all (window); |